Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass at reference violation tests #208

Merged
merged 4 commits into from
Dec 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.obolibrary.robot;

import org.geneontology.reasoner.ExpressionMaterializingReasoner;
import org.obolibrary.robot.checks.InvalidReferenceChecker;
import org.obolibrary.robot.checks.InvalidReferenceViolation;
import org.obolibrary.robot.exceptions.InvalidReferenceException;
import org.obolibrary.robot.exceptions.OntologyLogicException;
import org.obolibrary.robot.reason.EquivalentClassReasoning;
import org.obolibrary.robot.reason.EquivalentClassReasoningMode;
Expand Down Expand Up @@ -70,6 +73,7 @@ public static Map<String, String> getDefaultOptions() {
options.put("annotate-inferred-axioms", "false");
options.put("exclude-duplicate-axioms", "false");
options.put("equivalent-classes-allowed", ALL.written());
options.put("prevent-invalid-references", "false");

return options;
}
Expand All @@ -83,11 +87,12 @@ public static Map<String, String> getDefaultOptions() {
* @param reasonerFactory the factory to create a reasoner instance from
* @throws OWLOntologyCreationException on ontology problem
* @throws OntologyLogicException on inconsistency or incoherency
* @throws InvalidReferenceException
*/
public static void reason(OWLOntology ontology,
OWLReasonerFactory reasonerFactory)
throws OWLOntologyCreationException,
OntologyLogicException {
OntologyLogicException, InvalidReferenceException {
reason(ontology, reasonerFactory, getDefaultOptions());
}

Expand All @@ -101,11 +106,12 @@ public static void reason(OWLOntology ontology,
* @param options a map of option strings, or null
* @throws OWLOntologyCreationException on ontology problem
* @throws OntologyLogicException on inconsistency or incoherency
* @throws InvalidReferenceException
*/
public static void reason(OWLOntology ontology,
OWLReasonerFactory reasonerFactory,
Map<String, String> options) throws OWLOntologyCreationException,
OntologyLogicException {
OntologyLogicException, InvalidReferenceException {
logger.info("Ontology has {} axioms.", ontology.getAxioms().size());

logger.info("Fetching labels...");
Expand All @@ -119,6 +125,19 @@ public static void reason(OWLOntology ontology,

OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
OWLDataFactory dataFactory = manager.getOWLDataFactory();

Set<InvalidReferenceViolation> referenceViolations = InvalidReferenceChecker.getInvalidReferenceViolations(ontology, false);
if (referenceViolations.size() > 0) {
logger.error("Reference violations found: "+referenceViolations.size()+" - reasoning may be incomplete");
for (InvalidReferenceViolation v : referenceViolations) {
logger.error("Reference violation: "+v);
}

if (OptionsHelper.optionIsTrue(options, "prevent-invalid-references")) {
throw new InvalidReferenceException(referenceViolations);
}

}

logger.info("Starting reasoning...");
OWLReasoner reasoner = reasonerFactory.createReasoner(ontology);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.obolibrary.robot.checks;

import java.util.HashSet;
import java.util.Set;

import org.obolibrary.robot.checks.InvalidReferenceViolation.Category;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.parameters.Imports;

/**
*
* See: https://github.com/ontodev/robot/issues/1
*
* @author cjm
*
*/
public class InvalidReferenceChecker {


/**
* @param ontology
* @param entity
* @return true if owlClass has no logical or non-logical axioms
*/
public static boolean isDangling(OWLOntology ontology, OWLEntity entity) {
if (entity instanceof OWLClass) {
OWLClass owlClass = (OWLClass)entity;
if (ontology.getAxioms(owlClass, Imports.INCLUDED).size() > 0)
return false;
if (ontology.getAnnotationAssertionAxioms(owlClass.getIRI()).size() > 0)
return false;
return true;
}
if (entity instanceof OWLObjectProperty) {
OWLObjectProperty owlProperty = (OWLObjectProperty)entity;
if (ontology.getAxioms(owlProperty, Imports.INCLUDED).size() > 0)
return false;
if (ontology.getAnnotationAssertionAxioms(owlProperty.getIRI()).size() > 0)
return false;
return true;
}
return false;
}

/**
* @param ontology
* @param entity
* @return true if entity is deprecated
*/
public static boolean isDeprecated(OWLOntology ontology, OWLEntity entity) {
for (OWLAnnotationAssertionAxiom a : ontology.getAnnotationAssertionAxioms(entity.getIRI())) {
if (a.isDeprecatedIRIAssertion()) {
if (a.getValue().asLiteral().get().parseBoolean()) {
return true;
}
}
}
return false;
}


/**
* @param ontology
* @param axioms
* @return all violations
*/
public static Set<InvalidReferenceViolation> getInvalidReferenceViolations(OWLOntology ontology, Set<OWLAxiom> axioms, boolean ignoreDangling) {
Set<InvalidReferenceViolation> violations = new HashSet<>();
for (OWLAxiom axiom : axioms) {
for (OWLEntity e : axiom.getSignature()) {
if (!ignoreDangling && isDangling(ontology, e)) {
violations.add(InvalidReferenceViolation.create(axiom, e, Category.DANGLING));
}
if (isDeprecated(ontology, e)) {
violations.add(InvalidReferenceViolation.create(axiom, e, Category.DEPRECATED));
}

}

}
return violations;
}

/**
* @param ontology
* @param ignoreDangling
* @return all violations in ontology
*/
public static Set<InvalidReferenceViolation> getInvalidReferenceViolations(OWLOntology ontology, boolean ignoreDangling) {
return getInvalidReferenceViolations(ontology, ontology.getAxioms(Imports.INCLUDED), ignoreDangling);
}


/**
* Checks an import module. If the base ontology refers to deprecated entities in the import module
* this constitutes a violation
*
* @param importModule
* @param baseOntology
* @return all deprecation-reference violations in baseOntology with respect to import module
*/
public static Set<InvalidReferenceViolation> checkImportModule(OWLOntology importModule, OWLOntology baseOntology) {
return getInvalidReferenceViolations(importModule, baseOntology.getAxioms(Imports.INCLUDED), true);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package org.obolibrary.robot.checks;

import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLEntity;

/**
* Represents a reference violation
*
* TODO: we may want to make warnings if a class is slated for deprecation in the future:
* see https://github.com/information-artifact-ontology/ontology-metadata/issues/22
*
* @author cjm
*
*/
public class InvalidReferenceViolation {

final private OWLAxiom axiom;
final private OWLEntity referencedObject;
final private Category category;



private InvalidReferenceViolation(OWLAxiom axiom,
OWLEntity referencedObject, Category category) {
super();
this.axiom = axiom;
this.referencedObject = referencedObject;
this.category = category;
}

/**
* @param axiom
* @param referencedObject
* @param category
* @return new instance
*/
public static InvalidReferenceViolation create(OWLAxiom axiom,
OWLEntity referencedObject, Category category) {
return new InvalidReferenceViolation(axiom, referencedObject, category);
}



/**
* @return the axiom that contains the invalid reference
*/
public OWLAxiom getAxiom() {
return axiom;
}



/**
* @return the referencedObject that is either deprecated or dangling
*/
public OWLEntity getReferencedObject() {
return referencedObject;
}



/**
* @return the category of violation (deprecated or dangling)
*/
public Category getCategory() {
return category;
}



/**
* A reference may be invalid for different reasons
*
* - the referenced object may be deprecated
* - the referenced object may be dangling
*
* @author cjm
*
*/
public enum Category {
DANGLING, DEPRECATED
}



/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
// TODO: pretty-printer
return "InvalidReferenceViolation [axiom=" + axiom
+ ", referencedObject=" + referencedObject + ", category="
+ category + "]";
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.obolibrary.robot.exceptions;

import java.util.Set;

import org.obolibrary.robot.checks.InvalidReferenceViolation;
import org.semanticweb.owlapi.model.OWLClass;

/**
* Ontology contains unsatisfiable classes.
*
* @author cjm
*
*/
public class InvalidReferenceException extends OntologyStructureException {

/**
*
*/
private static final long serialVersionUID = -6157565029337883652L;

/**
* @param unsatisfiableClasses list of unsat classes
*/
public InvalidReferenceException(Set<InvalidReferenceViolation> violations) {
// TODO Auto-generated constructor stub
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.obolibrary.robot.exceptions;

/**
* Ontology contains contains structure that constitutes an exception
*
* Example: a logical axiom referencing a deprecated entity
*
* @author cjm
*
*/
public abstract class OntologyStructureException extends Exception {

/**
*
*/
private static final long serialVersionUID = 8211835056287159708L;
}
Loading