From 4abe645d26d07206f0a034e0c8aaa22e4c8b75b0 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Tue, 11 Oct 2022 10:04:18 +0200 Subject: [PATCH 01/11] core: loaders: owl2: add project loader from owl 2 file Loads ontology metadata from an owl 2 file and creates a new project from it. --- eddy/core/loaders/owl2.py | 71 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/eddy/core/loaders/owl2.py b/eddy/core/loaders/owl2.py index d234113e..0ffc28b2 100644 --- a/eddy/core/loaders/owl2.py +++ b/eddy/core/loaders/owl2.py @@ -1,17 +1,84 @@ from PyQt5 import QtCore from jpype import JImplements, JOverride -from eddy.core.common import HasThreadingSystem from eddy.core.datatypes.system import File from eddy.core.jvm import getJavaVM -from eddy.core.loaders.common import AbstractOntologyLoader +from eddy.core.loaders.common import AbstractProjectLoader from eddy.core.output import getLogger from eddy.core.owl import ImportedOntology +from eddy.core.project import Project from eddy.core.worker import AbstractWorker LOGGER = getLogger() +class OwlProjectLoader(AbstractProjectLoader): + """ + Extends AbstractProjectLoader with facilities to create a project from Owl file. + """ + def __init__(self, path, session): + """ + Initialize the loader. + :param path: path to the OWL 2 file + :param session: session + """ + super().__init__(path, session) + self.nproject = None + + def run(self): + """ + Perform project import. + """ + self.createProject() + self.projectLoaded() + + @classmethod + def filetype(cls): + """ + Returns the type of the file that will be used for the import. + :return: File + """ + return File.Owl + + def createProject(self): + """ + Create the Project by reading data from the parsed Owl File. + """ + self.nproject = Project( + parent=self.session, + profile=self.session.createProfile('OWL 2'), + ontologyIRI=self.getOntologyIRI() + ) + LOGGER.info('Loaded project from ontology: %s...', self.path) + + def projectLoaded(self): + """ + Initialize the Session Project to be the loaded one. + """ + self.session.project = self.nproject + + def getOntologyIRI(self): + """ + Get Ontology IRI from Owl File. + """ + vm = getJavaVM() + if not vm.isRunning(): + vm.initialize() + vm.attachThreadToJVM() + + OWLManager = vm.getJavaClass('org.semanticweb.owlapi.apibinding.OWLManager') + JavaFileClass = vm.getJavaClass('java.io.File') + fileInstance = JavaFileClass(self.path) + manager = OWLManager().createOWLOntologyManager() + ontology = manager.loadOntologyFromOntologyDocument(fileInstance) + try: + ontology_version = ontology.getOntologyID().getVersionIRI().get().toString() + except Exception: + ontology_version = ontology.getOntologyID().getOntologyIRI().get().toString() + + return ontology_version + + class OwlOntologyImportWorker(AbstractWorker): """ Expose facilities to load an OWL ontology starting from the given parameters From 1038928145349c3da3b6b02834c73dff7ca8fea4 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Tue, 11 Oct 2022 10:15:27 +0200 Subject: [PATCH 02/11] ui: project: add dialog to create project with name Used to create a project from an OWL 2 file. --- eddy/ui/project.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/eddy/ui/project.py b/eddy/ui/project.py index 241a19a7..aa5f59f4 100644 --- a/eddy/ui/project.py +++ b/eddy/ui/project.py @@ -191,3 +191,100 @@ def doValidateForm(self) -> None: self.caption.setVisible(not isEmpty(caption)) self.confirmationBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled) self.setFixedSize(self.sizeHint()) + + +class ProjectFromOWLDialog(QtWidgets.QDialog): + """ + This class is used to display a modal window to enter new project specific data. + """ + def __init__(self, parent: QtWidgets.QWidget = None) -> None: + """ + Initialize the project dialog. + :type parent: QWidget + """ + super().__init__(parent) + + ############################################# + # FORM AREA + ################################# + + self.nameLabel = QtWidgets.QLabel(self) + self.nameLabel.setText('Project name') + self.nameField = StringField(self) + self.nameField.setMinimumWidth(400) + self.nameField.setMaxLength(64) + + connect(self.nameField.textChanged, self.doValidateForm) + + self.formWidget = QtWidgets.QWidget(self) + self.formLayout = QtWidgets.QFormLayout(self.formWidget) + self.formLayout.addRow(self.nameLabel, self.nameField) + + ############################################# + # CONFIRMATION AREA + ################################# + + self.confirmationBox = QtWidgets.QDialogButtonBox(QtCore.Qt.Horizontal, self) + self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Ok) + self.confirmationBox.addButton(QtWidgets.QDialogButtonBox.Cancel) + self.confirmationBox.setContentsMargins(10, 0, 10, 10) + self.confirmationBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) + + ############################################# + # SETUP DIALOG LAYOUT + ################################# + + self.caption = QtWidgets.QLabel(self) + self.caption.setContentsMargins(8, 0, 8, 0) + self.caption.setProperty('class', 'invalid') + self.caption.setVisible(False) + + self.gridLayout = QtWidgets.QVBoxLayout(self) + self.gridLayout.setContentsMargins(0, 0, 0, 0) + self.gridLayout.addWidget(self.formWidget) + self.gridLayout.addWidget(self.caption) + self.gridLayout.addWidget(self.confirmationBox, 0, QtCore.Qt.AlignRight) + + self.setFixedSize(self.sizeHint()) + self.setWindowIcon(QtGui.QIcon(':/icons/128/ic_eddy')) + self.setWindowTitle('New project from OWL file') + + connect(self.confirmationBox.accepted, self.accept) + connect(self.confirmationBox.rejected, self.reject) + + ############################################# + # INTERFACE + ################################# + + def name(self) -> str: + """ + Returns the value of the name field (trimmed). + """ + return self.nameField.value() + + ############################################# + # SLOTS + ################################# + + @QtCore.pyqtSlot() + def doValidateForm(self) -> None: + """ + Validate project settings. + """ + caption = '' + enabled = True + + ############################################# + # CHECK NAME + ################################# + + if not self.name(): + caption = '' + enabled = False + + ############################################# + + self.caption.setText(caption) + self.caption.setVisible(not isEmpty(caption)) + self.confirmationBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled) + self.setFixedSize(self.sizeHint()) From 98f94a40773c1cd4059c82c3d01760587a9f93f1 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Tue, 11 Oct 2022 10:23:22 +0200 Subject: [PATCH 03/11] ui: session: handle project creation from owl 2 file Adds a new kwarg to provide a path to an owl 2 file and a new signal emitted when the project is successfully created from the owl 2 file. --- eddy/ui/session.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/eddy/ui/session.py b/eddy/ui/session.py index 42af57be..320cad39 100644 --- a/eddy/ui/session.py +++ b/eddy/ui/session.py @@ -166,7 +166,10 @@ GrapholIRIProjectLoader_v3, GrapholOntologyIRILoader_v3, ) -from eddy.core.loaders.owl2 import OwlOntologyImportSetWorker +from eddy.core.loaders.owl2 import ( + OwlOntologyImportSetWorker, + OwlProjectLoader, +) from eddy.core.network import NetworkManager from eddy.core.output import getLogger from eddy.core.owl import ( @@ -293,6 +296,8 @@ class Session( sgnIRIRemovedFromAllDiagrams = QtCore.pyqtSignal(IRI) sgnSingleNodeSwitchIRI = QtCore.pyqtSignal(AbstractNode, IRI) + sgnStartOwlImport = QtCore.pyqtSignal(str) + # Signals related to rendering options sgnRenderingModified = QtCore.pyqtSignal(str) @@ -314,6 +319,7 @@ def __init__( name: Optional[str] = None, iri: Optional[str] = None, prefix: Optional[str] = None, + owl_path: Optional[str] = None, **kwargs: str, ) -> None: """ @@ -381,15 +387,11 @@ def __init__( self.projectFromFile = True worker = self.createProjectLoader(File.Graphol, path, self) worker.run() - worker = OwlOntologyImportSetWorker(self.project) + elif owl_path: + self.projectFromFile = True + worker = self.createProjectLoader(File.Owl, owl_path, self) worker.run() - self.owlOntologyImportSize = worker.importSize - self.owlOntologyImportLoadedCount = worker.loadCount - if ( - self.owlOntologyImportSize > 0 - and self.owlOntologyImportSize != self.owlOntologyImportLoadedCount - ): - self.owlOntologyImportErrors = worker.owlOntologyImportErrors + self.project.name = name else: self.project = Project( parent=self, @@ -399,6 +401,14 @@ def __init__( profile=OWL2Profile(), ) + if self.projectFromFile: + worker = OwlOntologyImportSetWorker(self.project) + worker.run() + self.owlOntologyImportSize = worker.importSize + self.owlOntologyImportLoadedCount = worker.loadCount + if self.owlOntologyImportSize > self.owlOntologyImportLoadedCount: + self.owlOntologyImportErrors = worker.owlOntologyImportErrors + ############################################# # CONNECT PROJECT SIGNALS ################################# @@ -1159,6 +1169,7 @@ def initLoaders(self) -> None: self.addOntologyLoader(CsvLoader) self.addOntologyLoader(XlsxLoader) self.addProjectLoader(GrapholIRIProjectLoader_v3) + self.addProjectLoader(OwlProjectLoader) # noinspection PyArgumentList def initMenus(self) -> None: From 1b9d794376e175e969da44abe8e62390eb1b0cac Mon Sep 17 00:00:00 2001 From: rooosyf Date: Tue, 11 Oct 2022 10:26:07 +0200 Subject: [PATCH 04/11] core: application: add optional owl 2 file path to doCreateSession() Used to pass an owl 2 file path to the session for project creation. --- eddy/core/application.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/eddy/core/application.py b/eddy/core/application.py index 5e43b514..6026d28a 100644 --- a/eddy/core/application.py +++ b/eddy/core/application.py @@ -310,12 +310,14 @@ def start(self) -> None: @QtCore.pyqtSlot(str) @QtCore.pyqtSlot(str, str, str, str) + @QtCore.pyqtSlot(str, str, str, str, str) def doCreateSession( self, path: Optional[str] = None, name: Optional[str] = None, iri: Optional[str] = None, prefix: Optional[str] = None, + owl_path: Optional[str] = None ) -> None: """ Create a session using the given project path. @@ -335,7 +337,7 @@ def doCreateSession( # If we do not have a session for the given project we'll create one. with BusyProgressDialog('Loading project: {0}'.format(path)): try: - session = Session(self, path, name=name, iri=iri, prefix=prefix) + session = Session(self, path, name=name, iri=iri, prefix=prefix, owl_path=owl_path) except ProjectStopLoadingError: pass except (ProjectNotFoundError, ProjectNotValidError, ProjectVersionError) as e: @@ -387,6 +389,8 @@ def doCreateSession( self.sessions.append(session) self.sgnSessionCreated.emit(session) session.show() + if owl_path: + session.sgnStartOwlImport[str].emit(owl_path) @QtCore.pyqtSlot() def doQuit(self) -> None: From 3d296631886bc0d7f68bac81f9b6e0eae95d3e7b Mon Sep 17 00:00:00 2001 From: rooosyf Date: Tue, 11 Oct 2022 10:34:39 +0200 Subject: [PATCH 05/11] ui: welcome: add new project from owl 2 file button --- eddy/ui/welcome.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/eddy/ui/welcome.py b/eddy/ui/welcome.py index 3656d92f..074124a7 100644 --- a/eddy/ui/welcome.py +++ b/eddy/ui/welcome.py @@ -71,14 +71,17 @@ ) from eddy.core.functions.signals import connect from eddy.ui.file import FileDialog -from eddy.ui.project import NewProjectDialog +from eddy.ui.project import ( + NewProjectDialog, + ProjectFromOWLDialog, +) class Welcome(QtWidgets.QDialog): """ This class is used to display the welcome screen of Eddy. """ - sgnCreateSession = QtCore.pyqtSignal([str], [str, str, str, str]) + sgnCreateSession = QtCore.pyqtSignal([str], [str, str, str, str], [str, str, str, str, str]) sgnOpenProject = QtCore.pyqtSignal(str) sgnUpdateRecentProjects = QtCore.pyqtSignal() @@ -152,6 +155,11 @@ def __init__( self.buttonOpenProject.setIconSize(QtCore.QSize(24, 24)) self.buttonOpenProject.setText('&Open project') connect(self.buttonOpenProject.clicked, self.doOpen) + self.buttonImportProject = PHCQPushButton(self) + self.buttonImportProject.setIcon(QtGui.QIcon(':/icons/24/ic_system_update')) + self.buttonImportProject.setIconSize(QtCore.QSize(24, 24)) + self.buttonImportProject.setText('Create project from OWL &file') + connect(self.buttonImportProject.clicked, self.doImportFromOWL) self.buttonHelp = PHCQToolButton(self) self.buttonHelp.setIcon(QtGui.QIcon(':/icons/24/ic_help_outline_black')) @@ -164,6 +172,7 @@ def __init__( self.buttonLayoutRT = QtWidgets.QVBoxLayout() self.buttonLayoutRT.addWidget(self.buttonNewProject) self.buttonLayoutRT.addWidget(self.buttonOpenProject) + self.buttonLayoutRT.addWidget(self.buttonImportProject) self.buttonLayoutRT.setContentsMargins(0, 38, 0, 0) self.buttonLayoutRT.setAlignment(QtCore.Qt.AlignHCenter) self.buttonLayoutRB = QtWidgets.QHBoxLayout() @@ -217,6 +226,7 @@ def __init__( connect(self.sgnCreateSession[str], application.doCreateSession) connect(self.sgnCreateSession[str, str, str, str], application.doCreateSession) + connect(self.sgnCreateSession[str, str, str, str, str], application.doCreateSession) connect(self.sgnOpenProject, self.doOpenProject) connect(self.sgnUpdateRecentProjects, self.doUpdateRecentProjects) @@ -326,6 +336,22 @@ def doOpenURL(self) -> None: if weburl: QtGui.QDesktopServices.openUrl(QtCore.QUrl(weburl)) + def doImportFromOWL(self): + """ + Bring up a modal dialog to create a new project from an OWL 2 file. + """ + dialog = FileDialog(self) + dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) + dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile) + dialog.setViewMode(QtWidgets.QFileDialog.Detail) + dialog.setNameFilters([File.Owl.value]) + if dialog.exec_() == QtWidgets.QFileDialog.Accepted: + filePath = dialog.selectedFiles()[0] + form = ProjectFromOWLDialog(self) + if form.exec_() == ProjectFromOWLDialog.Accepted: + self.sgnCreateSession[str, str, str, str, str].emit( + None, form.name(), None, None, str(filePath)) + @QtCore.pyqtSlot(str) def doRemoveProject(self, path: str) -> None: """ From c500beed364d0b191fa7311c9e15c3aa71337245 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Tue, 11 Oct 2022 10:35:32 +0200 Subject: [PATCH 06/11] plugins: ontology_importer: start import on project-from-owl creation --- .../ontology-importer/ontology_importer.py | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/eddy/plugins/ontology-importer/ontology_importer.py b/eddy/plugins/ontology-importer/ontology_importer.py index 9fd53749..973975ad 100644 --- a/eddy/plugins/ontology-importer/ontology_importer.py +++ b/eddy/plugins/ontology-importer/ontology_importer.py @@ -37,6 +37,7 @@ import sqlite3 import sys import textwrap +from typing import Optional from PyQt5 import ( QtCore, @@ -855,19 +856,25 @@ def importPrefixes(self): command = CommandProjectAddPrefix(self.project, prefix, namespace) self.session.undostack.push(command) - def doOpenOntologyFile(self): + @QtCore.pyqtSlot(str) + @QtCore.pyqtSlot() + def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): """ Starts the import process by selecting an OWL 2 ontology file. """ - dialog = FileDialog(self.session) - dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) - dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile) - dialog.setViewMode(QtWidgets.QFileDialog.Detail) - dialog.setNameFilters([File.Owl.value]) + if my_owl_file: + self.filePath = [my_owl_file] + else: + dialog = FileDialog(self.session) + dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptOpen) + dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile) + dialog.setViewMode(QtWidgets.QFileDialog.Detail) + dialog.setNameFilters([File.Owl.value]) - if dialog.exec_(): - self.filePath = dialog.selectedFiles() + if dialog.exec_(): + self.filePath = dialog.selectedFiles() + if self.filePath: ### SET SPACE BETWEEN ITEMS ### form = DiagramPropertiesForm(self.project, parent=self.session) if form.exec_(): @@ -950,8 +957,7 @@ def doOpenOntologyFile(self): try: - for x in dialog.selectedFiles(): - + for x in self.filePath: QtCore.QCoreApplication.processEvents() self.fileInstance = self.JavaFileClass(x) @@ -1202,7 +1208,7 @@ def start(self): # CONFIGURE SIGNALS/SLOTS connect(self.session.sgnNoSaveProject, self.onNoSave) - + connect(self.session.sgnStartOwlImport, self.doOpenOntologyFile) # importation in DB # class Importation(): From f66b9031be6744698781dffb429a56d1ede05747 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Mon, 17 Oct 2022 12:28:13 +0200 Subject: [PATCH 07/11] core: loaders: owl2: fixes on ontology IRI + imported ontologies added --- eddy/core/loaders/owl2.py | 57 ++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/eddy/core/loaders/owl2.py b/eddy/core/loaders/owl2.py index 0ffc28b2..2c1d6203 100644 --- a/eddy/core/loaders/owl2.py +++ b/eddy/core/loaders/owl2.py @@ -44,10 +44,13 @@ def createProject(self): """ Create the Project by reading data from the parsed Owl File. """ + ontologyIRI, ontologyV = self.getOntologyIRI() self.nproject = Project( parent=self.session, profile=self.session.createProfile('OWL 2'), - ontologyIRI=self.getOntologyIRI() + ontologyIRI=ontologyIRI, + version=ontologyV, + imports=self.addImports() ) LOGGER.info('Loaded project from ontology: %s...', self.path) @@ -67,17 +70,59 @@ def getOntologyIRI(self): vm.attachThreadToJVM() OWLManager = vm.getJavaClass('org.semanticweb.owlapi.apibinding.OWLManager') + MissingImportHandlingStrategy = vm.getJavaClass('org.semanticweb.owlapi.model.MissingImportHandlingStrategy') JavaFileClass = vm.getJavaClass('java.io.File') fileInstance = JavaFileClass(self.path) manager = OWLManager().createOWLOntologyManager() + manager.getOntologyLoaderConfiguration().setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT) ontology = manager.loadOntologyFromOntologyDocument(fileInstance) - try: - ontology_version = ontology.getOntologyID().getVersionIRI().get().toString() - except Exception: - ontology_version = ontology.getOntologyID().getOntologyIRI().get().toString() + ontologyID = ontology.getOntologyID() + if ontologyID.isAnonymous(): + ontologyIRI = None + ontologyV = None + else: + ontologyIRI = ontologyID.getOntologyIRI().get().toString() + if ontologyID.getVersionIRI().isPresent(): + ontologyV = ontologyID.getVersionIRI().get().toString() + else: + ontologyV = None - return ontology_version + return ontologyIRI, ontologyV + def addImports(self): + """ + Add imported ontologies. + """ + vm = getJavaVM() + if not vm.isRunning(): + vm.initialize() + vm.attachThreadToJVM() + + OWLManager = vm.getJavaClass('org.semanticweb.owlapi.apibinding.OWLManager') + JavaFileClass = vm.getJavaClass('java.io.File') + fileInstance = JavaFileClass(self.path) + manager = OWLManager().createOWLOntologyManager() + ontology = manager.loadOntologyFromOntologyDocument(fileInstance) + + directImports = ontology.getDirectImports() + importedOnto = set() + for imp in directImports: + ontologyID = imp.getOntologyID() + if ontologyID.isAnonymous(): + ontologyIRI = None + ontologyURI = None + ontologyV = None + else: + ontologyIRI = ontologyID.getOntologyIRI().get().toString() + ontologyURI = ontologyID.getOntologyIRI().get().toURI().toString() + if ontologyID.getVersionIRI().isPresent(): + ontologyV = ontologyID.getVersionIRI().get().toString() + else: + ontologyV = None + impOnto = ImportedOntology(ontologyIRI, ontologyURI, ontologyV, False) + importedOnto.add(impOnto) + + return importedOnto class OwlOntologyImportWorker(AbstractWorker): """ From 024ff194703a0c839c263ada91d3eda4fecb6fb0 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Mon, 17 Oct 2022 12:49:07 +0200 Subject: [PATCH 08/11] plugins: ontology-importer: addImportedOntologies --- .../ontology-importer/ontology_importer.py | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/eddy/plugins/ontology-importer/ontology_importer.py b/eddy/plugins/ontology-importer/ontology_importer.py index 973975ad..4c14d271 100644 --- a/eddy/plugins/ontology-importer/ontology_importer.py +++ b/eddy/plugins/ontology-importer/ontology_importer.py @@ -87,7 +87,7 @@ from eddy.core.owl import ( AnnotationAssertion, IllegalNamespaceError, - Facet, + Facet, ImportedOntology, ) from eddy.core.owl import IRI from eddy.core.owl import Literal @@ -856,6 +856,26 @@ def importPrefixes(self): command = CommandProjectAddPrefix(self.project, prefix, namespace) self.session.undostack.push(command) + def addImportedOntologies(self): + directImports = self.ontology.getDirectImports() + importedOnto = set() + for imp in directImports: + ontologyID = imp.getOntologyID() + if ontologyID.isAnonymous(): + ontologyIRI = None + ontologyURI = None + ontologyV = None + else: + ontologyIRI = ontologyID.getOntologyIRI().get().toString() + ontologyURI = ontologyID.getOntologyIRI().get().toURI().toString() + if ontologyID.getVersionIRI().isPresent(): + ontologyV = ontologyID.getVersionIRI().get().toString() + else: + ontologyV = None + impOnto = ImportedOntology(ontologyIRI, ontologyURI, ontologyV, False) + self.project.addImportedOntology(impOnto) + + @QtCore.pyqtSlot(str) @QtCore.pyqtSlot() def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): @@ -896,6 +916,8 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): ### IMPORT OWL API ### if True: self.OWLManager = self.vm.getJavaClass('org.semanticweb.owlapi.apibinding.OWLManager') + self.MissingImportHandlingStrategy = self.vm.getJavaClass( + 'org.semanticweb.owlapi.model.MissingImportHandlingStrategy') self.JavaFileClass = self.vm.getJavaClass('java.io.File') self.Type = self.vm.getJavaClass('org.semanticweb.owlapi.model.AxiomType') self.Set = self.vm.getJavaClass('java.util.Set') @@ -964,6 +986,9 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): QtCore.QCoreApplication.processEvents() self.manager = self.OWLManager().createOWLOntologyManager() + self.manager.getOntologyLoaderConfiguration().setMissingImportHandlingStrategy( + self.MissingImportHandlingStrategy.SILENT) + QtCore.QCoreApplication.processEvents() self.ontology = self.manager.loadOntologyFromOntologyDocument( @@ -1006,6 +1031,7 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): QtCore.QCoreApplication.processEvents() self.df = self.OWLManager.getOWLDataFactory() + self.addImportedOntologies() QtCore.QCoreApplication.processEvents() From d317fe0f28c9897aa20017ce196055f871eabbd6 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Thu, 20 Oct 2022 17:08:46 +0200 Subject: [PATCH 09/11] core: loaders: owl2: removed redundant getImportedOntologies + added signal on load --- eddy/core/loaders/owl2.py | 45 ++++++--------------------------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/eddy/core/loaders/owl2.py b/eddy/core/loaders/owl2.py index 2c1d6203..17818424 100644 --- a/eddy/core/loaders/owl2.py +++ b/eddy/core/loaders/owl2.py @@ -1,3 +1,6 @@ +import os +import sys + from PyQt5 import QtCore from jpype import JImplements, JOverride @@ -44,13 +47,12 @@ def createProject(self): """ Create the Project by reading data from the parsed Owl File. """ - ontologyIRI, ontologyV = self.getOntologyIRI() + ontologyIRI, ontologyV = self.getOntologyID() self.nproject = Project( parent=self.session, profile=self.session.createProfile('OWL 2'), ontologyIRI=ontologyIRI, - version=ontologyV, - imports=self.addImports() + version=ontologyV ) LOGGER.info('Loaded project from ontology: %s...', self.path) @@ -60,7 +62,7 @@ def projectLoaded(self): """ self.session.project = self.nproject - def getOntologyIRI(self): + def getOntologyID(self): """ Get Ontology IRI from Owl File. """ @@ -89,40 +91,6 @@ def getOntologyIRI(self): return ontologyIRI, ontologyV - def addImports(self): - """ - Add imported ontologies. - """ - vm = getJavaVM() - if not vm.isRunning(): - vm.initialize() - vm.attachThreadToJVM() - - OWLManager = vm.getJavaClass('org.semanticweb.owlapi.apibinding.OWLManager') - JavaFileClass = vm.getJavaClass('java.io.File') - fileInstance = JavaFileClass(self.path) - manager = OWLManager().createOWLOntologyManager() - ontology = manager.loadOntologyFromOntologyDocument(fileInstance) - - directImports = ontology.getDirectImports() - importedOnto = set() - for imp in directImports: - ontologyID = imp.getOntologyID() - if ontologyID.isAnonymous(): - ontologyIRI = None - ontologyURI = None - ontologyV = None - else: - ontologyIRI = ontologyID.getOntologyIRI().get().toString() - ontologyURI = ontologyID.getOntologyIRI().get().toURI().toString() - if ontologyID.getVersionIRI().isPresent(): - ontologyV = ontologyID.getVersionIRI().get().toString() - else: - ontologyV = None - impOnto = ImportedOntology(ontologyIRI, ontologyURI, ontologyV, False) - importedOnto.add(impOnto) - - return importedOnto class OwlOntologyImportWorker(AbstractWorker): """ @@ -381,6 +349,7 @@ def run(self): else: self._loadCount += 1 impOnt.correctlyLoaded = True + self.project.sgnImportedOntologyLoaded.emit(impOnt) except Exception as e: LOGGER.exception('Fatal exception while resolving ontology imports: {}'.format(str(e))) else: From 3ee9659a4742a861d9be93dc36e9dc5051ec35ec Mon Sep 17 00:00:00 2001 From: rooosyf Date: Thu, 20 Oct 2022 17:09:57 +0200 Subject: [PATCH 10/11] plugins: ontology-importer: fixed getImportedOntologies with local path --- .../ontology-importer/ontology_importer.py | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/eddy/plugins/ontology-importer/ontology_importer.py b/eddy/plugins/ontology-importer/ontology_importer.py index 4c14d271..82aeb2fe 100644 --- a/eddy/plugins/ontology-importer/ontology_importer.py +++ b/eddy/plugins/ontology-importer/ontology_importer.py @@ -84,6 +84,7 @@ from eddy.core.items.nodes.union import UnionNode from eddy.core.items.nodes.value_domain import ValueDomainNode from eddy.core.jvm import getJavaVM +from eddy.core.loaders.owl2 import OwlOntologyImportSetWorker from eddy.core.owl import ( AnnotationAssertion, IllegalNamespaceError, @@ -856,25 +857,34 @@ def importPrefixes(self): command = CommandProjectAddPrefix(self.project, prefix, namespace) self.session.undostack.push(command) - def addImportedOntologies(self): + def getImportedOntologies(self): + """ + Get set of Imported Ontologies. + """ + folder = self.JavaFileClass(str(os.path.expanduser('~'))) + iriMapper = self.AutoIRIMapper(folder, True) + self.manager.getIRIMappers().add(iriMapper) + directImports = self.ontology.getDirectImports() importedOnto = set() for imp in directImports: ontologyID = imp.getOntologyID() - if ontologyID.isAnonymous(): - ontologyIRI = None - ontologyURI = None - ontologyV = None - else: + if not ontologyID.isAnonymous(): ontologyIRI = ontologyID.getOntologyIRI().get().toString() ontologyURI = ontologyID.getOntologyIRI().get().toURI().toString() if ontologyID.getVersionIRI().isPresent(): ontologyV = ontologyID.getVersionIRI().get().toString() else: ontologyV = None - impOnto = ImportedOntology(ontologyIRI, ontologyURI, ontologyV, False) - self.project.addImportedOntology(impOnto) - + ontologyPath = iriMapper.getDocumentIRI(ontologyID.getOntologyIRI().get()) + if ontologyPath: + ontologyPath = ontologyPath.toString().replace('file:', '', 1) + impOnto = ImportedOntology(ontologyIRI, ontologyPath, ontologyV, True) + importedOnto.add(impOnto) + else: + impOnto = ImportedOntology(ontologyIRI, ontologyURI, ontologyV, False) + importedOnto.add(impOnto) + return importedOnto @QtCore.pyqtSlot(str) @QtCore.pyqtSlot() @@ -918,6 +928,7 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): self.OWLManager = self.vm.getJavaClass('org.semanticweb.owlapi.apibinding.OWLManager') self.MissingImportHandlingStrategy = self.vm.getJavaClass( 'org.semanticweb.owlapi.model.MissingImportHandlingStrategy') + self.AutoIRIMapper = self.vm.getJavaClass('org.semanticweb.owlapi.util.AutoIRIMapper') self.JavaFileClass = self.vm.getJavaClass('java.io.File') self.Type = self.vm.getJavaClass('org.semanticweb.owlapi.model.AxiomType') self.Set = self.vm.getJavaClass('java.util.Set') @@ -1031,7 +1042,6 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): QtCore.QCoreApplication.processEvents() self.df = self.OWLManager.getOWLDataFactory() - self.addImportedOntologies() QtCore.QCoreApplication.processEvents() @@ -1071,6 +1081,18 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): self.importAnnotations(diagram) QtCore.QCoreApplication.processEvents() + ### IMPORT IMPORTED ONTOLOGIES ### + imported = self.getImportedOntologies() + for imp in imported: + self.project.addImportedOntology(imp) + QtCore.QCoreApplication.processEvents() + worker = OwlOntologyImportSetWorker(self.project) + worker.run() + self.session.owlOntologyImportSize = worker.importSize + self.session.owlOntologyImportLoadedCount = worker.loadCount + if self.session.owlOntologyImportSize > self.session.owlOntologyImportLoadedCount: + self.session.owlOntologyImportErrors = worker.owlOntologyImportErrors + renderer = self.ManchesterOWLSyntaxOWLObjectRendererImpl() ### COUNT PROCESSED AXIOMS ### From f3eacd15d28ccdd535e87ac28777710fc0f43da5 Mon Sep 17 00:00:00 2001 From: rooosyf Date: Thu, 27 Oct 2022 11:46:49 +0200 Subject: [PATCH 11/11] fix on missing imports --- eddy/core/loaders/owl2.py | 4 +++- eddy/plugins/ontology-importer/ontology_importer.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/eddy/core/loaders/owl2.py b/eddy/core/loaders/owl2.py index 17818424..60d86517 100644 --- a/eddy/core/loaders/owl2.py +++ b/eddy/core/loaders/owl2.py @@ -76,7 +76,9 @@ def getOntologyID(self): JavaFileClass = vm.getJavaClass('java.io.File') fileInstance = JavaFileClass(self.path) manager = OWLManager().createOWLOntologyManager() - manager.getOntologyLoaderConfiguration().setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT) + config = manager.getOntologyLoaderConfiguration() + config = config.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT) + manager.setOntologyLoaderConfiguration(config) ontology = manager.loadOntologyFromOntologyDocument(fileInstance) ontologyID = ontology.getOntologyID() if ontologyID.isAnonymous(): diff --git a/eddy/plugins/ontology-importer/ontology_importer.py b/eddy/plugins/ontology-importer/ontology_importer.py index 82aeb2fe..fd3a95cb 100644 --- a/eddy/plugins/ontology-importer/ontology_importer.py +++ b/eddy/plugins/ontology-importer/ontology_importer.py @@ -997,9 +997,10 @@ def doOpenOntologyFile(self, my_owl_file: Optional[str] = None): QtCore.QCoreApplication.processEvents() self.manager = self.OWLManager().createOWLOntologyManager() - self.manager.getOntologyLoaderConfiguration().setMissingImportHandlingStrategy( + config = self.manager.getOntologyLoaderConfiguration() + config = config.setMissingImportHandlingStrategy( self.MissingImportHandlingStrategy.SILENT) - + self.manager.setOntologyLoaderConfiguration(config) QtCore.QCoreApplication.processEvents() self.ontology = self.manager.loadOntologyFromOntologyDocument(