/******************************************************************************* * This file is part of ecco. * * ecco is distributed under the terms of the GNU Lesser General Public License (LGPL), Version 3.0. * * Copyright 2011-2014, The University of Manchester * * ecco is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * ecco is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with ecco. * If not, see http://www.gnu.org/licenses/. ******************************************************************************/ package uk.ac.manchester.cs.diff.axiom; import java.util.HashSet; import java.util.Set; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLLogicalAxiom; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLSubClassOfAxiom; import uk.ac.manchester.cs.diff.axiom.changeset.StructuralChangeSet; import uk.ac.manchester.cs.diff.output.csv.CSVAxiomDiffReport; import uk.ac.manchester.cs.diff.output.xml.XMLAxiomDiffReport; /** * @author Rafael S. Goncalves <br> * Information Management Group (IMG) <br> * School of Computer Science <br> * University of Manchester <br> */ public class StructuralDiff implements AxiomDiff { private OWLOntology ont1, ont2; private String ont1name, ont2name; private StructuralChangeSet changeSet; private double diffTime; private boolean verbose; /** * Constructor * @param ont1 Ontology 1 * @param ont2 Ontology 2 * @param verbose true if detailed output should be printed, false otherwise */ public StructuralDiff(OWLOntology ont1, OWLOntology ont2, boolean verbose) { this.ont1 = ont1; this.ont2 = ont2; this.verbose = verbose; } /** * Constructor 2 * @param ont1 Ontology 1 * @param ont2 Ontology 2 * @param ont1name Ontology 1 filename * @param ont2name Ontology 2 filename * @param verbose true if detailed output should be printed, false otherwise */ public StructuralDiff(OWLOntology ont1, OWLOntology ont2, String ont1name, String ont2name, boolean verbose) { this.ont1 = ont1; this.ont2 = ont2; this.ont1name = ont1name; this.ont2name = ont2name; this.verbose = verbose; } /** * Get structural changes between ontologies * @return Structural change set */ @SuppressWarnings("deprecation") public StructuralChangeSet getDiff() { if(changeSet != null) return changeSet; if(verbose) System.out.print(" Computing structural differences... "); Set<OWLLogicalAxiom> o1axs = ont1.getLogicalAxioms(); Set<OWLLogicalAxiom> o2axs = ont2.getLogicalAxioms(); Set<OWLAxiom> additions = new HashSet<OWLAxiom>(); Set<OWLAxiom> removals = new HashSet<OWLAxiom>(); Set<OWLAxiom> shared = new HashSet<OWLAxiom>(); long start = System.currentTimeMillis(); for(OWLAxiom ax : o1axs) { if(!o2axs.contains(ax)) { if(ax instanceof OWLSubClassOfAxiom) { if(!((OWLSubClassOfAxiom)ax).getSuperClass().isTopEntity()) removals.add(ax); } else removals.add(ax); } else shared.add(ax); } o2axs.removeAll(shared); for(OWLAxiom ax : o2axs) { if(!o1axs.contains(ax)) { if(ax instanceof OWLSubClassOfAxiom) { if(!((OWLSubClassOfAxiom)ax).getSuperClass().isTopEntity()) additions.add(ax); } else additions.add(ax); } else shared.add(ax); } long end = System.currentTimeMillis(); diffTime = (end-start)/1000.0; changeSet = new StructuralChangeSet(additions, removals, shared); addOntologyFileNames(); changeSet.setDiffTime(diffTime); if(verbose) System.out.println("done (" + diffTime + " secs)"); if(verbose) printDiff(); return changeSet; } /** * Print diff results */ public void printDiff() { System.out.println( "\tAdditions: " + changeSet.getAddedAxioms().size() + "\n\tRemovals: " + changeSet.getRemovedAxioms().size() + "\n\tShared: " + changeSet.getShared().size()); } /** * Record file names of given ontologies in the change set */ @SuppressWarnings("deprecation") private void addOntologyFileNames() { if(ont1name == null) changeSet.setOntologyName(1, "Ont1"); else changeSet.setOntologyName(1, ont1name); if(ont2name == null) changeSet.setOntologyName(2, "Ont2"); else changeSet.setOntologyName(2, ont2name); } /** * Get an XML change report for the change set computed by this diff * @return XML change report object */ public XMLAxiomDiffReport getXMLReport() { if(changeSet == null) changeSet = getDiff(); return new XMLAxiomDiffReport(ont1, ont2, changeSet); } /** * Get a CSV change report * @return Change report as a CSV document */ public String getCSVChangeReport() { if(changeSet == null) changeSet = getDiff(); return new CSVAxiomDiffReport().getReport(changeSet); } /** * Determine if ontologies are structurally equivalent (thus logically equivalent) * @return true if ontologies are structurally equivalent, false otherwise */ public boolean isEquivalent() { if(changeSet == null) changeSet = getDiff(); if(changeSet.isEmpty()) return true; else return false; } /** * Get the time to compute the diff * @return Diff time (in seconds) */ public double getDiffTime() { return diffTime; } }