From e344d84cd52adb404eafc3950516526edfdcd519 Mon Sep 17 00:00:00 2001 From: Ensar Emir Erol Date: Wed, 4 Dec 2024 17:16:44 +0100 Subject: [PATCH] ontology service --- .../components/WorkspaceCardItem/styles.scss | 15 +- app/src/pages/workspaces_page/styles.scss | 7 +- server/const/err_enums.py | 6 + server/models/ontology.py | 10 -- .../ontology_service_protocol/__init__.py | 2 +- .../core/sqlite_db_service/tables/ontology.py | 1 + .../services/local/local_ontology_service.py | 152 +++++++++++++++--- 7 files changed, 152 insertions(+), 41 deletions(-) diff --git a/app/src/pages/workspaces_page/components/WorkspaceCardItem/styles.scss b/app/src/pages/workspaces_page/components/WorkspaceCardItem/styles.scss index d12c17a..42ea0f3 100644 --- a/app/src/pages/workspaces_page/components/WorkspaceCardItem/styles.scss +++ b/app/src/pages/workspaces_page/components/WorkspaceCardItem/styles.scss @@ -1,7 +1,6 @@ .workspace-card { - flex: 1; + width: calc(25% - 10px); max-height: fit-content; - min-width: 100%; } h5 { @@ -14,10 +13,13 @@ p { overflow: hidden; } -@media screen and (min-width: 768px) { - .workspace-card { - min-width: calc(768px / 3 - 20px); - max-width: calc(768px / 3 - 20px); +@media (max-width: 768px) { + .workspace-card.bp5-card.bp5-elevation-2 { + width: calc(100% - 10px); + } + .workspaces-list { + flex-wrap: wrap; + justify-content: space-between; } } @@ -28,5 +30,4 @@ p { & > *:not(:first-child) { margin-left: 10px; } - margin-top: 10px; } diff --git a/app/src/pages/workspaces_page/styles.scss b/app/src/pages/workspaces_page/styles.scss index 8eb2f64..74a01d1 100644 --- a/app/src/pages/workspaces_page/styles.scss +++ b/app/src/pages/workspaces_page/styles.scss @@ -17,15 +17,14 @@ .workspaces-list { display: flex; gap: 10px; + padding: 10px; + flex-wrap: wrap; - align-items: flex-start; align-content: flex-start; - flex-direction: column; width: 100%; - padding: 10px; } -@media only screen and (min-width: 768px) { +@media (max-width: 768px) { .workspaces-list { flex-direction: row; } diff --git a/server/const/err_enums.py b/server/const/err_enums.py index fac8e1d..68772c0 100644 --- a/server/const/err_enums.py +++ b/server/const/err_enums.py @@ -2,6 +2,9 @@ class ErrCodes(Enum): + # General + UNKNOWN_ERROR = -1 + NOT_IMPLEMENTED = -2 # FS Service FILE_NOT_FOUND = 0 FILE_CORRUPTED = 1 @@ -10,3 +13,6 @@ class ErrCodes(Enum): WORKSPACE_METADATA_NOT_FOUND = 20 WORKSPACE_METADATA_EXISTS = 21 WORKSPACE_METADATA_ILLEGAL_UPDATE_OPERATION = 22 + + # Ontology Service + ONTOLOGY_NOT_FOUND = 40 diff --git a/server/models/ontology.py b/server/models/ontology.py index 370e473..4ffd880 100644 --- a/server/models/ontology.py +++ b/server/models/ontology.py @@ -275,7 +275,6 @@ class Ontology: classes (list[Class]): The classes in the ontology individuals (list[Individual]): The individuals in the ontology properties (list[Property]): The properties in the ontology - all_named_nodes (list[NamedNode]): All named nodes in the ontology """ @@ -285,7 +284,6 @@ class Ontology: classes: list[Class] individuals: list[Individual] properties: list[Property] - all_named_nodes: list[NamedNode] def to_dict(self): return { @@ -301,10 +299,6 @@ def to_dict(self): "properties": [ prop.to_dict() for prop in self.properties ], - "all_named_nodes": [ - node.to_dict() - for node in self.all_named_nodes - ], } @classmethod @@ -325,8 +319,4 @@ def from_dict(cls, data): Property.from_dict(prop) for prop in data["properties"] ], - all_named_nodes=[ - NamedNode.from_dict(node) - for node in data["all_named_nodes"] - ], ) diff --git a/server/service_protocols/ontology_service_protocol/__init__.py b/server/service_protocols/ontology_service_protocol/__init__.py index b557e2f..ad35ca1 100644 --- a/server/service_protocols/ontology_service_protocol/__init__.py +++ b/server/service_protocols/ontology_service_protocol/__init__.py @@ -34,7 +34,7 @@ def get_ontologies( ... def create_ontology( - self, name: str, content: bytes + self, name: str, base_uri: str, content: bytes ) -> Ontology: """ Create an ontology diff --git a/server/services/core/sqlite_db_service/tables/ontology.py b/server/services/core/sqlite_db_service/tables/ontology.py index 31f3c4c..f90ccd2 100644 --- a/server/services/core/sqlite_db_service/tables/ontology.py +++ b/server/services/core/sqlite_db_service/tables/ontology.py @@ -14,3 +14,4 @@ class OntologyTable(Base): ) name: Mapped[str] = mapped_column(String) json_file_uuid: Mapped[str] = mapped_column(String) + ontology_file_uuid: Mapped[str] = mapped_column(String) diff --git a/server/services/local/local_ontology_service.py b/server/services/local/local_ontology_service.py index ca2b177..77112c5 100644 --- a/server/services/local/local_ontology_service.py +++ b/server/services/local/local_ontology_service.py @@ -1,9 +1,12 @@ import json import logging +from uuid import uuid4 from kink import inject +from pkg_resources import FileMetadata from sqlalchemy import select +from server.exceptions import ErrCodes, ServerException from server.models.ontology import Ontology from server.service_protocols.fs_service_protocol import ( FSServiceProtocol, @@ -15,6 +18,8 @@ from server.services.local.local_fs_service import ( LocalFSService, ) +from server.utils.ontology_indexer import OntologyIndexer +from server.utils.rdf_loader import RDFLoader @inject @@ -22,12 +27,32 @@ class LocalOntologyService: def __init__( self, fs_service: LocalFSService, + ontology_indexer: OntologyIndexer, db_service: DBService, ): self.logger = logging.getLogger(__name__) + self.ontology_indexer: OntologyIndexer = ( + ontology_indexer + ) self.fs_service: FSServiceProtocol = fs_service self.db_service: DBService = db_service + def _get_from_ontology_table( + self, ontology_id: str + ) -> OntologyTable | None: + query = ( + select(OntologyTable) + .where(OntologyTable.uuid == ontology_id) + .limit(1) + ) + + with self.db_service.get_session() as session: + result = session.execute(query).first() + if not result: + return None + + return result[0] + def get_ontology(self, ontology_id: str) -> Ontology: """ Get ontology by id @@ -42,26 +67,14 @@ def get_ontology(self, ontology_id: str) -> Ontology: self.logger.info( f"Getting ontology with id: {ontology_id}" ) - query = ( - select(OntologyTable) - .where(OntologyTable.uuid == ontology_id) - .limit(1) + ontology_table = self._get_from_ontology_table( + ontology_id ) - ontology_table: OntologyTable | None = None - - with self.db_service.get_session() as session: - result = session.execute(query).first() - if not result: - raise ValueError( - f"Ontology with id {ontology_id} not found" - ) - - ontology_table = result[0] - if not ontology_table: - raise ValueError( - f"Ontology with id {ontology_id} not found" + raise ServerException( + "Ontology not found", + ErrCodes.ONTOLOGY_NOT_FOUND, ) file_bytes = ( @@ -114,5 +127,106 @@ def get_ontologies( return ontologies def create_ontology( - self, name: str, content: bytes - ) -> Ontology: ... + self, name: str, base_uri: str, content: bytes + ) -> Ontology: + self.logger.info(f"Creating ontology: {name}") + self.logger.info("Parsing ontology content") + g = RDFLoader.load_rdf_bytes(content) + self.logger.info(f"Indexing ontology: {name}") + + all_classes = self.ontology_indexer.get_classes( + base_uri, g + ) + + all_properties = ( + self.ontology_indexer.get_properties( + base_uri, g + ) + ) + + all_individuals = ( + self.ontology_indexer.get_individuals( + base_uri, g + ) + ) + + self.logger.info("Indexing complete") + self.logger.info("Uploading ontology file") + file_metadata = self.fs_service.upload_file( + name, content + ) + self.logger.info("File uploaded") + + ontology = Ontology( + uuid=uuid4().hex, + file_uuid=file_metadata.uuid, + name=name, + classes=all_classes, + individuals=all_individuals, + properties=all_properties, + ) + + self.logger.info("Saving ontology to filesystem") + + json_data = ontology.to_dict() + + ontology_json_file = self.fs_service.upload_file( + f"{name}.json", + json.dumps(json_data).encode("utf-8"), + ) + self.logger.info("Ontology saved to filesystem") + + with self.db_service.get_session() as session: + session.add( + OntologyTable( + uuid=ontology.uuid, + name=ontology.name, + json_file_uuid=ontology_json_file.uuid, + ontology_file_uuid=file_metadata.uuid, + ) + ) + session.commit() + + return ontology + + def update_ontology( + self, + ontology_id: str, + name: str, + file_metadata: FileMetadata, + ) -> Ontology: + raise ServerException( + "Not implemented", ErrCodes.NOT_IMPLEMENTED + ) + + def delete_ontology(self, ontology_id: str): + self.logger.info( + f"Deleting ontology with id: {ontology_id}" + ) + + ontology_table = self._get_from_ontology_table( + ontology_id + ) + + if not ontology_table: + raise ServerException( + "Ontology not found", + ErrCodes.ONTOLOGY_NOT_FOUND, + ) + + self.fs_service.delete_file_with_uuid( + ontology_table.json_file_uuid + ) + self.fs_service.delete_file_with_uuid( + ontology_table.ontology_file_uuid + ) + + with self.db_service.get_session() as session: + session.delete(ontology_table) + session.commit() + + self.logger.info( + f"Ontology with id: {ontology_id} deleted" + ) + + return None