diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f16d0a9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: Build and Release JAR + +on: + push: + branches: + - main + release: + types: [created] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + distribution: 'adopt' + java-version: '11' + + - name: Build with Maven + run: mvn clean package + + - name: Archive build artifacts + uses: actions/upload-artifact@v3 + with: + name: neo4j2owl-jar + path: target/*.jar + + release: + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'release' + + steps: + - name: Download build artifact + uses: actions/download-artifact@v3 + with: + name: neo4j2owl-jar + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + files: neo4j2owl-jar/*.jar + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/main/java/ebi/spot/neo4j2owl/N2OProcedure.java b/src/main/java/ebi/spot/neo4j2owl/N2OProcedure.java index 768c633..0353185 100644 --- a/src/main/java/ebi/spot/neo4j2owl/N2OProcedure.java +++ b/src/main/java/ebi/spot/neo4j2owl/N2OProcedure.java @@ -57,8 +57,26 @@ public Stream importOntology(@Name("url") String url) { @Procedure(mode = Mode.WRITE) public Stream exportOWL() { logger.resetTimer(); - N2OExportService importService = new N2OExportService(db); - N2OReturnValue result = importService.owl2Export(); + N2OExportService exportService = new N2OExportService(db); + N2OReturnValue result = exportService.owl2Export(); + return Stream.of(result); + } + + @SuppressWarnings("unused") + @Procedure(mode = Mode.WRITE) + public Stream exportOWLNodes(@Name("skip") Long skip, @Name("limit") Long limit) { + logger.resetTimer(); + N2OExportService exportService = new N2OExportService(db); + N2OReturnValue result = exportService.owl2ExportNodes(skip, limit); + return Stream.of(result); + } + + @SuppressWarnings("unused") + @Procedure(mode = Mode.WRITE) + public Stream exportOWLEdges() { + logger.resetTimer(); + N2OExportService exportService = new N2OExportService(db); + N2OReturnValue result = exportService.owl2ExportEdges(); return Stream.of(result); } diff --git a/src/main/java/ebi/spot/neo4j2owl/exporter/N2OExportService.java b/src/main/java/ebi/spot/neo4j2owl/exporter/N2OExportService.java index 65c20c6..659c345 100644 --- a/src/main/java/ebi/spot/neo4j2owl/exporter/N2OExportService.java +++ b/src/main/java/ebi/spot/neo4j2owl/exporter/N2OExportService.java @@ -65,7 +65,7 @@ public N2OReturnValue owl2Export() { OWLOntologyManager man = OWLManager.createOWLOntologyManager(); OWLOntology o = man.createOntology(); - addEntities(o); + addEntities(o, 0L, Long.MAX_VALUE); addAnnotations(o); addRelation(o, N2OStatic.RELTYPE_SUBCLASSOF); addRelation(o, N2OStatic.RELTYPE_INSTANCEOF); @@ -88,6 +88,64 @@ public N2OReturnValue owl2Export() { } return returnValue; } + + public N2OReturnValue owl2ExportNodes(Long skip, Long limit) { + n2OEntityManager = new N2OExportManager(); + qsls_with_no_matching_properties = new HashSet<>(); + logger.resetTimer(); + N2OReturnValue returnValue = new N2OReturnValue(); + + try { + OWLOntologyManager man = OWLManager.createOWLOntologyManager(); + + OWLOntology o = man.createOntology(); + addAnnotationProperties(o); + addEntities(o, skip, limit); + addAnnotations(o); + ByteArrayOutputStream os = new ByteArrayOutputStream(); // new FileOutputStream(new File(fileName)) + man.saveOntology(o, new RDFXMLDocumentFormat(), os); + qsls_with_no_matching_properties.forEach(logger::log); + List ontologyChunks = createArrayChunks(os.toByteArray()); + returnValue.setOntology(ontologyChunks); + returnValue.setLog(o.getLogicalAxiomCount() + ""); + } catch (Exception e) { + e.printStackTrace(); + returnValue.setLog(logger.getStackTrace(e)); + } + return returnValue; + } + + public N2OReturnValue owl2ExportEdges() { + n2OEntityManager = new N2OExportManager(); + qsls_with_no_matching_properties = new HashSet<>(); + logger.resetTimer(); + N2OReturnValue returnValue = new N2OReturnValue(); + + try { + OWLOntologyManager man = OWLManager.createOWLOntologyManager(); + + OWLOntology o = man.createOntology(); + findEntities(0L, Long.MAX_VALUE); + addRelation(o, N2OStatic.RELTYPE_SUBCLASSOF); + addRelation(o, N2OStatic.RELTYPE_INSTANCEOF); + for (String rel_qsl : getRelations(OWLAnnotationProperty.class)) { + addRelation(o, rel_qsl); + } + for (String rel_qsl : getRelations(OWLObjectProperty.class)) { + addRelation(o, rel_qsl); + } + ByteArrayOutputStream os = new ByteArrayOutputStream(); // new FileOutputStream(new File(fileName)) + man.saveOntology(o, new RDFXMLDocumentFormat(), os); + qsls_with_no_matching_properties.forEach(logger::log); + List ontologyChunks = createArrayChunks(os.toByteArray()); + returnValue.setOntology(ontologyChunks); + returnValue.setLog(o.getLogicalAxiomCount() + ""); + } catch (Exception e) { + e.printStackTrace(); + returnValue.setLog(logger.getStackTrace(e)); + } + return returnValue; + } private Set getRelations(Class cl) { return n2OEntityManager.relationshipQSLs().stream() @@ -107,13 +165,13 @@ private void addRelation(OWLOntology o, String RELTYPE) throws N2OException { Map r = s.next(); Object object = r.get("n"); // log(r); - Long nid = ((Node) r.get("n")).getId(); - Long xid = ((Node) r.get("x")).getId(); - Relationship rp = (Relationship) r.get("r"); + Long nid = ((Node) r.get("n")).getId(); + Long xid = ((Node) r.get("x")).getId(); + Relationship rp = (Relationship) r.get("r"); - OWLAxiom ax = createAxiom(n2OEntityManager.getEntity(nid), n2OEntityManager.getEntity(xid), RELTYPE); - Set axiomAnnotations = getAxiomAnnotations(rp); - changes.add(new AddAxiom(o, ax.getAnnotatedAxiom(axiomAnnotations))); + OWLAxiom ax = createAxiom(n2OEntityManager.getEntity(nid), n2OEntityManager.getEntity(xid), RELTYPE); + Set axiomAnnotations = getAxiomAnnotations(rp); + changes.add(new AddAxiom(o, ax.getAnnotatedAxiom(axiomAnnotations))); } if (!changes.isEmpty()) { try { @@ -341,8 +399,32 @@ private OWLAnnotationProperty getAnnotationProperty(String qsl_anno) { * - just declarations. The main purpose is to index all entities for the next * Steps in the pipeline */ - private void addEntities(OWLOntology o) throws N2OException { - String cypher = "MATCH (n:Entity) Return n"; + private void addEntities(OWLOntology o, Long skip, Long limit) throws N2OException { + findEntities(skip, limit); + n2OEntityManager.entities().stream().filter(e -> !e.isBuiltIn()).forEach((e -> addDeclaration(e, o))); + } + + /** + * Only discovers entities and updates the n2OEntityManager without adding to the Ontology. + * @param o + * @param skip + * @param limit + * @throws N2OException + */ + private void findEntities(Long skip, Long limit) throws N2OException { + String cypher = String.format("MATCH (n:Entity) Return n SKIP %d LIMIT %d", skip, limit); + Result s; + try (Transaction tx = db.beginTx()) { + s = tx.execute(cypher); + Objects.requireNonNull(s); + s.stream().forEach(r -> createEntityForEachLabel((Node) r.get("n"))); + } catch (Exception e) { + throw new N2OException(N2OStatic.CYPHER_FAILED_TO_EXECUTE + cypher, e); + } + } + + private void addAnnotationProperties(OWLOntology o) throws N2OException { + String cypher = String.format("MATCH (n:AnnotationProperty) Return n"); Result s; try (Transaction tx = db.beginTx()) { s = tx.execute(cypher); diff --git a/src/main/java/ebi/spot/neo4j2owl/exporter/N2OReturnValue.java b/src/main/java/ebi/spot/neo4j2owl/exporter/N2OReturnValue.java index 740682b..d41868e 100644 --- a/src/main/java/ebi/spot/neo4j2owl/exporter/N2OReturnValue.java +++ b/src/main/java/ebi/spot/neo4j2owl/exporter/N2OReturnValue.java @@ -25,4 +25,4 @@ public void addOntologyChunk(String chunk) { public void setLog(String log) { this.log = log; } -} +} \ No newline at end of file