diff --git a/src/http/server.py b/src/http/server.py index 06ae4098e9c100241f9e8d4b4a0339ad2627c49a..a947643233b4f72a1e43458588e3fb6e9977007c 100644 --- a/src/http/server.py +++ b/src/http/server.py @@ -19,6 +19,7 @@ from ..soil.figure import Figure from ..soil.function import Function from ..soil.measurement import Measurement from ..soil.parameter import Parameter +from ..soil.semantics import Semantics from ..soil.stream import StreamScheduler from ..utils import root_logger from ..utils import serialize @@ -125,9 +126,8 @@ class HTTPServer(object): return queried_attributes def prepare_response(self, body: Union[Dict, rdflib.Graph], element: Element, status: int = 200, - query: MultiDict = None): + query: MultiDict = None, semantic: bool = False): dataformat = self._dataformat - semantic = False if query is not None and 'format' in query and query['format'] in ['json', 'xml', 'turtle']: dataformat = query['format'] if query is not None and 'semantic' in query and query['semantic'] in ['data', 'metadata', 'profile']: @@ -171,6 +171,7 @@ class HTTPServer(object): logger.info("GET Request from {}".format(request.url)) logger.debug('Request: {}'.format(request)) logger.debug('Query Parameters: {}'.format(request.query_string)) + splitted_request = HTTPServer.parse_uuids(request) keys = self._filter_query(request.query) # determine whether a semantic answer is expected @@ -178,14 +179,16 @@ class HTTPServer(object): if request.query is not None and 'semantic' in request.query and request.query['semantic'] in ['data', 'metadata', 'profile']: semantic = request.query['semantic'] - # retrieving the element - try: - item = self.root[HTTPServer.parse_uuids(request)] - except KeyError as e: - logger.error(traceback.format_exc()) - response = {'error': str(e)} - logger.error('Response: {}'.format(response)) - return self.prepare_response(response, None, status=404, query=request.query) + if len(splitted_request) > 0 and splitted_request[0] == Semantics.prefix: + item, semantic = self.root.resolve_semantic_path(splitted_request[1:]) + else: + try: + item = self.root[splitted_request] + except KeyError as e: + logger.error(traceback.format_exc()) + response = {'error': str(e)} + logger.error('Response: {}'.format(response)) + return self.prepare_response(response, None, status=404, query=request.query) # serializing the element try: @@ -200,7 +203,7 @@ class HTTPServer(object): response = {'error': str(e)} status = 500 logger.error('Response: {}'.format(response)) - return self.prepare_response(response, item, status=status, query=request.query) + return self.prepare_response(response, item, status=status, query=request.query, semantic=semantic is not None) async def post(self, request): logger.info("POST Request from {}".format(request.url)) diff --git a/src/soil/component.py b/src/soil/component.py index 77fdcdf08ad3e22d772870b6ce2dcd1253557318..4c507d6c40a95235c788832a99186f6dfc7e969f 100644 --- a/src/soil/component.py +++ b/src/soil/component.py @@ -393,3 +393,26 @@ class Component(Element): else: raise DeviceException('The provided kind of semantic information cannot be returned.') return result + + def resolve_semantic_path(self, path: List[str]): + if len(path) == 0: + raise ChildNotFoundException('Could not resolve the semantic path.') + + # first try to resolve whether it is a path to a profile + if path[0] == f'{self._profilename}Shape': + if len(path) == 1: + return self, 'profile' + else: + for child in self.children: + try: + return child.resolve_semantic_path(path) + except ChildNotFoundException: + continue + + # TODO resolve data or metadata terms + + raise ChildNotFoundException('Could not resolve the semantic path.') + + + + diff --git a/src/soil/element.py b/src/soil/element.py index 9d2d646e0166f8c3ed5986d19764d37451f9abb3..c248859527f5b54a39d1f458bf0f27d725fab607 100644 --- a/src/soil/element.py +++ b/src/soil/element.py @@ -5,6 +5,7 @@ from typing import Any, Dict, List import rdflib +from .error import ChildNotFoundException from ..utils.constants import BASE_UUID_PATTERN, HTTP_GET from ..utils.error import SerialisationException @@ -110,3 +111,14 @@ class Element(ABC): @abstractmethod def serialize_semantics(self, kind: str) -> rdflib.Graph: ... + + def resolve_semantic_path(self, path: List[str]) -> ('Element', str): + if len(path) == 0: + raise ChildNotFoundException('Could not resolve the semantic path.') + + if path[0] == f'{self._profilename}Shape' and len(path) == 1: + return self, 'profile' + else: + raise ChildNotFoundException('Could not resolve the semantic path.') + + # TODO resolve data or metadata terms