Skip to content

Commit

Permalink
Implement merge-axiom-annotations option for repair
Browse files Browse the repository at this point in the history
  • Loading branch information
rctauber committed Aug 15, 2018
1 parent 56133ca commit 580ac30
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public RepairCommand() {
o.addOption("I", "input-iri", true, "load ontology from an IRI");
o.addOption("o", "output", true, "save ontology to a file");
o.addOption("O", "output-iri", true, "set OntologyIRI for output");
o.addOption(
"m",
"merge-axiom-annotations",
true,
"if true, merge axiom annotations on duplicate axioms");
options = o;
}

Expand Down Expand Up @@ -88,7 +93,7 @@ public void main(String[] args) {
* @throws Exception on any problem
*/
public CommandState execute(CommandState state, String[] args) throws Exception {
OWLOntology outputOntology = null;
OWLOntology outputOntology;

CommandLine line = CommandLineHelper.getCommandLine(getUsage(), getOptions(), args);
if (line == null) {
Expand All @@ -104,8 +109,14 @@ public CommandState execute(CommandState state, String[] args) throws Exception
outputIRI = inputOntology.getOntologyID().getOntologyIRI().orNull();
}

RepairOperation.repair(inputOntology, ioHelper);
boolean mergeAxiomAnnotations =
CommandLineHelper.getBooleanValue(line, "merge-axiom-annotations", false);

RepairOperation.repair(inputOntology, ioHelper, mergeAxiomAnnotations);
outputOntology = inputOntology;
if (outputIRI != null) {
outputOntology.getOWLOntologyManager().setOntologyDocumentIRI(outputOntology, outputIRI);
}

CommandLineHelper.maybeSaveOutput(line, outputOntology);

Expand Down
104 changes: 84 additions & 20 deletions robot-core/src/main/java/org/obolibrary/robot/RepairOperation.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,7 @@
import org.obolibrary.robot.checks.InvalidReferenceChecker;
import org.obolibrary.robot.checks.InvalidReferenceViolation;
import org.obolibrary.robot.checks.InvalidReferenceViolation.Category;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationValue;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.model.parameters.Imports;
import org.semanticweb.owlapi.util.OWLEntityRenamer;
import org.slf4j.Logger;
Expand All @@ -37,7 +27,7 @@ public class RepairOperation {
* @return a map with default values for all available options
*/
public static Map<String, String> getDefaultOptions() {
Map<String, String> options = new HashMap<String, String>();
Map<String, String> options = new HashMap<>();
// options.put("remove-redundant-subclass-axioms", "true");

return options;
Expand All @@ -47,23 +37,98 @@ public static Map<String, String> getDefaultOptions() {
* Repairs ontology
*
* @param ontology the OWLOntology to repair
* @param iohelper IOHelper to work with the ontology
* @param ioHelper IOHelper to work with the ontology
*/
public static void repair(OWLOntology ontology, IOHelper iohelper) {
repair(ontology, iohelper, getDefaultOptions());
public static void repair(OWLOntology ontology, IOHelper ioHelper) {
repair(ontology, ioHelper, getDefaultOptions());
}

/**
* Repairs ontology
*
* @param ontology the OWLOntology to repair
* @param iohelper IOHelper to work with the ontology
* @param ioHelper IOHelper to work with the ontology
* @param mergeAxiomAnnotations if true, merge annotations on duplicate axioms
*/
public static void repair(
OWLOntology ontology, IOHelper ioHelper, boolean mergeAxiomAnnotations) {
repair(ontology, ioHelper, getDefaultOptions(), mergeAxiomAnnotations);
}

/**
* Repairs ontology
*
* @param ontology the OWLOntology to repair
* @param ioHelper IOHelper to work with the ontology
* @param options map of repair options
*/
public static void repair(OWLOntology ontology, IOHelper iohelper, Map<String, String> options) {
public static void repair(OWLOntology ontology, IOHelper ioHelper, Map<String, String> options) {
repair(ontology, ioHelper, options, false);
}

/**
* Repairs ontology
*
* @param ontology the OWLOntology to reapir
* @param ioHelper IOHelper to work with the ontology
* @param options map of repair options
* @param mergeAxiomAnnotations if true, merge annotations on duplicate axioms
*/
public static void repair(
OWLOntology ontology,
IOHelper ioHelper,
Map<String, String> options,
boolean mergeAxiomAnnotations) {
Set<InvalidReferenceViolation> violations =
InvalidReferenceChecker.getInvalidReferenceViolations(ontology, true);
repairInvalidReferences(iohelper, ontology, violations);
repairInvalidReferences(ioHelper, ontology, violations);
mergeAxiomAnnotations(ontology);
}

/**
* Given an ontology, merge the annotations of duplicate axioms to create one axiom with all
* annotations.
*
* @param ontology the OWLOntology to repair
*/
public static void mergeAxiomAnnotations(OWLOntology ontology) {
Map<OWLAxiom, Set<OWLAnnotation>> mergedAxioms = new HashMap<>();
Set<OWLAxiom> axiomsToMerge = new HashSet<>();

// Find duplicated axioms and collect their annotations
// OWLAPI should already merge non-annotated duplicates
for (OWLAxiom axiom : ontology.getAxioms()) {
if (axiom.isAnnotated()) {
axiomsToMerge.add(axiom);
OWLAxiom strippedAxiom = axiom.getAxiomWithoutAnnotations();
Set<OWLAnnotation> annotations = axiom.getAnnotations();
if (mergedAxioms.containsKey(strippedAxiom)) {
logger.info("Merging annotations on axiom: {}", strippedAxiom.toString());
Set<OWLAnnotation> mergeAnnotations = new HashSet<>();
mergeAnnotations.addAll(mergedAxioms.get(strippedAxiom));
mergeAnnotations.addAll(annotations);
mergedAxioms.put(strippedAxiom, mergeAnnotations);
} else {
mergedAxioms.put(strippedAxiom, annotations);
}
}
}

OWLOntologyManager manager = ontology.getOWLOntologyManager();
OWLDataFactory dataFactory = manager.getOWLDataFactory();
// Remove the duplicated axioms
manager.removeAxioms(ontology, axiomsToMerge);

// Create the axioms with new set of annotations
Set<OWLAxiom> newAxioms = new HashSet<>();
for (Map.Entry<OWLAxiom, Set<OWLAnnotation>> mergedAxiom : mergedAxioms.entrySet()) {
OWLAxiom axiom = mergedAxiom.getKey();
if (axiom.isAnnotationAxiom()) {
OWLAxiom newAxiom = axiom.getAnnotatedAxiom(mergedAxiom.getValue());
newAxioms.add(newAxiom);
}
}
manager.addAxioms(ontology, newAxioms);
}

/**
Expand Down Expand Up @@ -132,8 +197,7 @@ public static void repairInvalidReferences(

logger.info("PRESERVE: " + axiomsToPreserve);
manager.removeAxioms(ontology, axiomsToPreserve);
List<OWLOntologyChange> changes = new ArrayList<OWLOntologyChange>();
changes.addAll(renamer.changeIRI(renameMap));
List<OWLOntologyChange> changes = new ArrayList<>(renamer.changeIRI(renameMap));
manager.applyChanges(changes);
manager.addAxioms(ontology, axiomsToPreserve);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class RepairOperationTest extends CoreTest {
public void testRepair() throws IOException, OWLOntologyCreationException {
OWLOntology ontology = loadOntology("/need-of-repair.owl");
IOHelper iohelper = new IOHelper();
RepairOperation.repair(ontology, iohelper);
RepairOperation.repair(ontology, iohelper, true);
iohelper.saveOntology(ontology, "target/foo.owl");
assertIdentical("/repaired.owl", ontology);
}
Expand Down
37 changes: 33 additions & 4 deletions robot-core/src/test/resources/need-of-repair.owl
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
<?xml version="1.0"?>
<rdf:RDF xmlns="http://purl.obolibrary.org/obo/need-of-repair.owl#"
xml:base="http://purl.obolibrary.org/obo/need-of-repair.owl"
xmlns:obo="http://purl.obolibrary.org/obo/"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:oboInOwl="http://www.geneontology.org/formats/oboInOwl#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:oboInOwl="http://www.geneontology.org/formats/oboInOwl#">
xmlns:obo="http://purl.obolibrary.org/obo/">
<owl:Ontology rdf:about="http://purl.obolibrary.org/obo/need-of-repair.owl"/>



<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Annotation properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->




<!-- http://purl.obolibrary.org/obo/IAO_0100001 -->

<owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0100001"/>



<!--
///////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -28,8 +44,21 @@

<owl:Class rdf:about="http://purl.obolibrary.org/obo/GO_1">
<rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/GO_2"/>
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something duplicated</rdfs:comment>
<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">leaf node</rdfs:label>
</owl:Class>
<owl:Axiom>
<owl:annotatedSource rdf:resource="http://purl.obolibrary.org/obo/GO_1"/>
<owl:annotatedProperty rdf:resource="http://www.w3.org/2000/01/rdf-schema#comment"/>
<owl:annotatedTarget rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something duplicated</owl:annotatedTarget>
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Annotation 1</rdfs:comment>
</owl:Axiom>
<owl:Axiom>
<owl:annotatedSource rdf:resource="http://purl.obolibrary.org/obo/GO_1"/>
<owl:annotatedProperty rdf:resource="http://www.w3.org/2000/01/rdf-schema#comment"/>
<owl:annotatedTarget rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something duplicated</owl:annotatedTarget>
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Annotation 2</rdfs:comment>
</owl:Axiom>



Expand All @@ -53,5 +82,5 @@



<!-- Generated by the OWL API (version 4.5.0) https://github.com/owlcs/owlapi -->
<!-- Generated by the OWL API (version 4.2.8.20170104-2310) https://github.com/owlcs/owlapi -->

19 changes: 15 additions & 4 deletions robot-core/src/test/resources/repaired.owl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
-->




<!-- http://purl.obolibrary.org/obo/IAO_0100001 -->

<owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0100001"/>



Expand All @@ -38,9 +43,16 @@

<owl:Class rdf:about="http://purl.obolibrary.org/obo/GO_1">
<rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/GO_3"/>
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something duplicated</rdfs:comment>
<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">leaf node</rdfs:label>
</owl:Class>

<owl:Axiom>
<owl:annotatedSource rdf:resource="http://purl.obolibrary.org/obo/GO_1"/>
<owl:annotatedProperty rdf:resource="http://www.w3.org/2000/01/rdf-schema#comment"/>
<owl:annotatedTarget rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something duplicated</owl:annotatedTarget>
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Annotation 1</rdfs:comment>
<rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Annotation 2</rdfs:comment>
</owl:Axiom>



Expand All @@ -51,6 +63,7 @@
<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">original parent</rdfs:label>
<owl:deprecated rdf:datatype="http://www.w3.org/2001/XMLSchema#boolean">true</owl:deprecated>
</owl:Class>



<!-- http://purl.obolibrary.org/obo/GO_3 -->
Expand All @@ -59,11 +72,9 @@
<rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/GO_3"/>
<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">replacement parent</rdfs:label>
</owl:Class>


</rdf:RDF>



<!-- Generated by the OWL API (version 4.2.6.20160910-2108) https://github.com/owlcs/owlapi -->
<!-- Generated by the OWL API (version 4.2.6) https://github.com/owlcs/owlapi -->

0 comments on commit 580ac30

Please sign in to comment.