def parse(doc: Dict[str, Any]) -> Dict[str, Any]:
    """
    To parse the "info" block and create Hydra Doc
    :param doc: the open api documentation
    :return:  hydra doc created
    """
    definitionSet = set()  # type: Set[str]
    info = try_catch_replacement(doc, "info", "")
    global_ = dict()
    global_["class_names"] = definitionSet
    global_["doc"] = doc

    if info != "":
        desc = try_catch_replacement(info, "description", "not defined")
        title = try_catch_replacement(info, "title", "not defined")
    else:
        desc = "not defined"
        title = "not defined"
        print("Desc and title not present hence exit")
        sys.exit()
    baseURL = try_catch_replacement(doc, "host", "localhost")
    name = try_catch_replacement(doc, "basePath", "api")
    schemes = try_catch_replacement(doc, "schemes", "http")
    api_doc = HydraDoc(name, title, desc, name,
                       "{}://{}".format(schemes[0], baseURL))
    get_paths(global_)
    for name in global_["class_names"]:
        for prop in global_[name]["prop_definition"]:
            global_[name]["class_definition"].add_supported_prop(prop)
        for op in global_[name]["op_definition"]:
            global_[name]["class_definition"].add_supported_op(op)
        if global_[name]["collection"] is True:
            if global_[name]["class_definition"].endpoint is True:
                global_[name]["class_definition"].endpoint = False

        api_doc.add_supported_class(
            global_[name]["class_definition"],
            global_[name]["collection"],
            collection_path=global_[name]["path"])

    generateEntrypoint(api_doc)
    hydra_doc = api_doc.generate()

    return hydra_doc
Exemplo n.º 2
0
def get_classes(apidoc: HydraDoc) -> List[Dict[str, Any]]:
    """Get all the classes in the APIDocumentation."""
    COLLECTION_ID = "http://www.w3.org/ns/hydra/core#Collection"
    RESOURCE_ID = "http://www.w3.org/ns/hydra/core#Resource"
    ENTRYPOINT_ID = apidoc.entrypoint.entrypoint.id_
    classes = []
    for class_ in apidoc.generate()["supportedClass"]:
        if class_["@id"] not in [COLLECTION_ID, RESOURCE_ID, ENTRYPOINT_ID]:
            classes.append(class_)
    # print(classes)
    return classes
def generateEntrypoint(api_doc: HydraDoc) -> None:
    """
    Generates Entrypoint ,
    Base Collection and Base Resource for the documentation
    :param api_doc: contains the Hydra Doc created
    """
    api_doc.add_baseCollection()
    api_doc.add_baseResource()
    api_doc.gen_EntryPoint()
Exemplo n.º 4
0
"""Sample to create Hydra APIDocumentation using doc_writer."""

from hydra_python_core.doc_writer import (HydraDoc, HydraClass, HydraClassProp,
                                          HydraClassOp, HydraStatus, HydraLink,
                                          HydraCollection)
from typing import Any, Dict, Union

# Creating the HydraDoc object, this is the primary class for the Doc
API_NAME = "api"  # Name of the API, will serve as EntryPoint
BASE_URL = "http://hydrus.com/"  # The base url at which the API is hosted
# NOTE: The API will be accessible at BASE_URL + ENTRY_POINT
# (http://hydrus.com/api)
# Create ApiDoc Object
api_doc = HydraDoc(API_NAME, "Title for the API Documentation",
                   "Description for the API Documentation", API_NAME, BASE_URL,
                   "vocab")

# Creating classes for the API
class_title = "dummyClass"  # Title of the Class
class_description = "A dummyClass for demo"  # Description of the class
class_ = HydraClass(class_title, class_description, endpoint=False)

# Class with single instance

class_2_title = "singleClass"
class_2_description = "A non collection class"
class_2 = HydraClass(class_2_title, class_2_description, endpoint=True)

# Another class with single instance, will be used as nested class

class_1_title = "anotherSingleClass"
def doc_gen(API, BASE_URL):
    """Generate API Doc for server."""
    # Main API Doc
    api_doc = HydraDoc(API, "API Doc for the server side API",
                       "API Documentation for the server side system", API,
                       BASE_URL)

    # State Class
    state = HydraClass("State", "State", "Class for drone state objects")
    # Properties
    # Status include Active, Inactive, Off, Charging
    state.add_supported_prop(
        HydraClassProp("http://auto.schema.org/speed", "Speed", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "Position", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/Property", "Direction", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/fuelCapacity", "Battery", False,
                       False, True))
    state.add_supported_prop(
        HydraClassProp("https://schema.org/status", "Status", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))

    state.add_supported_op(
        HydraClassOp("GetState", "GET", None, "vocab:State",
                     [{
                         "statusCode": 404,
                         "description": "State not found"
                     }, {
                         "statusCode": 200,
                         "description": "State Returned"
                     }]))

    # Drone Class
    drone = HydraClass("Drone", "Drone", "Class for a drone")
    # Properties
    drone.add_supported_prop(
        HydraClassProp("vocab:State", "State", False, False, True))
    drone.add_supported_prop(
        HydraClassProp("http://schema.org/name", "name", False, False, True))
    drone.add_supported_prop(
        HydraClassProp("http://schema.org/model", "model", False, False, True))
    drone.add_supported_prop(
        HydraClassProp("http://auto.schema.org/speed", "MaxSpeed", False,
                       False, True))
    drone.add_supported_prop(
        HydraClassProp("http://schema.org/device", "Sensor", False, False,
                       True))
    # Operations
    # Drones will submit their state to the server at certain intervals or when some event happens
    drone.add_supported_op(
        HydraClassOp("SubmitDrone", "POST", "vocab:Drone", None,
                     [{
                         "statusCode": 200,
                         "description": "Drone updated"
                     }]))

    drone.add_supported_op(
        HydraClassOp("UpdateDrone", "PUT", "vocab:Drone", None,
                     [{
                         "statusCode": 200,
                         "description": "Drone updated"
                     }]))
    # Mechanics or GUI need to get the drone, it contains the state object of the drone already.
    drone.add_supported_op(
        HydraClassOp("GetDrone", "GET", None, "vocab:Drone",
                     [{
                         "statusCode": 404,
                         "description": "Drone not found"
                     }, {
                         "statusCode": 200,
                         "description": "Drone Returned"
                     }]))
    drone.add_supported_op(
        HydraClassOp("DeleteDrone", "DELETE", None, None,
                     [{
                         "statusCode": 404,
                         "description": "Drone not found"
                     }, {
                         "statusCode": 200,
                         "description": "Drone successfully deleted."
                     }]))

    # NOTE: Commands are stored in a collection. You may GET a command or you may DELETE it, there is not UPDATE.
    command = HydraClass("Command", "Command", "Class for drone commands")
    command.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    command.add_supported_prop(
        HydraClassProp("vocab:State", "State", False, False, True))
    # Used by mechanics to get newly added commands
    command.add_supported_op(
        HydraClassOp("GetCommand", "GET", None, "vocab:Command",
                     [{
                         "statusCode": 404,
                         "description": "Command not found"
                     }, {
                         "statusCode": 200,
                         "description": "Command Returned"
                     }]))
    # Used by server to add new commands
    command.add_supported_op(
        HydraClassOp("AddCommand", "PUT", "vocab:Command", None,
                     [{
                         "statusCode": 201,
                         "description": "Command added"
                     }]))

    # Data is stored as a collection. Each data object can be read.
    # New data added to the collection
    datastream = HydraClass("Datastream", "Datastream",
                            "Class for a datastream entry")
    datastream.add_supported_prop(
        HydraClassProp("http://schema.org/QuantitativeValue", "Temperature",
                       False, False, True))
    datastream.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    datastream.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "Position", False, False,
                       True))
    datastream.add_supported_op(
        HydraClassOp("ReadDatastream", "GET", None, "vocab:Datastream",
                     [{
                         "statusCode": 404,
                         "description": "Data not found"
                     }, {
                         "statusCode": 200,
                         "description": "Data returned"
                     }]))

    dronelog = HydraClass("DroneLog", "DroneLog",
                          "Class for a drone log entry")
    dronelog.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    dronelog.add_supported_prop(
        HydraClassProp("http://schema.org/Text", "LogString", False, False,
                       True))
    dronelog.add_supported_op(
        HydraClassOp("ReadDroneLog", "GET", None, "vocab:DroneLog",
                     [{
                         "statusCode": 404,
                         "description": "DroneLog not found"
                     }, {
                         "statusCode": 200,
                         "description": "DroneLog returned"
                     }]))

    controllerlog = HydraClass("ControllerLog", "ControllerLog",
                               "Class for a controller log entry")
    controllerlog.add_supported_prop(
        HydraClassProp("http://schema.org/Text", "LogString", False, False,
                       True))
    controllerlog.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    controllerlog.add_supported_op(
        HydraClassOp("ReadControllerLog", "GET", None, "vocab:ControllerLog",
                     [{
                         "statusCode": 404,
                         "description": "ControllerLog not found"
                     }, {
                         "statusCode": 200,
                         "description": "ControllerLog returned"
                     }]))

    httpapilog = HydraClass("HttpApiLog", "HttpApiLog",
                            "Class for a http api log entry")
    httpapilog.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "Subject", False, False,
                       True))
    httpapilog.add_supported_prop(
        HydraClassProp("http://schema.org/Action", "Predicate", False, False,
                       True))
    httpapilog.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "Object", False, False,
                       True))
    httpapilog.add_supported_op(
        HydraClassOp("ReadHttpApiLog", "GET", None, "vocab:HttpApiLog",
                     [{
                         "statusCode": 404,
                         "description": "HttpApiLog not found"
                     }, {
                         "statusCode": 200,
                         "description": "HttpApiLog returned"
                     }]))

    # Single object representing the area of interest. No collections.
    location = HydraClass("Location",
                          "Location",
                          "Class for location of the central controller.",
                          endpoint=True)
    # Using two positions to have a bounding box
    location.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "Location", False, False,
                       True))
    # Allowing updation of the area of interest
    location.add_supported_op(
        HydraClassOp(
            "UpdateLocation", "POST", "vocab:Location", None,
            [{
                "statusCode": 200,
                "description": "Controller location updated successfully."
            }]))
    location.add_supported_op(
        HydraClassOp(
            "AddLocation", "PUT", "vocab:Location", None,
            [{
                "statusCode": 200,
                "description": "Controller location added successfully."
            }]))
    location.add_supported_op(
        HydraClassOp("GetLocation", "GET", None, "vocab:Location",
                     [{
                         "statusCode": 404,
                         "description": "Location of Controller not found."
                     }, {
                         "statusCode": 200,
                         "description": "Location of controller returned."
                     }]))

    message = HydraClass("Message", "Message",
                         "Class for messages received by the GUI interface")
    message.add_supported_prop(
        HydraClassProp("http://schema.org/Text", "MessageString", False, False,
                       True))
    message.add_supported_op(
        HydraClassOp("GetMessage", "GET", None, "vocab:Message",
                     [{
                         "statusCode": 404,
                         "description": "Message not found"
                     }, {
                         "statusCode": 200,
                         "description": "Message returned"
                     }]))
    message.add_supported_op(
        HydraClassOp("DeleteMessage", "DELETE", None, None,
                     [{
                         "statusCode": 404,
                         "description": "Message not found"
                     }, {
                         "statusCode": 200,
                         "description": "Message successfully deleted."
                     }]))

    anomaly = HydraClass(
        "Anomaly", "Anomaly",
        "Class for Temperature anomalies that need to be confirmed")
    anomaly.add_supported_prop(
        HydraClassProp("vocab:Location", "Location", False, False, True))
    anomaly.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    # Status of any anomaly can be ["Positive", "Negative", "Confirming", "To be confirmed"]
    anomaly.add_supported_prop(
        HydraClassProp("http://schema.org/eventStatus", "Status", False, False,
                       True))
    anomaly.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "AnomalyID", False,
                       False, True))

    anomaly.add_supported_op(
        HydraClassOp("GetAnomaly", "GET", None, "vocab:Anomaly",
                     [{
                         "statusCode": 404,
                         "description": "Anomaly not found"
                     }, {
                         "statusCode": 200,
                         "description": "Anomaly returned"
                     }]))
    anomaly.add_supported_op(
        HydraClassOp("AddAnomaly", "PUT", "vocab:Anomaly", None,
                     [{
                         "statusCode": 200,
                         "description": "Anomaly added successfully."
                     }]))
    anomaly.add_supported_op(
        HydraClassOp("UpdateAnomaly", "POST", "vocab:Anomaly", None,
                     [{
                         "statusCode": 201,
                         "description": "Anomaly updated successfully."
                     }]))
    anomaly.add_supported_op(
        HydraClassOp("DeleteAnomaly", "DELETE", None, None,
                     [{
                         "statusCode": 404,
                         "description": "Anomaly not found"
                     }, {
                         "statusCode": 200,
                         "description": "Anomaly successfully deleted."
                     }]))

    api_doc.add_supported_class(drone, collection=True)
    api_doc.add_supported_class(state, collection=True)
    api_doc.add_supported_class(datastream, collection=True)
    api_doc.add_supported_class(dronelog, collection=True)
    api_doc.add_supported_class(controllerlog, collection=True)
    api_doc.add_supported_class(httpapilog, collection=True)
    api_doc.add_supported_class(location, collection=False)
    api_doc.add_supported_class(command, collection=True)
    api_doc.add_supported_class(message, collection=True)
    api_doc.add_supported_class(anomaly, collection=True)

    api_doc.add_baseResource()
    api_doc.add_baseCollection()
    api_doc.gen_EntryPoint()
    return api_doc
Exemplo n.º 6
0
"""Sample to create Hydra APIDocumentation using doc_writer."""

from hydra_python_core.doc_writer import HydraDoc, HydraClass, HydraClassProp, HydraClassOp
from typing import Any, Dict, Union

# Creating the HydraDoc object, this is the primary class for the Doc
API_NAME = "api"  # Name of the API, will serve as EntryPoint
BASE_URL = "https://hydrus.com/"  # The base url at which the API is hosted
# NOTE: The API will be accessible at BASE_URL + ENTRY_POINT
# (http://hydrus.com/api/)

# Create ApiDoc Object
api_doc = HydraDoc(API_NAME, "Title for the API Documentation",
                   "Description for the API Documentation", API_NAME, BASE_URL)

# Creating classes for the API
class_uri = "dummyClass"  # URI of class for the HydraClass
class_title = "dummyClass"  # Title of the Class
class_description = "A dummyClass for demo"  # Description of the class
class_ = HydraClass(class_uri, class_title, class_description, endpoint=False)

# Class with single instance
class_2_uri = "singleClass"
class_2_title = "singleClass"
class_2_description = "A non collection class"
class_2 = HydraClass(class_2_uri,
                     class_2_title,
                     class_2_description,
                     endpoint=True)

# Another class with single instance, will be used as nested class
Exemplo n.º 7
0
def create_doc(doc: Dict[str, Any],
               HYDRUS_SERVER_URL: str = None,
               API_NAME: str = None) -> HydraDoc:
    """
    Create the HydraDoc object from the API Documentation.

    :param doc: dictionary of hydra api doc
    :param HYDRUS_SERVER_URL: url of the hydrus server
    :param API_NAME: name of the api
    :return: instance of HydraDoc which server and agent can understand
    :raise SyntaxError: If the `doc` doesn't have an entry for `@id` , `@context`, `@type` key.
    """

    # These keys must be there in the APIDOC: @context, @id, @type
    if not all(key in doc for key in ('@context', '@id', '@type')):
        raise SyntaxError(
            "Please make sure doc contains @context, @id and @type")

    _context = doc['@context']
    base_url = ''
    entrypoint = ''
    doc_name = 'vocab'
    doc_url = ''
    _id = ''
    _entrypoint = ''
    _title = "The default title"
    _description = "This is the default description"
    _classes = []
    _collections = []
    _endpoints = []
    _possible_status = []
    _endpoint_class = []
    _endpoint_collection = []
    _non_endpoint_classes = []

    expanded_doc = jsonld.expand(doc)
    for item in expanded_doc:
        _id = item['@id']
        # Extract base_url, entrypoint and API name
        base_url = urlparse(_id).scheme + '//' + urlparse(_id).netloc
        entrypoint = _entrypoint
        doc_name = urlparse(_id).path.split('/')[-1]
        doc_url = DocUrl(HYDRUS_SERVER_URL,
                         api_name=API_NAME,
                         doc_name=doc_name).doc_url
        for entrypoint in item[hydra['entrypoint']]:
            _entrypoint = entrypoint['@id']
        if hydra['title'] in item:
            for title in item[hydra['title']]:
                _title = title['@value']
        if hydra['description'] in item:
            for description in item[hydra['description']]:
                _description = description['@value']
        for classes in item[hydra['supportedClass']]:
            isCollection = False
            if hydra['manages'] in classes:
                isCollection = True
                _collections.append(classes)
            for supported_prop in classes[hydra['supportedProperty']]:
                for prop in supported_prop[hydra['property']]:
                    if '@type' in prop:
                        for prop_type in prop['@type']:
                            if prop_type == hydra['Link']:
                                # find the range of the link
                                for resource_range in prop[rdfs['range']]:
                                    _endpoints.append(
                                        check_namespace(resource_range['@id']))
            if not isCollection:
                _classes.append(classes)
        for status in item[hydra['possibleStatus']]:
            _possible_status.append(status)
    for classes in _classes:
        if classes['@id'] == hydra['Resource'] or classes['@id'] == hydra[
                'Collection']:
            continue
        endpoint = False
        if classes['@id'].find("EntryPoint") != -1:
            classes['@id'] = "{}{}".format(doc_url, "EntryPoint")
        else:
            classes['@id'] = check_namespace(classes['@id'])
        for endpoints in _endpoints:
            if classes['@id'] == endpoints:
                endpoint = True
                _endpoint_class.append(classes)
        if not endpoint:
            _non_endpoint_classes.append(classes)

    for collections in _collections:
        collections['@id'] = check_namespace(collections['@id'])
        for endpoints in _endpoints:
            if collections['@id'] == endpoints:
                _endpoint_collection.append(collections)
    # Main doc object
    if HYDRUS_SERVER_URL is not None and API_NAME is not None:
        apidoc = HydraDoc(API_NAME, _title, _description, API_NAME,
                          HYDRUS_SERVER_URL, doc_name)
    else:
        apidoc = HydraDoc(entrypoint, _title, _description, entrypoint,
                          base_url, doc_name)

    # additional context entries
    for entry in _context:
        apidoc.add_to_context(entry, _context[entry])

    # make endpoint classes
    for endpoint_classes in _endpoint_class:
        if endpoint_classes['@id'] == hydra['Resource'] or endpoint_classes['@id'] == hydra['Collection'] or \
                endpoint_classes['@id'].find("EntryPoint") != -1:
            continue
        class_ = create_class(endpoint_classes, endpoint=True)
        apidoc.add_supported_class(class_)

    # make non-endpoint classes
    for classes in _non_endpoint_classes:
        if classes['@id'] == hydra['Resource'] or classes['@id'] == hydra['Collection'] or \
                classes['@id'].find("EntryPoint") != -1:
            continue
        class_ = create_class(classes, endpoint=False)
        apidoc.add_supported_class(class_)

    # make endpoint collections
    for endpoint_collection in _endpoint_collection:
        collection_ = create_collection(endpoint_collection)
        apidoc.add_supported_collection(collection_)

    # add possibleStatus
    status_list = create_status(_possible_status)
    for status in status_list:
        apidoc.add_possible_status(status)

    # add base collection and resource
    apidoc.add_baseResource()
    apidoc.add_baseCollection()
    apidoc.gen_EntryPoint()
    return apidoc
Exemplo n.º 8
0
def create_doc(doc: Dict[str, Any],
               HYDRUS_SERVER_URL: str = None,
               API_NAME: str = None) -> HydraDoc:
    """Create the HydraDoc object from the API Documentation.

    Raises:
        SyntaxError: If the `doc` doesn't have an entry for `@id` key.
        SyntaxError: If the `@id` key of the `doc` is not of
            the form : '[protocol] :// [base url] / [entrypoint] / vocab'

    """
    # Check @id
    try:
        id_ = doc["@id"]
    except KeyError:
        raise SyntaxError("The API Documentation must have [@id]")

    # Extract base_url, entrypoint and API name
    match_obj = re.match(r'(.*)://(.*)/(.*)/vocab#?', id_, re.M | re.I)
    if match_obj:
        base_url = "{0}://{1}/".format(match_obj.group(1), match_obj.group(2))
        entrypoint = match_obj.group(3)

    # Syntax checks
    else:
        raise SyntaxError(
            "The '@id' of the Documentation must be of the form:\n"
            "'[protocol] :// [base url] / [entrypoint] / vocab'")
    doc_keys = {
        "description": False,
        "title": False,
        "supportedClass": False,
        "@context": False,
        "possibleStatus": False
    }
    result = {}
    for k, literal in doc_keys.items():
        result[k] = input_key_check(doc, k, "doc", literal)

    # EntryPoint object
    # getEntrypoint checks if all classes have @id
    entrypoint_obj = get_entrypoint(doc)

    # Main doc object
    if HYDRUS_SERVER_URL is not None and API_NAME is not None:
        apidoc = HydraDoc(API_NAME, result["title"], result["description"],
                          API_NAME, HYDRUS_SERVER_URL)
    else:
        apidoc = HydraDoc(entrypoint, result["title"], result["description"],
                          entrypoint, base_url)

    # additional context entries
    for entry in result["@context"]:
        apidoc.add_to_context(entry, result["@context"][entry])

    # add all parsed_classes
    for class_ in result["supportedClass"]:
        class_obj, collection, collection_path = create_class(
            entrypoint_obj, class_)
        if class_obj:
            apidoc.add_supported_class(class_obj,
                                       collection=collection,
                                       collection_path=collection_path)

    # add possibleStatus
    for status in result["possibleStatus"]:
        status_obj = create_status(status)
        apidoc.add_possible_status(status_obj)

    apidoc.add_baseResource()
    apidoc.add_baseCollection()
    apidoc.gen_EntryPoint()
    return apidoc
Exemplo n.º 9
0
def doc_gen(API: str, BASE_URL: str) -> HydraDoc:
    """Generate API Doc for server."""
    # Main API Doc
    api_doc = HydraDoc(API, "API Doc for the server side API",
                       "API Documentation for the server side system", API,
                       BASE_URL)

    # State Class
    state = HydraClass("State", "State", "Class for drone state objects")
    # Properties
    state.add_supported_prop(
        HydraClassProp("http://auto.schema.org/speed", "Speed", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "Position", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/Property", "Direction", False, False,
                       True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/fuelCapacity", "Battery", False,
                       False, True))
    state.add_supported_prop(
        HydraClassProp("https://schema.org/status", "SensorStatus", False,
                       False, True))
    state.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    # Operations
    state.add_supported_op(
        HydraClassOp("GetState", "GET", None, "vocab:State",
                     [{
                         "statusCode": 404,
                         "description": "State not found"
                     }, {
                         "statusCode": 200,
                         "description": "State Returned"
                     }]))

    # Drone Class
    drone = HydraClass("Drone", "Drone", "Class for a drone")
    # Properties
    drone.add_supported_prop(
        HydraClassProp("vocab:State", "DroneState", False, False, True))
    drone.add_supported_prop(
        HydraClassProp("http://schema.org/name", "name", False, False, True))
    drone.add_supported_prop(
        HydraClassProp("http://schema.org/model", "model", False, False, True))
    drone.add_supported_prop(
        HydraClassProp("http://auto.schema.org/speed", "MaxSpeed", False,
                       False, True))
    drone.add_supported_prop(
        HydraClassProp("http://schema.org/device", "Sensor", False, False,
                       True))
    # Operations
    # Drones will submit their state to the server at certain intervals or
    # when some event happens
    drone.add_supported_op(
        HydraClassOp("SubmitDrone", "POST", "vocab:Drone", None,
                     [{
                         "statusCode": 200,
                         "description": "Drone updated"
                     }]))
    drone.add_supported_op(
        HydraClassOp("CreateDrone", "PUT", "vocab:Drone", None,
                     [{
                         "statusCode": 200,
                         "description": "Drone added"
                     }]))
    drone.add_supported_op(
        HydraClassOp("GetDrone", "GET", None, "vocab:Drone",
                     [{
                         "statusCode": 404,
                         "description": "Drone not found"
                     }, {
                         "statusCode": 200,
                         "description": "Drone Returned"
                     }]))

    # NOTE: Commands are stored in a collection. You may GET a command or you
    # may DELETE it, there is not UPDATE.
    command = HydraClass("Command", "Command", "Class for drone commands")
    command.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    command.add_supported_prop(
        HydraClassProp("vocab:State", "State", False, False, True))
    # Used by mechanics to get newly added commands
    command.add_supported_op(
        HydraClassOp("GetCommand", "GET", None, "vocab:Command",
                     [{
                         "statusCode": 404,
                         "description": "Command not found"
                     }, {
                         "statusCode": 200,
                         "description": "Command Returned"
                     }]))
    # Used by server to add new commands
    command.add_supported_op(
        HydraClassOp("AddCommand", "PUT", "vocab:Command", None,
                     [{
                         "statusCode": 201,
                         "description": "Command added"
                     }]))

    command.add_supported_op(
        HydraClassOp("DeleteCommand", "DELETE", None, None,
                     [{
                         "statusCode": 201,
                         "description": "Command deleted"
                     }]))

    # Logs to be accessed mostly by the GUI. Mechanics should add logs for
    # every event.
    log = HydraClass("LogEntry", "LogEntry", "Class for a log entry")
    # Subject
    log.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", True, True,
                       False))
    # Predicate
    log.add_supported_prop(
        HydraClassProp("http://schema.org/UpdateAction", "Update", False, True,
                       False))
    log.add_supported_prop(
        HydraClassProp("http://schema.org/ReplyAction", "Get", False, True,
                       False))
    log.add_supported_prop(
        HydraClassProp("http://schema.org/SendAction", "Send", False, True,
                       False))
    # Objects
    log.add_supported_prop(
        HydraClassProp("vocab:State", "State", False, True, False))
    log.add_supported_prop(
        HydraClassProp("vocab:Datastream", "Data", False, True, False))
    log.add_supported_prop(
        HydraClassProp("vocab:Command", "Command", False, True, False))
    # GUI will get a certain log entry.
    log.add_supported_op(
        HydraClassOp("GetLog", "GET", None, "vocab:LogEntry",
                     [{
                         "statusCode": 404,
                         "description": "Log entry not found"
                     }, {
                         "statusCode": 200,
                         "description": "Log entry returned"
                     }]))
    log.add_supported_op(
        HydraClassOp("AddLog", "PUT", "vocab:LogEntry", None,
                     [{
                         "statusCode": 201,
                         "description": "Log entry created"
                     }]))

    # Data is stored as a collection. Each data object can be read.
    # New data added to the collection
    datastream = HydraClass("Datastream", "Datastream",
                            "Class for a datastream entry")
    datastream.add_supported_prop(
        HydraClassProp("http://schema.org/QuantitativeValue", "Temperature",
                       False, False, True))
    datastream.add_supported_prop(
        HydraClassProp("http://schema.org/identifier", "DroneID", False, False,
                       True))
    datastream.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "Position", False, False,
                       True))
    datastream.add_supported_op(
        HydraClassOp("ReadDatastream", "GET", None, "vocab:Datastream",
                     [{
                         "statusCode": 404,
                         "description": "Data not found"
                     }, {
                         "statusCode": 200,
                         "description": "Data returned"
                     }]))
    datastream.add_supported_op(
        HydraClassOp("UpdateDatastream", "POST", "vocab:Datastream", None,
                     [{
                         "statusCode": 200,
                         "description": "Data updated"
                     }]))
    datastream.add_supported_op(
        HydraClassOp("DeleteDatastream", "DELETE", None, None,
                     [{
                         "statusCode": 200,
                         "description": "Data deleted"
                     }]))

    # Single object representing the area of interest. No collections.
    area = HydraClass("Area",
                      "Area",
                      "Class for Area of Interest of the server",
                      endpoint=True)
    # Using two positions to have a bounding box
    area.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "TopLeft", False, False, True))
    area.add_supported_prop(
        HydraClassProp("http://schema.org/geo", "BottomRight", False, False,
                       True))
    # Allowing updation of the area of interest
    area.add_supported_op(
        HydraClassOp("UpdateArea", "POST", "vocab:Area", None,
                     [{
                         "statusCode": 200,
                         "description": "Area of interest changed"
                     }]))
    area.add_supported_op(
        HydraClassOp("GetArea", "GET", None, "vocab:Area",
                     [{
                         "statusCode": 404,
                         "description": "Area of interest not found"
                     }, {
                         "statusCode": 200,
                         "description": "Area of interest returned"
                     }]))

    message = HydraClass("Message", "Message",
                         "Class for messages received by the GUI interface")
    message.add_supported_prop(
        HydraClassProp("http://schema.org/Text", "MessageString", False, False,
                       True))
    message.add_supported_op(
        HydraClassOp("GetMessage", "GET", None, "vocab:Message",
                     [{
                         "statusCode": 404,
                         "description": "Message not found"
                     }, {
                         "statusCode": 200,
                         "description": "Message returned"
                     }]))
    message.add_supported_op(
        HydraClassOp("DeleteMessage", "DELETE", None, None,
                     [{
                         "statusCode": 200,
                         "description": "Message deleted"
                     }]))

    api_doc.add_supported_class(drone, collection=True)
    api_doc.add_supported_class(state, collection=True)
    api_doc.add_supported_class(datastream, collection=True)
    api_doc.add_supported_class(log, collection=True)
    api_doc.add_supported_class(area, collection=False)
    api_doc.add_supported_class(command, collection=True)
    api_doc.add_supported_class(message, collection=True)

    api_doc.add_baseResource()
    api_doc.add_baseCollection()
    api_doc.gen_EntryPoint()
    return api_doc
Exemplo n.º 10
0
def doc_gen(API, BASE_URL):
    """Generate API Doc for drone."""
    # Main API Doc
    api_doc = HydraDoc(API,
                       "API Doc for the drone side API",
                       "API Documentation for the drone side system",
                       API,
                       BASE_URL)

    # State Class
    # NOTE: Each drone will have only one State Class, this can't be deleted. Only read and update.
    state = HydraClass("State", "State", "Class for drone state objects")
    # Properties
    state.add_supported_prop(HydraClassProp(
        "http://auto.schema.org/speed", "Speed", True, False, False))
    state.add_supported_prop(HydraClassProp(
        "http://schema.org/geo", "Position", True, False, False))
    state.add_supported_prop(HydraClassProp(
        "http://schema.org/Property", "Direction", True, False, False))
    state.add_supported_prop(HydraClassProp(
        "http://schema.org/fuelCapacity", "Battery", True, True, False))
    state.add_supported_prop(HydraClassProp(
        "https://schema.org/status", "Status", True, False, False))

    # Drone Class
    # NOTE: The actual changes to the drone are to be made at the /api/Drone URI.
    # GET will return current State. POST will update the State.
    drone = HydraClass("Drone", "Drone", "Class for a drone", endpoint=True)
    # Properties
    drone.add_supported_prop(HydraClassProp(
        "vocab:State", "State", False, False, True))
    drone.add_supported_prop(HydraClassProp(
        "http://schema.org/name", "name", False, False, True))
    drone.add_supported_prop(HydraClassProp(
        "http://schema.org/model", "model", False, False, True))
    drone.add_supported_prop(HydraClassProp(
        "http://auto.schema.org/speed", "MaxSpeed", False, False, True))
    drone.add_supported_prop(HydraClassProp(
        "http://schema.org/device", "Sensor", False, False, True))
    drone.add_supported_prop(HydraClassProp(
        "http://schema.org/identifier", "DroneID", False, False, True))
    # Operations
    drone.add_supported_op(HydraClassOp("GetDrone",
                                        "GET",
                                        None,
                                        "vocab:Drone",
                                        [{"statusCode": 404, "description": "Drone not found"},
                                         {"statusCode": 200, "description": "Drone returned"}]))
    # When new commands are issued, mechanics will need to change the state of the drone
    drone.add_supported_op(HydraClassOp("UpdateDrone",
                                        "POST",
                                        "vocab:Drone",
                                        None,
                                        [{"statusCode": 200, "description": "Drone updated"}]))
    drone.add_supported_op(HydraClassOp("AddDrone",
                                        "PUT",
                                        "vocab:Drone",
                                        None,
                                        [{"statusCode": 200, "description": "Drone added"}]))

    # Command Class
    # NOTE: Commands are stored in a collection. You may GET a command or you may DELETE it, there is not UPDATE.
    command = HydraClass("Command", "Command", "Class for drone commands")
    command.add_supported_prop(HydraClassProp(
        "http://schema.org/identifier", "DroneID", False, False, True))
    command.add_supported_prop(HydraClassProp(
        "vocab:State", "State", False, False, True))
    # Used by mechanics to get newly added commands
    command.add_supported_op(HydraClassOp("GetCommand",
                                          "GET",
                                          None,
                                          "vocab:Command",
                                          [{"statusCode": 404, "description": "Command not found"},
                                           {"statusCode": 200, "description": "Command Returned"}]))
    # Used by server to add new commands
    command.add_supported_op(HydraClassOp("AddCommand",
                                          "PUT",
                                          "vocab:Command",
                                          None,
                                          [{"statusCode": 201, "description": "Command added"}]))
    # Used by mechanics to delete command after it has been executed
    command.add_supported_op(HydraClassOp("DeleteCommand",
                                          "DELETE",
                                          None,
                                          None,
                                          [{"statusCode": 200, "description": "Command deleted"}]))

    # Datastream class
    # NOTE: This is for the Datastream to be captured/generated. The mechanics module will enter random data and POST it.
    # The server will read[GET] the data when it needs it. No need for collections. Only one instance showing current reading of sensor
    # The URI is /api/Datastream
    datastream = HydraClass("Datastream", "Datastream",
                            "Class for a data entry from drone sensors", endpoint=True)
    datastream.add_supported_prop(HydraClassProp(
        "http://schema.org/QuantitativeValue", "Temperature", False, False, True))
    datastream.add_supported_prop(HydraClassProp(
        "http://schema.org/identifier", "DroneID", False, False, True))
    datastream.add_supported_prop(HydraClassProp(
        "http://schema.org/geo", "Position", False, False, True))
    datastream.add_supported_op(HydraClassOp("GetDatastream",
                                             "GET",
                                             None,
                                             "vocab:Datastream",
                                             [{"statusCode": 404, "description": "Datastream not found"},
                                              {"statusCode": 200, "description": "Datastream returned"}]))
    datastream.add_supported_op(HydraClassOp("UpdateDatastream",
                                             "POST",
                                             "vocab:Datastream",
                                             None,
                                             [{"statusCode": 200, "description": "Datastream updated"}]))
    datastream.add_supported_op(HydraClassOp("AddDatastream",
                                             "PUT",
                                             "vocab:Datastream",
                                             None,
                                             [{"statusCode": 200, "description": "Datastream added"}]))

    anomaly = HydraClass(
        "Anomaly", "Anomaly", "Class for Temperature anomalies that need to be confirmed", endpoint=True)
    anomaly.add_supported_prop(HydraClassProp(
        "vocab:Location", "Location", False, False, True))
    anomaly.add_supported_prop(HydraClassProp(
        "http://schema.org/identifier", "DroneID", False, False, True))
    # Status of any anomaly can be ["Positive", "Negative", "Confirming"]
    anomaly.add_supported_prop(HydraClassProp(
        "http://schema.org/eventStatus", "Status", False, False, True))
    anomaly.add_supported_prop(HydraClassProp(
        "http://schema.org/identifier", "AnomalyID", False, False, True))
    anomaly.add_supported_op(HydraClassOp("GetAnomaly",
                                          "GET",
                                          None,
                                          "vocab:Anomaly",
                                          [{"statusCode": 404, "description": "Anomaly not found"},
                                           {"statusCode": 200, "description": "Anomaly returned"}]))
    anomaly.add_supported_op(HydraClassOp("AddAnomaly",
                                          "PUT",
                                          "vocab:Anomaly",
                                          None,
                                          [{"statusCode": 201, "description": "Anomaly added successfully"}]))
    anomaly.add_supported_op(HydraClassOp("UpdateAnomaly",
                                          "POST",
                                          "vocab:Anomaly",
                                          None,
                                          [{"statusCode": 201, "description": "Anomaly updated successfully"}]))

    api_doc.add_supported_class(state, collection=False)
    api_doc.add_supported_class(drone, collection=False)
    api_doc.add_supported_class(command, collection=True)
    api_doc.add_supported_class(datastream, collection=False)
    api_doc.add_supported_class(anomaly, collection=False)

    api_doc.add_baseCollection()
    api_doc.add_baseResource()
    api_doc.gen_EntryPoint()
    return api_doc