package org.mindswap.swoop.utils.owlapi.diff;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.semanticweb.owl.model.OWLAnnotationInstance;
import org.semanticweb.owl.model.OWLAnnotationProperty;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLClassAxiom;
import org.semanticweb.owl.model.OWLClassAxiomVisitor;
import org.semanticweb.owl.model.OWLDataFactory;
import org.semanticweb.owl.model.OWLDataProperty;
import org.semanticweb.owl.model.OWLDataPropertyRangeAxiom;
import org.semanticweb.owl.model.OWLDataRange;
import org.semanticweb.owl.model.OWLDataType;
import org.semanticweb.owl.model.OWLDataValue;
import org.semanticweb.owl.model.OWLDescription;
import org.semanticweb.owl.model.OWLDifferentIndividualsAxiom;
import org.semanticweb.owl.model.OWLDisjointClassesAxiom;
import org.semanticweb.owl.model.OWLEntity;
import org.semanticweb.owl.model.OWLEntityVisitor;
import org.semanticweb.owl.model.OWLEnumeration;
import org.semanticweb.owl.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owl.model.OWLEquivalentPropertiesAxiom;
import org.semanticweb.owl.model.OWLException;
import org.semanticweb.owl.model.OWLFunctionalPropertyAxiom;
import org.semanticweb.owl.model.OWLIndividual;
import org.semanticweb.owl.model.OWLIndividualAxiom;
import org.semanticweb.owl.model.OWLIndividualAxiomVisitor;
import org.semanticweb.owl.model.OWLInverseFunctionalPropertyAxiom;
import org.semanticweb.owl.model.OWLInversePropertyAxiom;
import org.semanticweb.owl.model.OWLObject;
import org.semanticweb.owl.model.OWLObjectProperty;
import org.semanticweb.owl.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owl.model.OWLOntology;
import org.semanticweb.owl.model.OWLProperty;
import org.semanticweb.owl.model.OWLPropertyAxiom;
import org.semanticweb.owl.model.OWLPropertyAxiomVisitor;
import org.semanticweb.owl.model.OWLPropertyDomainAxiom;
import org.semanticweb.owl.model.OWLSameIndividualsAxiom;
import org.semanticweb.owl.model.OWLSubClassAxiom;
import org.semanticweb.owl.model.OWLSubPropertyAxiom;
import org.semanticweb.owl.model.OWLSymmetricPropertyAxiom;
import org.semanticweb.owl.model.OWLTransitivePropertyAxiom;
import org.semanticweb.owl.model.change.RemoveAnnotationInstance;
import org.semanticweb.owl.model.change.RemoveClassAxiom;
import org.semanticweb.owl.model.change.RemoveDataPropertyInstance;
import org.semanticweb.owl.model.change.RemoveDataPropertyRange;
import org.semanticweb.owl.model.change.RemoveDataType;
import org.semanticweb.owl.model.change.RemoveDomain;
import org.semanticweb.owl.model.change.RemoveEntity;
import org.semanticweb.owl.model.change.RemoveEnumeration;
import org.semanticweb.owl.model.change.RemoveIndividualAxiom;
import org.semanticweb.owl.model.change.RemoveIndividualClass;
import org.semanticweb.owl.model.change.RemoveObjectPropertyInstance;
import org.semanticweb.owl.model.change.RemoveObjectPropertyRange;
import org.semanticweb.owl.model.change.RemovePropertyAxiom;
import org.semanticweb.owl.model.change.RemoveSuperClass;
import org.semanticweb.owl.model.change.RemoveSuperProperty;
import org.semanticweb.owl.model.change.SetDeprecated;
import org.semanticweb.owl.model.change.SetFunctional;
import org.semanticweb.owl.model.change.SetInverseFunctional;
import org.semanticweb.owl.model.change.SetOneToOne;
import org.semanticweb.owl.model.change.SetSymmetric;
import org.semanticweb.owl.model.change.SetTransitive;
public class NegativeDiff implements OWLEntityVisitor, OWLClassAxiomVisitor,
OWLPropertyAxiomVisitor, OWLIndividualAxiomVisitor {
/**
* Get the differences as a set of OWLChanges, ready to apply to the
* target.
* @param source The source ontology
* @param destination The destination ontology
* @param target The OWLOntology the changes should be applied to.
* @return
* @throws OWLException
*/
public static List getChanges(OWLOntology source, OWLOntology destination, OWLOntology target) throws OWLException {
NegativeDiff ndiff = new NegativeDiff(source, destination);
return ndiff.getChanges(target);
}
private List changes;
private OWLCopy copier;
private OWLOntology destination;
private OWLDataFactory factory;
private OWLOntology source;
private OWLOntology target;
public NegativeDiff(OWLOntology source, OWLOntology destination) {
this.source = source;
this.destination = destination;
changes = new Vector();
}
/**
* Remove any excess annotations an object might have.
* @param src
* @param dst
* @param tgt
* @throws OWLException
*/
protected void annotationRemover(OWLObject src, OWLObject dst, OWLObject tgt) throws OWLException {
Set srcAnnotations = src.getAnnotations(source);
Set dstAnnotations = dst.getAnnotations(destination);
for (Iterator iter = srcAnnotations.iterator(); iter.hasNext();) {
OWLAnnotationInstance annotation = (OWLAnnotationInstance) iter.next();
if (!dstAnnotations.contains(annotation)) {
OWLAnnotationProperty tgtProp = (OWLAnnotationProperty) copier.copy(annotation.getProperty());
changes.add(new RemoveAnnotationInstance(target, tgt, tgtProp, annotation.getContent(), null));
}
}
}
/**
* Adds changes between OWLProperties (not Data or Object property specific changes)
* @param src
* @param dst
* @param tgt
* @throws OWLException
*/
private void genericPropertyChanges(OWLProperty entity, OWLProperty dstEntity, OWLProperty tgtEntity) throws OWLException {
annotationRemover(entity, dstEntity, tgtEntity);
if (entity.isDeprecated(source) && !dstEntity.isDeprecated(destination)) {
changes.add(new SetDeprecated(target, tgtEntity, false, null));
}
if (entity.isFunctional(source) && !dstEntity.isFunctional(destination)) {
changes.add(new SetFunctional(target, tgtEntity, false, null));
}
for (Iterator iter = entity.getDomains(source).iterator(); iter.hasNext(); ) {
OWLDescription desc = (OWLDescription) iter.next();
if (!dstEntity.getDomains(destination).contains(desc)) {
OWLDescription tgtDesc = copier.copy(desc);
changes.add(new RemoveDomain(target, tgtEntity, tgtDesc, null));
}
}
for (Iterator iter = entity.getSuperProperties(source).iterator(); iter.hasNext();) {
OWLProperty prop = (OWLProperty) iter.next();
if (!dstEntity.getSuperProperties(destination).contains(prop)) {
OWLProperty tgtProp = (OWLProperty) copier.copy(prop);
changes.add(new RemoveSuperProperty(target, tgtEntity, tgtProp, null));
}
}
}
/**
* Get the differences as a set of OWLChanges, ready to apply to the
* target.
* @param target The OWLOntology the changes should be applied to.
* @return
* @throws OWLException
*/
public List getChanges(OWLOntology target) throws OWLException {
changes = new Vector();
this.target = target;
factory = target.getOWLDataFactory();
copier = new OWLCopy(source, target);
Set entities = new HashSet();
entities.addAll(source.getClasses());
entities.addAll(source.getIndividuals());
entities.addAll(source.getAnnotationProperties());
entities.addAll(source.getDataProperties());
entities.addAll(source.getObjectProperties());
for (Iterator iter = entities.iterator(); iter.hasNext();) {
((OWLEntity) iter.next()).accept(this);
}
for (Iterator iter = source.getClassAxioms().iterator(); iter.hasNext();) {
((OWLClassAxiom) iter.next()).accept(this);
}
for (Iterator iter = source.getPropertyAxioms().iterator(); iter.hasNext();) {
((OWLPropertyAxiom) iter.next()).accept(this);
}
for (Iterator iter = source.getIndividualAxioms().iterator(); iter.hasNext();) {
((OWLIndividualAxiom) iter.next()).accept(this);
}
// Data types don't have a specific visitor, don't want all of OWLObjectVisitor
for (Iterator iter = source.getDatatypes().iterator(); iter.hasNext();) {
OWLDataType srcDT = (OWLDataType) iter.next();
if (!destination.getDatatypes().contains(srcDT)) {
OWLDataType tgtDT = factory.getOWLConcreteDataType(srcDT.getURI());
changes.add(new RemoveDataType(target, tgtDT, null));
}
}
return changes;
}
public void visit(OWLAnnotationProperty entity) throws OWLException {
OWLAnnotationProperty tgtEntity = factory.getOWLAnnotationProperty(entity.getURI());
OWLAnnotationProperty dstEntity = destination.getAnnotationProperty(entity.getURI());
if (dstEntity == null) {
changes.add(new RemoveEntity(target, tgtEntity, null));
dstEntity = destination.getOWLDataFactory().getOWLAnnotationProperty(entity.getURI());
}
annotationRemover(entity, dstEntity, tgtEntity);
}
public void visit(OWLClass entity) throws OWLException {
OWLClass tgtEntity = factory.getOWLClass(entity.getURI());
OWLClass dstEntity = destination.getClass(entity.getURI());
if (dstEntity == null) {
changes.add(new RemoveEntity(target, tgtEntity, null));
dstEntity = destination.getOWLDataFactory().getOWLClass(entity.getURI());
}
annotationRemover(entity, dstEntity, tgtEntity);
for (Iterator iter = entity.getEnumerations(source).iterator(); iter.hasNext();) {
OWLEnumeration srcEnum = (OWLEnumeration) iter.next();
if (!dstEntity.getEnumerations(destination).contains(srcEnum)) {
changes.add(new RemoveEnumeration(target, tgtEntity,
(OWLEnumeration) copier.copy(srcEnum), null));
}
}
for (Iterator iter = entity.getSuperClasses(source).iterator(); iter.hasNext();) {
OWLDescription desc = (OWLDescription) iter.next();
if (!dstEntity.getSuperClasses(destination).contains(desc)) {
changes.add(new RemoveSuperClass(target, tgtEntity,
copier.copy(desc), null));
}
}
}
public void visit(OWLDataProperty entity) throws OWLException {
OWLDataProperty tgtEntity = factory.getOWLDataProperty(entity.getURI());
OWLDataProperty dstEntity = destination.getDataProperty(entity.getURI());
if (dstEntity == null) {
changes.add(new RemoveEntity(target, tgtEntity, null));
dstEntity = destination.getOWLDataFactory().getOWLDataProperty(entity.getURI());
}
genericPropertyChanges(entity, dstEntity, tgtEntity);
for (Iterator iter = entity.getRanges(source).iterator(); iter.hasNext(); ) {
OWLDataRange range = (OWLDataRange) iter.next();
if (!dstEntity.getRanges(destination).contains(range)) {
OWLDataRange tgtRange = copier.copyDataRange(range);
changes.add(new RemoveDataPropertyRange(target, tgtEntity, tgtRange, null));
}
}
}
public void visit(OWLDataPropertyRangeAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLDataProperty tgtProperty = (OWLDataProperty) copier.copy(axiom.getProperty());
OWLDataRange tgtRange = copier.copyDataRange(axiom.getRange());
OWLPropertyAxiom tgtAxiom = factory.getOWLDataPropertyRangeAxiom(tgtProperty, tgtRange);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLDifferentIndividualsAxiom axiom) throws OWLException {
if (!destination.getIndividualAxioms().contains(axiom)) {
Set different = new HashSet();
for (Iterator iter = axiom.getIndividuals().iterator(); iter.hasNext(); ) {
different.add(copier.copy((OWLIndividual)iter.next()));
}
OWLIndividualAxiom tgtAxiom = factory.getOWLDifferentIndividualsAxiom(different);
changes.add(new RemoveIndividualAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLDisjointClassesAxiom axiom) throws OWLException {
if (!destination.getClassAxioms().contains(axiom)) {
Set disjoints = new HashSet();
for (Iterator iter = axiom.getDisjointClasses().iterator(); iter.hasNext(); ) {
disjoints.add(copier.copy((OWLDescription) iter.next()));
}
OWLClassAxiom tgtAxiom = factory.getOWLDisjointClassesAxiom(disjoints);
changes.add(new RemoveClassAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLEquivalentClassesAxiom axiom) throws OWLException {
if (!destination.getClassAxioms().contains(axiom)) {
Set equivalents = new HashSet();
for (Iterator iter = axiom.getEquivalentClasses().iterator(); iter.hasNext(); ) {
equivalents.add(copier.copy((OWLDescription) iter.next()));
}
OWLClassAxiom tgtAxiom = factory.getOWLEquivalentClassesAxiom(equivalents);
changes.add(new RemoveClassAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLEquivalentPropertiesAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
Set equivalents = new HashSet();
for (Iterator iter = axiom.getProperties().iterator(); iter.hasNext();) {
equivalents.add(copier.copy((OWLProperty) iter.next()));
}
OWLPropertyAxiom tgtAxiom = factory.getOWLEquivalentPropertiesAxiom(equivalents);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLFunctionalPropertyAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLProperty tgtProp = (OWLProperty) copier.copy(axiom.getProperty());
OWLPropertyAxiom tgtAxiom = factory.getOWLFunctionalPropertyAxiom(tgtProp);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLIndividual entity) throws OWLException {
OWLIndividual tgtEntity;
OWLIndividual dstEntity;
if (entity.isAnonymous()) {
tgtEntity = factory.getAnonOWLIndividual(entity.getAnonId());
dstEntity = destination.getIndividual(entity.getAnonId());
} else {
tgtEntity = factory.getOWLIndividual(entity.getURI());
dstEntity = destination.getIndividual(entity.getURI());
}
if (dstEntity == null) {
changes.add(new RemoveEntity(target, tgtEntity, null));
if (entity.isAnonymous()) {
dstEntity = destination.getOWLDataFactory().getAnonOWLIndividual(entity.getAnonId());
} else {
dstEntity = destination.getOWLDataFactory().getOWLIndividual(entity.getURI());
}
}
annotationRemover(entity, dstEntity, tgtEntity);
Set srcTypes = entity.getTypes(source);
Set dstTypes = dstEntity.getTypes(destination);
for (Iterator typeIter = srcTypes.iterator(); typeIter.hasNext();) {
OWLDescription srcType = (OWLDescription) typeIter.next();
if (!dstTypes.contains(srcType)) {
OWLDescription tgtType = copier.copy(srcType);
changes.add(new RemoveIndividualClass(target, tgtEntity,
tgtType, null));
}
}
Map srcProps = entity.getDataPropertyValues(source);
Map dstProps = dstEntity.getDataPropertyValues(destination);
for (Iterator propIter = srcProps.keySet().iterator(); propIter
.hasNext();) {
OWLDataProperty prop = (OWLDataProperty) propIter.next();
OWLDataProperty dstProp = destination.getOWLDataFactory().getOWLDataProperty(prop.getURI());
OWLDataProperty tgtProp = factory.getOWLDataProperty(prop.getURI());
Set srcValues = (Set) srcProps.get(prop);
Set dstValues = (Set) dstProps.get(dstProp);
if (dstValues == null) {
dstValues = Collections.EMPTY_SET;
}
for (Iterator valueIter = srcValues.iterator(); valueIter.hasNext();) {
OWLDataValue dv = (OWLDataValue) valueIter.next();
if (!dstValues.contains(dv)) {
OWLDataValue tgtDV = factory.getOWLConcreteData(
dv.getURI(), dv.getLang(), dv.getValue());
changes.add(new RemoveDataPropertyInstance(target,
tgtEntity, tgtProp, tgtDV, null));
}
}
}
srcProps = entity.getObjectPropertyValues(source);
dstProps = dstEntity.getObjectPropertyValues(destination);
for (Iterator propIter = srcProps.keySet().iterator(); propIter
.hasNext();) {
OWLObjectProperty prop = (OWLObjectProperty) propIter.next();
OWLObjectProperty dstProp = destination.getOWLDataFactory().getOWLObjectProperty(prop.getURI());
OWLObjectProperty tgtProp = factory.getOWLObjectProperty(prop.getURI());
Set srcValues = (Set) srcProps.get(prop);
Set dstValues = (Set) dstProps.get(dstProp);
if (dstValues == null) {
dstValues = Collections.EMPTY_SET;
}
for (Iterator valueIter = srcValues.iterator(); valueIter.hasNext();) {
OWLIndividual object = (OWLIndividual) valueIter.next();
OWLIndividual dstObject;
OWLIndividual tgtInd;
if (object.isAnonymous()) {
dstObject = destination.getOWLDataFactory().getAnonOWLIndividual(object.getAnonId());
tgtInd = factory.getAnonOWLIndividual(object.getAnonId());
} else {
dstObject = destination.getOWLDataFactory().getOWLIndividual(object.getURI());
tgtInd = factory.getOWLIndividual(object.getURI());
}
if (!dstValues.contains(dstObject)) {
changes.add(new RemoveObjectPropertyInstance(target,
tgtEntity, tgtProp, tgtInd, null));
}
}
}
}
public void visit(OWLInverseFunctionalPropertyAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLObjectProperty tgtProp = (OWLObjectProperty) copier.copy(axiom.getProperty());
OWLPropertyAxiom tgtAxiom = factory.getOWLInverseFunctionalPropertyAxiom(tgtProp);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLInversePropertyAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLObjectProperty tgtProp = (OWLObjectProperty) copier.copy(axiom.getProperty());
OWLObjectProperty tgtInverse = (OWLObjectProperty) copier.copy(axiom.getInverseProperty());
OWLPropertyAxiom tgtAxiom = factory.getOWLInversePropertyAxiom(tgtProp, tgtInverse);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLObjectProperty entity) throws OWLException {
OWLObjectProperty tgtEntity = factory.getOWLObjectProperty(entity.getURI());
OWLObjectProperty dstEntity = destination.getObjectProperty(entity.getURI());
if (dstEntity == null) {
changes.add(new RemoveEntity(target, tgtEntity, null));
dstEntity = destination.getOWLDataFactory().getOWLObjectProperty(entity.getURI());
}
genericPropertyChanges(entity, dstEntity, tgtEntity);
if (entity.isInverseFunctional(source) && !dstEntity.isInverseFunctional(destination)) {
changes.add(new SetInverseFunctional(target, tgtEntity, false, null));
}
if (entity.isSymmetric(source) && !dstEntity.isSymmetric(destination)) {
changes.add(new SetSymmetric(target, tgtEntity, false, null));
}
if (entity.isTransitive(source) && !dstEntity.isTransitive(destination)) {
changes.add(new SetTransitive(target, tgtEntity, false, null));
}
if (entity.isOneToOne(source) && !dstEntity.isOneToOne(destination)) {
changes.add(new SetOneToOne(target, tgtEntity, false, null));
}
for (Iterator iter = entity.getRanges(source).iterator(); iter.hasNext(); ) {
OWLDescription desc = (OWLDescription) iter.next();
if (!dstEntity.getRanges(destination).contains(desc)) {
OWLDescription tgtDesc = copier.copy(desc);
changes.add(new RemoveObjectPropertyRange(target, tgtEntity, tgtDesc, null));
}
}
}
public void visit(OWLObjectPropertyRangeAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLObjectProperty tgtProperty = (OWLObjectProperty) copier.copy(axiom.getProperty());
OWLDescription tgtRange = copier.copy(axiom.getRange());
OWLPropertyAxiom tgtAxiom = factory.getOWLObjectPropertyRangeAxiom(tgtProperty, tgtRange);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLPropertyDomainAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLProperty tgtProperty = (OWLProperty) copier.copy(axiom.getProperty());
OWLDescription tgtDomain = copier.copy(axiom.getDomain());
OWLPropertyAxiom tgtAxiom = factory.getOWLPropertyDomainAxiom(tgtProperty, tgtDomain);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLSameIndividualsAxiom axiom) throws OWLException {
if (!destination.getIndividualAxioms().contains(axiom)) {
Set equivalents = new HashSet();
for (Iterator iter = axiom.getIndividuals().iterator(); iter.hasNext(); ) {
equivalents.add(copier.copy((OWLIndividual)iter.next()));
}
OWLIndividualAxiom tgtAxiom = factory.getOWLSameIndividualsAxiom(equivalents);
changes.add(new RemoveIndividualAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLSubClassAxiom axiom) throws OWLException {
if (!destination.getClassAxioms().contains(axiom)) {
OWLDescription subClass = copier.copy(axiom.getSubClass());
OWLDescription superClass = copier.copy(axiom.getSuperClass());
OWLClassAxiom tgtAxiom = factory.getOWLSubClassAxiom(subClass, superClass);
changes.add(new RemoveClassAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLSubPropertyAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLProperty subProp = (OWLProperty) copier.copy(axiom.getSubProperty());
OWLProperty superProp = (OWLProperty) copier.copy(axiom.getSuperProperty());
OWLPropertyAxiom tgtAxiom = factory.getOWLSubPropertyAxiom(subProp, superProp);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLSymmetricPropertyAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLObjectProperty tgtProp = (OWLObjectProperty) copier.copy(axiom.getProperty());
OWLPropertyAxiom tgtAxiom = factory.getOWLSymmetricPropertyAxiom(tgtProp);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
public void visit(OWLTransitivePropertyAxiom axiom) throws OWLException {
if (!destination.getPropertyAxioms().contains(axiom)) {
OWLObjectProperty tgtProp = (OWLObjectProperty) copier.copy(axiom.getProperty());
OWLPropertyAxiom tgtAxiom = factory.getOWLTransitivePropertyAxiom(tgtProp);
changes.add(new RemovePropertyAxiom(target, tgtAxiom, null));
}
}
}