Skip to content

Commit

Permalink
Add control flag to structure walking to switch between not walking a…
Browse files Browse the repository at this point in the history
…nnotations, walking ontology annotations only, and walking all annotations.

The second case is the default if no flag is supplied, and provides the same behavior as before
If  ontology annotations are walked, recursive annotations will not be processed.
The current annotation will be set before the callback is run.
Annotations on an object are processed after the visitor callback, but before any fields specific to the object are walked;  thus a literal in annotation on a data property assertion will be handed to the callback before the literal in the assertion itself.

In a separate change,  constructors are added to OWLObjectWalker to allow lists of objects to be supplied instead of just sets.  Since the set is copied into a list before walking, this avoids having to turn a list of objects into a set prior to walking.
  • Loading branch information
sesuncedu committed Aug 16, 2015
1 parent ff53a52 commit 7906c57
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 111 deletions.
68 changes: 56 additions & 12 deletions api/src/main/java/org/semanticweb/owlapi/util/OWLObjectWalker.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import javax.annotation.Nullable;

import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.util.StructureWalker.AnnotationWalkingControl;
import static org.semanticweb.owlapi.util.StructureWalker.AnnotationWalkingControl.WALK_ONTOLOGY_ANNOTATIONS_ONLY;

/**
* @author Matthew Horridge, The University Of Manchester, Information
Expand All @@ -45,14 +47,66 @@ public class OWLObjectWalker<O extends OWLObject> {
private final List<OWLClassExpression> classExpressionPath = new ArrayList<>();
private final List<OWLDataRange> dataRangePath = new ArrayList<>();
@Nonnull
private StructureWalker<O> walker = new StructureWalker<>(this);
private StructureWalker<O> walker;

/**
* @param objects
* the set of objects to visit
* Visit duplicates.
* Only walk ontology anotations.
*/
public OWLObjectWalker(@Nonnull Set<O> objects) {
this(objects, true);
this(objects, WALK_ONTOLOGY_ANNOTATIONS_ONLY);
}

/**
* @param objects
* the list of objects to visit
*/

public OWLObjectWalker(@Nonnull List<O> objects) {
this(objects, WALK_ONTOLOGY_ANNOTATIONS_ONLY);
}

/**
* @param visitDuplicates
* true if duplicates should be visited
* @param objects
* the set of objects to visit
* Only walk ontology annotations.
*/

public OWLObjectWalker(@Nonnull Set<O> objects, boolean visitDuplicates) {
this(objects, visitDuplicates, WALK_ONTOLOGY_ANNOTATIONS_ONLY);
}

/**
* @param visitDuplicates
* true if duplicates should be visited
* @param objects
* the list of objects to visit
*/

public OWLObjectWalker(@Nonnull List<O> objects, boolean visitDuplicates) {
this(objects, visitDuplicates, WALK_ONTOLOGY_ANNOTATIONS_ONLY);
}

public OWLObjectWalker(@Nonnull Set<O> objects,AnnotationWalkingControl walkFlag) {
this(objects, true, walkFlag);
}

public OWLObjectWalker(@Nonnull List<O> objects,AnnotationWalkingControl walkFlag) {
this(objects, true, walkFlag);
}

public OWLObjectWalker(@Nonnull Set<O> objects, boolean visitDuplicates, AnnotationWalkingControl walkFlag) {
this(new ArrayList<O>(checkNotNull(objects, "objects cannot be null")),visitDuplicates, walkFlag);
}

public OWLObjectWalker(@Nonnull List<O> objects, boolean visitDuplicates, AnnotationWalkingControl walkFlag) {
this.objects = checkNotNull(objects, "objects cannot be null");
this.visitDuplicates = visitDuplicates;
this.walker = new StructureWalker<>(this, walkFlag);
}

protected Object passToVisitor(OWLObject o) {
Expand All @@ -75,16 +129,6 @@ protected void setVisitor(OWLObjectVisitor visitor) {
visitorEx = null;
}

/**
* @param visitDuplicates
* true if duplicates should be visited
* @param objects
* the set of objects to visit
*/
public OWLObjectWalker(@Nonnull Set<O> objects, boolean visitDuplicates) {
this.objects = new ArrayList<>(checkNotNull(objects, "objects cannot be null"));
this.visitDuplicates = visitDuplicates;
}

/**
* @param walker
Expand Down
146 changes: 47 additions & 99 deletions api/src/main/java/org/semanticweb/owlapi/util/StructureWalker.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,100 +17,8 @@

import javax.annotation.Nonnull;

import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLAnnotationPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLAnonymousIndividual;
import org.semanticweb.owlapi.model.OWLAsymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
import org.semanticweb.owlapi.model.OWLDataComplementOf;
import org.semanticweb.owlapi.model.OWLDataExactCardinality;
import org.semanticweb.owlapi.model.OWLDataHasValue;
import org.semanticweb.owlapi.model.OWLDataIntersectionOf;
import org.semanticweb.owlapi.model.OWLDataMaxCardinality;
import org.semanticweb.owlapi.model.OWLDataMinCardinality;
import org.semanticweb.owlapi.model.OWLDataOneOf;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLDataPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLDataUnionOf;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLDatatypeDefinitionAxiom;
import org.semanticweb.owlapi.model.OWLDatatypeRestriction;
import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
import org.semanticweb.owlapi.model.OWLDifferentIndividualsAxiom;
import org.semanticweb.owlapi.model.OWLDisjointClassesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointDataPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLDisjointUnionAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentDataPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLEquivalentObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLFacetRestriction;
import org.semanticweb.owlapi.model.OWLFunctionalDataPropertyAxiom;
import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLHasKeyAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLIrreflexiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLNegativeDataPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLNegativeObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
import org.semanticweb.owlapi.model.OWLObjectHasSelf;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectInverseOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectOneOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLObjectVisitor;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLReflexiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLSameIndividualAxiom;
import org.semanticweb.owlapi.model.OWLSubAnnotationPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.OWLSubDataPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
import org.semanticweb.owlapi.model.OWLSymmetricObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.SWRLAtom;
import org.semanticweb.owlapi.model.SWRLBuiltInAtom;
import org.semanticweb.owlapi.model.SWRLClassAtom;
import org.semanticweb.owlapi.model.SWRLDArgument;
import org.semanticweb.owlapi.model.SWRLDataPropertyAtom;
import org.semanticweb.owlapi.model.SWRLDataRangeAtom;
import org.semanticweb.owlapi.model.SWRLDifferentIndividualsAtom;
import org.semanticweb.owlapi.model.SWRLIndividualArgument;
import org.semanticweb.owlapi.model.SWRLLiteralArgument;
import org.semanticweb.owlapi.model.SWRLObjectPropertyAtom;
import org.semanticweb.owlapi.model.SWRLRule;
import org.semanticweb.owlapi.model.SWRLSameIndividualAtom;
import org.semanticweb.owlapi.model.SWRLVariable;
import org.semanticweb.owlapi.model.*;
import static org.semanticweb.owlapi.util.StructureWalker.AnnotationWalkingControl.*;

/**
* Structure walker for object walkers.
Expand All @@ -120,15 +28,42 @@
*/
public class StructureWalker<O extends OWLObject> implements OWLObjectVisitor {

/**
* Control flag for whether to walk annotations
*/
public static enum AnnotationWalkingControl {
/**
* Do not walk any annotations
*/
DONT_WALK_ANNOTATIONS,
/**
* Only walk ontology annotations (previous behaviour)
*/
WALK_ONTOLOGY_ANNOTATIONS_ONLY,
/**
* Walk all annotations
*/
WALK_ANNOTATIONS
}

protected final OWLObjectWalker<O> walkerCallback;
protected final Set<OWLObject> visited = new HashSet<>();
protected final AnnotationWalkingControl annotationWalkFlag;

public StructureWalker(OWLObjectWalker<O> owlObjectWalker) {
this(owlObjectWalker, WALK_ONTOLOGY_ANNOTATIONS_ONLY);
}

/**
* @param owlObjectWalker
* callback object walker
* @param annotationWalkFlag
* control flag for annotation walking
*/
public StructureWalker(OWLObjectWalker<O> owlObjectWalker) {
walkerCallback = owlObjectWalker;
public StructureWalker(OWLObjectWalker<O> owlObjectWalker,
AnnotationWalkingControl annotationWalkFlag) {
this.walkerCallback = owlObjectWalker;
this.annotationWalkFlag = annotationWalkFlag;
}

protected void process(@Nonnull OWLObject object) {
Expand All @@ -146,6 +81,22 @@ protected void process(@Nonnull OWLObject object) {
} else {
walkerCallback.passToVisitor(object);
}
if (object instanceof HasAnnotations) {
HasAnnotations hasAnnotations = (HasAnnotations) object;
switch(annotationWalkFlag) {
case DONT_WALK_ANNOTATIONS:
break;
case WALK_ONTOLOGY_ANNOTATIONS_ONLY:
if (!(object instanceof OWLOntology)) {
break;
}
// fall-through
case WALK_ANNOTATIONS:
for (OWLAnnotation anno : hasAnnotations.getAnnotations()) {
anno.accept(this);
}
}
}
}

@Override
Expand All @@ -158,9 +109,6 @@ public void visit(OWLOntology ontology) {
walkerCallback.ontology = ontology;
walkerCallback.ax = null;
process(ontology);
for (OWLAnnotation anno : ontology.getAnnotations()) {
anno.accept(this);
}
for (OWLAxiom a : ontology.getAxioms()) {
a.accept(this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.semanticweb.owlapi.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.semanticweb.owlapi.api.test.baseclasses.TestBase;
import org.semanticweb.owlapi.model.AddOntologyAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectVisitor;
import org.semanticweb.owlapi.model.OWLOntology;
import static org.semanticweb.owlapi.util.StructureWalker.AnnotationWalkingControl.DONT_WALK_ANNOTATIONS;
import static org.semanticweb.owlapi.util.StructureWalker.AnnotationWalkingControl.WALK_ANNOTATIONS;
import static org.semanticweb.owlapi.util.StructureWalker.AnnotationWalkingControl.WALK_ONTOLOGY_ANNOTATIONS_ONLY;

/**
* Created by ses on 8/15/15.
*/
public class OWLObjectWalkerTest extends TestBase {

private OWLAnnotation world;
private OWLAnnotation cruelWorld;
private OWLAnnotationProperty ap;
private OWLAnnotation goodbye;
private OWLAnnotation hello;

@Before
public void setUp() throws Exception {
this.ap = df.getOWLAnnotationProperty(iri("ap"));
this.cruelWorld = df.getOWLAnnotation(ap, df.getOWLLiteral("cruel world"));
this.goodbye = df.getOWLAnnotation(ap, df.getOWLLiteral("goodbye"), singleton(cruelWorld));
this.world = df.getOWLAnnotation(ap, df.getOWLLiteral("world"));
this.hello = df.getOWLAnnotation(ap, df.getOWLLiteral("hello"), singleton(world));
}

@Test
public void testWalkAnnotations() throws Exception {
OWLOntology o = getOwlOntology();
List<OWLAnnotation> emptyAnnotationList = Collections.emptyList();
checkWalkWithFlags(o, DONT_WALK_ANNOTATIONS, emptyAnnotationList);
checkWalkWithFlags(o, WALK_ONTOLOGY_ANNOTATIONS_ONLY, Arrays.asList(hello));
checkWalkWithFlags(o, WALK_ANNOTATIONS, Arrays.asList(hello, world, goodbye, cruelWorld));
}

private void checkWalkWithFlags(OWLOntology o, StructureWalker.AnnotationWalkingControl walkFlag, List<OWLAnnotation> expected) {
final List<OWLAnnotation> visitedAnnotations = new ArrayList<>();

OWLObjectVisitor visitor = new OWLObjectVisitorAdapter() {
@Override
public void visit(OWLAnnotation node) {
visitedAnnotations.add(node);
}
};

Set<? extends OWLObject> ontologySet = Collections.singleton(o);
OWLObjectWalker<? extends OWLObject> walker;
if (walkFlag == WALK_ONTOLOGY_ANNOTATIONS_ONLY) {
walker = new OWLObjectWalker<>(ontologySet);
} else {
walker = new OWLObjectWalker<>(ontologySet, walkFlag);
}
walker.walkStructure(visitor);
assertEquals(expected, visitedAnnotations);
}

@Nonnull
private OWLOntology getOwlOntology() {
OWLOntology o = getOWLOntology("foo");
m.applyChange(new AddOntologyAnnotation(o, hello));
addAxiom(o, df.getOWLDeclarationAxiom(ap, singleton(goodbye)));
return o;
}
}

0 comments on commit 7906c57

Please sign in to comment.