/******************************************************************************* * 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.output.xml; import java.util.Map; import java.util.Set; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.util.ShortFormProvider; import org.w3c.dom.Document; import org.w3c.dom.Element; import uk.ac.manchester.cs.diff.axiom.change.CategorisedChange; import uk.ac.manchester.cs.diff.axiom.change.CategorisedEffectualChange; import uk.ac.manchester.cs.diff.axiom.changeset.AxiomChangeSet; import uk.ac.manchester.cs.diff.concept.change.ConceptChange; import uk.ac.manchester.cs.diff.unity.changeset.AlignedChangeSet; import uk.ac.manchester.cs.diff.unity.changeset.AlignedDirectChangeSet; import uk.ac.manchester.cs.diff.unity.changeset.AlignedIndirectChangeSet; /** * @author Rafael S. Goncalves <br> * Information Management Group (IMG) <br> * School of Computer Science <br> * University of Manchester <br> */ public class XMLUnifiedDiffReport extends XMLAxiomDiffReport { private Map<OWLAxiom,Set<? extends ConceptChange>> ont1DirSpec, ont1DirGen, ont2DirSpec, ont2DirGen; private Map<OWLAxiom,Set<? extends ConceptChange>> ont1IndirSpec, ont1IndirGen, ont2IndirSpec, ont2IndirGen; /** * Constructor * @param ont1 Ontology 1 * @param ont2 Ontology 2 * @param changeSet Change set * @param alignedChangeSet Aligned change set */ public XMLUnifiedDiffReport(OWLOntology ont1, OWLOntology ont2, AxiomChangeSet changeSet, AlignedChangeSet alignedChangeSet) { super(ont1, ont2, changeSet); assignMaps(alignedChangeSet); } /** * Get the direct and indirect change maps * @param directChanges Aligned direct change set * @param indirectChanges Aligned indirect change set */ private void assignMaps(AlignedChangeSet alignedChangeSet) { AlignedDirectChangeSet directChanges = alignedChangeSet.getDirectChangeSet(); ont1DirSpec = directChanges.getOnt1SpecialisationsMap(); ont1DirGen = directChanges.getOnt1GeneralisationsMap(); ont2DirSpec = directChanges.getOnt2SpecialisationsMap(); ont2DirGen = directChanges.getOnt2GeneralisationsMap(); AlignedIndirectChangeSet indirectChanges = alignedChangeSet.getIndirectChangeSet(); ont1IndirSpec = indirectChanges.getOnt1SpecialisationsMap(); ont1IndirGen = indirectChanges.getOnt1GeneralisationsMap(); ont2IndirSpec = indirectChanges.getOnt2SpecialisationsMap(); ont2IndirGen = indirectChanges.getOnt2GeneralisationsMap(); } /** * Add a change element, which contains an axiom child element * @param id Id of the change element * @param change Categorised change object * @param d Document to be added to * @param parent Parent element of the change element * @param sf Short form provider */ @Override public void addAxiomChange(String id, CategorisedChange change, Document d, String parent, ShortFormProvider sf) { Element ele = d.createElement("Change"); ele.setAttribute("id", id); ele.setIdAttribute("id", true); Element root = d.getElementById(parent); root.appendChild(ele); Element axEle = d.createElement("Axiom"); OWLAxiom axiom = change.getAxiom(); axEle.setTextContent(getManchesterRendering(axiom, sf)); ele.appendChild(axEle); checkAndAddEffect(axiom, d, ele, sf); appendEffectualChange((CategorisedEffectualChange)change, d, ele, sf); } /** * Check whether the axiom affected any concepts, and if so add the affected concepts * @param axiom Axiom being checked * @param d XML document * @param parent Parent element to append the effect, if applicable * @param sf Short form provider */ private void checkAndAddEffect(OWLAxiom axiom, Document d, Element parent, ShortFormProvider sf) { Element effEle = d.createElement("ConceptChanges"); Element direct = d.createElement("DirectChanges"); Element indirect = d.createElement("IndirectChanges"); int nrDir = addDirectChanges(axiom, direct, d, sf); direct.setAttribute("size", "" + nrDir); int nrIndir = addIndirectChanges(axiom, indirect, d, sf); indirect.setAttribute("size", "" + nrIndir); int total = nrDir + nrIndir; effEle.setAttribute("size", "" + total); effEle.appendChild(direct); effEle.appendChild(indirect); parent.appendChild(effEle); } /** * Add direct concept changes caused by the given axiom, and get the total number of changes * @param axiom Axiom * @param parent Parent element in the document * @param d XML document * @param sf Short form provider * @return Number of direct concept changes caused by the given axiom */ @SuppressWarnings("unchecked") private int addDirectChanges(OWLAxiom axiom, Element parent, Document d, ShortFormProvider sf) { int nrChanges = 0; if(ont1DirSpec.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont1DirSpec.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Specialisation", true, parent, d, sf); } if(ont1DirGen.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont1DirGen.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Generalisation", true, parent, d, sf); } if(ont2DirSpec.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont2DirSpec.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Specialisation", true, parent, d, sf); } if(ont2DirGen.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont2DirGen.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Generalisation", true, parent, d, sf); } return nrChanges; } /** * Add indirect concept changes caused by the given axiom, and get the total number of changes * @param axiom Asserted axiom change * @param parent Parent element in the document * @param d XML document * @param sf Short form provider * @return Number of indirect concept changes caused by the given axiom */ @SuppressWarnings("unchecked") private int addIndirectChanges(OWLAxiom axiom, Element parent, Document d, ShortFormProvider sf) { int nrChanges = 0; if(ont1IndirSpec.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont1IndirSpec.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Specialisation", false, parent, d, sf); } if(ont1IndirGen.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont1IndirGen.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Generalisation", false, parent, d, sf); } if(ont2IndirSpec.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont2IndirSpec.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Specialisation", false, parent, d, sf); } if(ont2IndirGen.containsKey(axiom)) { Set<ConceptChange> changes = (Set<ConceptChange>) ont2IndirGen.get(axiom); nrChanges += changes.size(); addConceptChanges(axiom, changes, "Generalisation", false, parent, d, sf); } return nrChanges; } /** * Add set of concepts to the given element * @param axiomChange Asserted axiom change * @param concepts Set of concept changes * @param type Specialisation or generalisation * @param direct true if handling directly changed concepts * @param parent Element to append concept elements to * @param d XML document * @param sf Short form provider */ private void addConceptChanges(OWLAxiom axiomChange, Set<ConceptChange> concepts, String type, boolean direct, Element parent, Document d, ShortFormProvider sf) { for(ConceptChange c : concepts) { Element change = d.createElement(type); Element concept = d.createElement("Concept"); concept.setTextContent(getManchesterRendering(c.getConcept(), sf)); change.appendChild(concept); Set<OWLAxiom> witnesses = null; if(type.equalsIgnoreCase("Specialisation")) { if(direct) witnesses = c.getDirectSpecialisationWitnessesForAxiom(axiomChange); else witnesses = c.getIndirectSpecialisationWitnessesForAxiom(axiomChange); } else if(type.equals("Generalisation")) { if(direct) witnesses = c.getDirectGeneralisationWitnessesForAxiom(axiomChange); else witnesses = c.getIndirectGeneralisationWitnessesForAxiom(axiomChange); } if(witnesses != null) { addWitnesses(witnesses, change, d, sf); parent.appendChild(change); } } } /** * Add a set of witnesses to a concept change * @param witnesses Set of witnesses for a change to some concept * @param parent Parent element to append to * @param d XML document * @param sf Short form provider */ private void addWitnesses(Set<OWLAxiom> witnesses, Element parent, Document d, ShortFormProvider sf) { Element witEle = d.createElement("WitnessAxioms"); for(OWLAxiom ax : witnesses) { Element axEle = d.createElement("Axiom"); axEle.setTextContent(getManchesterRendering(ax, sf)); witEle.appendChild(axEle); } parent.appendChild(witEle); } }