/*******************************************************************************
* 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.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.semanticweb.owl.explanation.api.Explanation;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.util.ShortFormProvider;
import org.semanticweb.owlapi.util.SimpleShortFormProvider;
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.CategorisedEffectualAddition;
import uk.ac.manchester.cs.diff.axiom.change.CategorisedEffectualChange;
import uk.ac.manchester.cs.diff.axiom.change.CategorisedEffectualRemoval;
import uk.ac.manchester.cs.diff.axiom.change.CategorisedIneffectualAddition;
import uk.ac.manchester.cs.diff.axiom.change.CategorisedIneffectualRemoval;
import uk.ac.manchester.cs.diff.axiom.change.CategorisedIneffectualAddition.IneffectualAdditionCategory;
import uk.ac.manchester.cs.diff.axiom.change.CategorisedIneffectualRemoval.IneffectualRemovalCategory;
import uk.ac.manchester.cs.diff.axiom.changeset.AxiomChangeSet;
import uk.ac.manchester.cs.diff.axiom.changeset.CategorisedChangeSet;
import uk.ac.manchester.cs.diff.axiom.changeset.LogicalChangeSet;
import uk.ac.manchester.cs.diff.axiom.changeset.StructuralChangeSet;
import uk.ac.manchester.cs.diff.output.GenSymShortFormProvider;
import uk.ac.manchester.cs.diff.output.LabelShortFormProvider;
import uk.ac.manchester.cs.owl.owlapi.mansyntaxrenderer.ManchesterOWLSyntaxObjectRenderer;
/**
* @author Rafael S. Goncalves <br>
* Information Management Group (IMG) <br>
* School of Computer Science <br>
* University of Manchester <br>
*/
public class XMLAxiomDiffReport implements XMLDiffReport {
protected final String uuid = UUID.randomUUID().toString();
protected SimpleShortFormProvider sf;
protected GenSymShortFormProvider gp;
protected LabelShortFormProvider lp;
protected Document doc, genSymDoc, labelDoc;
protected HashMap<OWLEntity, String> genSymMap, labelMap;
protected HashMap<OWLAxiom,Integer> axiomIds;
protected OWLOntology ont1, ont2;
protected OWLDataFactory df;
protected DocumentBuilderFactory dbfac;
protected DocumentBuilder docBuilder;
protected AxiomChangeSet changeSet;
protected int changeNr = 1;
protected Set<OWLAxiom> sharedAxioms;
/**
* Constructor
* @param ont1 Ontology 1
* @param ont2 Ontology 2
* @param changeSet Change set
*/
public XMLAxiomDiffReport(OWLOntology ont1, OWLOntology ont2, AxiomChangeSet changeSet) {
this.ont1 = ont1;
this.ont2 = ont2;
this.dbfac = DocumentBuilderFactory.newInstance();
this.changeSet = changeSet;
initMapsAndSFPs();
}
/**
* Initialise labels and gensyms maps, and short form providers
*/
private void initMapsAndSFPs() {
try {
this.docBuilder = dbfac.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
df = ont1.getOWLOntologyManager().getOWLDataFactory();
genSymMap = new HashMap<OWLEntity,String>();
labelMap = new HashMap<OWLEntity, String>();
sf = new SimpleShortFormProvider();
generateGenSyms(); // Prep gen syms output
mapLabels(ont1); mapLabels(ont2); // Prep labels output
gp = new GenSymShortFormProvider(genSymMap);
lp = new LabelShortFormProvider(labelMap);
}
@Override
public Document getXMLDocumentUsingTermNames() {
doc = docBuilder.newDocument();
prepDocument(doc, "");
if(changeSet instanceof StructuralChangeSet)
return getStructuralChangeSetReport((StructuralChangeSet)changeSet, doc, sf);
else if(changeSet instanceof LogicalChangeSet)
return getLogicalChangeSetReport((LogicalChangeSet)changeSet, doc, sf);
else if(changeSet instanceof CategorisedChangeSet)
return getCategorisedChangeSetReport((CategorisedChangeSet)changeSet, doc, sf);
else
throw new Error("Invalid change set");
}
@Override
public Document getXMLDocumentUsingLabels() {
labelDoc = docBuilder.newDocument();
prepDocument(labelDoc, "-lbl");
if(changeSet instanceof StructuralChangeSet)
return getStructuralChangeSetReport((StructuralChangeSet)changeSet, labelDoc, lp);
else if(changeSet instanceof LogicalChangeSet)
return getLogicalChangeSetReport((LogicalChangeSet)changeSet, labelDoc, lp);
else if(changeSet instanceof CategorisedChangeSet)
return getCategorisedChangeSetReport((CategorisedChangeSet)changeSet, labelDoc, lp);
else
throw new Error("Invalid change set");
}
@Override
public Document getXMLDocumentUsingGenSyms() {
genSymDoc = docBuilder.newDocument();
prepDocument(genSymDoc, "-gs");
if(changeSet instanceof StructuralChangeSet)
return getStructuralChangeSetReport((StructuralChangeSet)changeSet, genSymDoc, gp);
else if(changeSet instanceof LogicalChangeSet)
return getLogicalChangeSetReport((LogicalChangeSet)changeSet, genSymDoc, gp);
else if(changeSet instanceof CategorisedChangeSet)
return getCategorisedChangeSetReport((CategorisedChangeSet)changeSet, genSymDoc, gp);
else
throw new Error("Invalid change set");
}
/**
* Get the XML report of a structural change set
* @param changeSet Structural change set
* @param doc XML document
* @param sf Short form provider
* @return XML report of a structural change set
*/
private Document getStructuralChangeSetReport(StructuralChangeSet changeSet, Document doc, ShortFormProvider sf) {
if(axiomIds == null) axiomIds = new HashMap<OWLAxiom,Integer>();
addElementAndChildren("Additions", "adds", changeSet.getAddedAxioms(), doc, "root", true, sf);
addElementAndChildren("Removals", "rems", changeSet.getRemovedAxioms(), doc, "root", true, sf);
addElementAndChildren("Shared", "shared", changeSet.getRemovedAxioms(), doc, "root", true, sf);
return doc;
}
/**
* Get the XML report of a logical change set
* @param changeSet Logical change set
* @param doc XML document
* @param sf Short form provider
* @return XML report of a logical change set
*/
private Document getLogicalChangeSetReport(LogicalChangeSet changeSet, Document doc, ShortFormProvider sf) {
if(axiomIds == null) axiomIds = new HashMap<OWLAxiom,Integer>();
addElement("Additions", "adds", changeSet.getAdditions().size(), doc, "root", true);
addElementAndChildren("Effectual", "effadds", changeSet.getEffectualAdditionAxioms(), doc, "adds", true, sf);
addElementAndChildren("Ineffectual", "ineffadds", changeSet.getIneffectualAdditionAxioms(), doc, "adds", true, sf);
addElement("Removals", "rems", changeSet.getRemovals().size(), doc, "root", true);
addElementAndChildren("Effectual", "effrems", changeSet.getEffectualRemovalAxioms(), doc, "rems", true, sf);
addElementAndChildren("Ineffectual", "ineffrems", changeSet.getIneffectualRemovalAxioms(), doc, "rems", true, sf);
return doc;
}
/**
* Get the XML report of a categorised change set
* @param changeSet Categorised change set
* @param doc XML document
* @param sf Short form provider
* @return XML report of a categorised change set
*/
private Document getCategorisedChangeSetReport(CategorisedChangeSet changeSet, Document doc, ShortFormProvider sf) {
sharedAxioms = changeSet.getSharedAxioms();
if(axiomIds == null) axiomIds = new HashMap<OWLAxiom,Integer>();
addElement("Additions", "adds", changeSet.getAdditions().size(), doc, "root", true);
addElement("Removals", "rems", changeSet.getRemovals().size(), doc, "root", true);
addElement("Effectual", "effadds", changeSet.getEffectualAdditions().size(), doc, "adds", true);
addEffectualCategoryElementAndChildren(
"Strengthening", "st", changeSet.getStrengthenings(), doc, "effadds", true, sf);
addEffectualCategoryElementAndChildren(
"StrengtheningWithNewTerms", "stnt", changeSet.getStrengtheningsWithNewTerms(), doc, "effadds", true, sf);
addEffectualCategoryElementAndChildren(
"NewDescription", "newdesc", changeSet.getNewDescriptions(), doc, "effadds", true, sf);
addEffectualCategoryElementAndChildren(
"PureAddition", "padd", changeSet.getPureAdditions(), doc, "effadds", true, sf);
addEffectualCategoryElementAndChildren(
"PureAdditionWithNewTerms", "paddnt", changeSet.getPureAdditionsWithNewTerms(), doc, "effadds", true, sf);
addEffectualCategoryElementAndChildren(
"NewModifiedDefinition", "stequiv", changeSet.getAddedModifiedDefinitions(), doc, "effadds", true, sf);
addEffectualCategoryElementAndChildren(
"NewModifiedDefinitionWithNewTerms", "stequivnt", changeSet.getAddedModifiedDefinitionsWithNewTerms(), doc, "effadds", true, sf);
addElement("Ineffectual", "ineffadds", changeSet.getIneffectualAdditions().size(), doc, "adds", true);
addIneffectualAdditions(
"AddedRedundancy", "ared", changeSet.getAddedRedundancies(), doc, "ineffadds", true, IneffectualAdditionCategory.REDUNDANCY, sf);
addElement("AddedRewrite", "arws", (changeSet.getAddedRewrites().size()+changeSet.getAddedPartialRewrites().size()), doc, "ineffadds", true);
addIneffectualAdditions(
"AddedCompleteRewrite", "arw", changeSet.getAddedRewrites(), doc, "arws", true, IneffectualAdditionCategory.REWRITE, sf);
addIneffectualAdditions(
"AddedPartialRewrite", "aprw", changeSet.getAddedPartialRewrites(), doc, "arws", true, IneffectualAdditionCategory.PREWRITE, sf);
addElement("AddedProspectiveRedundancy", "apred", changeSet.getAddedProspectiveRedundancies().size(), doc, "ineffadds", true);
addIneffectualAdditions(
"AddedReshuffleProspectiveRedundancy", "aavred", changeSet.getAddedReshuffleRedundancies(), doc, "apred", true,
IneffectualAdditionCategory.RESHUFFLEREDUNDANCY, sf);
addIneffectualAdditions(
"AddedNewProspectiveRedundancy", "anpred", changeSet.getAddedProspectiveNewRedundancies(), doc, "apred", true,
IneffectualAdditionCategory.NEWPROSPREDUNDANCY, sf);
addElement("Effectual", "effrems", changeSet.getEffectualRemovals().size(), doc, "rems", true);
addEffectualCategoryElementAndChildren(
"Weakening", "wk", changeSet.getWeakenings(), doc, "effrems", true, sf);
addEffectualCategoryElementAndChildren(
"WeakeningWithRetiredTerms", "wkrt", changeSet.getWeakeningsWithRetiredTerms(), doc, "effrems", true, sf);
addEffectualCategoryElementAndChildren(
"RetiredDescription", "retdesc", changeSet.getRetiredDescriptions(), doc, "effrems", true, sf);
addEffectualCategoryElementAndChildren(
"PureRemoval", "prem", changeSet.getPureRemovals(), doc, "effrems", true, sf);
addEffectualCategoryElementAndChildren(
"PureRemovalWithRetiredTerms", "premrt", changeSet.getPureRemovalsWithRetiredTerms(), doc, "effrems", true, sf);
addEffectualCategoryElementAndChildren(
"RetiredModifiedDefinition", "wkequiv", changeSet.getRemovedModifiedDefinitions(), doc, "effrems", true, sf);
addEffectualCategoryElementAndChildren(
"RetiredModifiedDefinitionWithRetiredTerms", "wkequivrt", changeSet.getRemovedModifiedDefinitionsWithRetiredTerms(),
doc, "effrems", true, sf);
addElement("Ineffectual", "ineffrems", changeSet.getIneffectualRemovals().size(), doc, "rems", true);
addIneffectualRemovals(
"RemovedRedundancy", "rred", changeSet.getRemovedRedundancies(), doc, "ineffrems", true, IneffectualRemovalCategory.REDUNDANCY, sf);
addElement("RemovedRewrite", "rrws", (changeSet.getRemovedRewrites().size()+changeSet.getRemovedPartialRewrites().size()), doc, "ineffrems", true);
addIneffectualRemovals(
"RemovedCompleteRewrite", "rrw", changeSet.getRemovedRewrites(), doc, "rrws", true, IneffectualRemovalCategory.REWRITE, sf);
addIneffectualRemovals(
"RemovedPartialRewrite", "rprw", changeSet.getRemovedPartialRewrites(), doc, "rrws", true, IneffectualRemovalCategory.PREWRITE, sf);
addElement("RemovedProspectiveRedundancy", "rpred", changeSet.getRemovedProspectiveRedundancies().size(), doc, "ineffrems", true);
addIneffectualRemovals(
"RemovedReshuffleProspectiveRedundancy", "ravred", changeSet.getRemovedReshuffleRedundancies(), doc, "rpred", true,
IneffectualRemovalCategory.RESHUFFLEREDUNDANCY, sf);
addIneffectualRemovals(
"RemovedNewProspectiveRedundancy", "rnpred", changeSet.getRemovedProspectiveNewRedundancies(), doc, "rpred", true,
IneffectualRemovalCategory.NEWPROSPREDUNDANCY, sf);
return doc;
}
/**
* Add a given element and, where appropriate, its children included in the specified set of axioms
* @param name Name of the element
* @param id Id of the element
* @param set Set of children axioms
* @param d Document to be added to
* @param parent Parent of the new element
* @param includeSize Include the size of the children set as an attribute of the new element
* @param sf Short form provider
*/
private void addElementAndChildren(String name, String id, Set<OWLAxiom> set, Document d, String parent, boolean includeSize, ShortFormProvider sf) {
addElement(name, id, set.size(), d, parent, includeSize);
List<OWLAxiom> orderedList = sortAxioms(set);
for(OWLAxiom ax : orderedList) {
if(axiomIds.containsKey(ax))
addAxiomChange(axiomIds.get(ax) + "", ax, d, id, sf);
else {
addAxiomChange(changeNr + "", ax, d, id, sf);
axiomIds.put(ax, changeNr);
changeNr++;
}
}
}
/**
* Add a given element and, where appropriate, its children included in the specified set of axioms
* @param name Name of the element
* @param id Id of the element
* @param set Set of children axioms
* @param d Document to be added to
* @param parent Parent of the new element
* @param includeSize Include the size of the children set as an attribute of the new element
* @param sf Short form provider
*/
private void addEffectualCategoryElementAndChildren(String name, String id, Set<? extends CategorisedChange> set, Document d,
String parent, boolean includeSize, ShortFormProvider sf) {
addElement(name, id, set.size(), d, parent, includeSize);
List<? extends CategorisedChange> orderedList = sort(set, sf);
for(CategorisedChange change : orderedList) {
OWLAxiom ax = change.getAxiom();
if(axiomIds.containsKey(ax))
addAxiomChange(axiomIds.get(ax) + "", change, d, id, sf);
else {
addAxiomChange(changeNr + "", change, d, id, sf);
axiomIds.put(ax, changeNr);
changeNr++;
}
}
}
/**
* Add a given element and, where appropriate, its children included in the specified set of axioms
* @param name Name of the element
* @param id Id of the element
* @param set Set of children axioms
* @param d Document to be added to
* @param parent Parent of the new element
* @param includeSize Include the size of the children set as an attribute of the new element
* @param cat Ineffectual removal category
* @param sf Short form provider
*/
private void addIneffectualRemovals(String name, String id, Set<? extends CategorisedChange> set, Document d, String parent,
boolean includeSize, IneffectualRemovalCategory cat, ShortFormProvider sf) {
addElement(name, id, set.size(), d, parent, includeSize);
List<? extends CategorisedChange> orderedList = sort(set, sf);
for(CategorisedChange change : orderedList) {
OWLAxiom ax = change.getAxiom();
if(axiomIds.containsKey(ax))
appendIneffectualRemoval(axiomIds.get(ax) + "", id, (CategorisedIneffectualRemoval)change, d, cat, sf);
else {
appendIneffectualRemoval(changeNr + "", id, (CategorisedIneffectualRemoval)change, d, cat, sf);
axiomIds.put(ax, changeNr);
changeNr++;
}
}
}
/**
* Add a given element and, where appropriate, its children included in the specified set of axioms
* @param name Name of the element
* @param id Id of the element
* @param set Set of children axioms
* @param d Document to be added to
* @param parent Parent of the new element
* @param includeSize Include the size of the children set as an attribute of the new element
* @param cat Ineffectual addition category
* @param sf Short form provider
*/
private void addIneffectualAdditions(String name, String id, Set<? extends CategorisedChange> set, Document d, String parent,
boolean includeSize, IneffectualAdditionCategory cat, ShortFormProvider sf) {
addElement(name, id, set.size(), d, parent, includeSize);
List<? extends CategorisedChange> orderedList = sort(set, sf);
for(CategorisedChange change : orderedList) {
OWLAxiom ax = change.getAxiom();
if(axiomIds.containsKey(ax))
appendIneffectualAddition(axiomIds.get(ax) + "", id, (CategorisedIneffectualAddition)change, d, cat, sf);
else {
appendIneffectualAddition(changeNr + "", id, (CategorisedIneffectualAddition)change, d, cat, sf);
axiomIds.put(ax, changeNr);
changeNr++;
}
}
}
/**
* Add a change element, which contains an axiom child element
* @param id Id of the change element
* @param axiom Child axiom of this change
* @param d Document to be added to
* @param parent Parent element of the change element
* @param sf Short form provider
*/
public void addAxiomChange(String id, OWLAxiom axiom, 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");
if(sharedAxioms != null && sharedAxioms.contains(axiom))
axEle.setAttribute("shared", "true");
axEle.setTextContent(getManchesterRendering(axiom, sf));
ele.appendChild(axEle);
}
/**
* 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
*/
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);
appendEffectualChange((CategorisedEffectualChange)change, d, ele, sf);
}
/**
* Append an effectual change to the specified document report
* @param c Change to be added
* @param d Document to be updated
* @param ele Parent element
* @param sf Short form provider
*/
protected void appendEffectualChange(CategorisedEffectualChange c, Document d, Element ele, ShortFormProvider sf) {
Set<OWLAxiom> aligns = c.getAxiomAlignment();
if(!aligns.isEmpty()) {
Element src = d.createElement("Source");
ele.appendChild(src);
for(OWLAxiom ax : aligns) {
Element srcAx = d.createElement("Axiom");
if(sharedAxioms != null && sharedAxioms.contains(ax))
srcAx.setAttribute("shared", "true");
srcAx.setTextContent(getManchesterRendering(ax, sf));
src.appendChild(srcAx);
}
}
if(!c.getDifferentTerms().isEmpty()) {
Element terms = null;
if(c instanceof CategorisedEffectualRemoval)
terms = d.createElement("Retired_Terms");
else if(c instanceof CategorisedEffectualAddition)
terms = d.createElement("New_Terms");
String diffEnts = getManchesterRendering(c.getDifferentTerms(), sf);
terms.setTextContent(diffEnts);
ele.appendChild(terms);
}
}
/**
* Append an ineffectual change to the specified document report
* @param id Change ID
* @param parent Parent element ID
* @param change Change to be added
* @param d Document to be updated
* @param cat Change category
* @param sf Short form provider
*/
private void appendIneffectualAddition(String id, String parent, CategorisedIneffectualAddition change, Document d, IneffectualAdditionCategory cat, 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);
Map<Explanation<OWLAxiom>,Set<IneffectualAdditionCategory>> aligns = change.getJustificationMap();
if(!aligns.isEmpty()) {
for(Explanation<OWLAxiom> exp : aligns.keySet()) {
for(IneffectualAdditionCategory catc : aligns.get(exp)) {
if(catc.equals(cat)) {
Element src = d.createElement("Source");
ele.appendChild(src);
for(OWLAxiom ax : exp.getAxioms()) {
Element srcAx = d.createElement("Axiom");
if(sharedAxioms != null && sharedAxioms.contains(ax))
srcAx.setAttribute("shared", "true");
else if(((CategorisedChangeSet)changeSet).getIneffectualRemovalAxioms().contains(ax))
srcAx.setAttribute("ineffectual", "true");
else if(((CategorisedChangeSet)changeSet).getEffectualRemovalAxioms().contains(ax))
srcAx.setAttribute("effectual", "true");
srcAx.setTextContent(getManchesterRendering(ax, sf));
src.appendChild(srcAx);
}
}
}
}
}
}
/**
* Append an ineffectual change to the specified document report
* @param id Change ID
* @param parent Parent element ID
* @param change Change to be added
* @param d Document to be updated
* @param cat Change category
* @param sf Short form provider
*/
private void appendIneffectualRemoval(String id, String parent, CategorisedIneffectualRemoval change, Document d, IneffectualRemovalCategory cat, 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);
Map<Explanation<OWLAxiom>,Set<IneffectualRemovalCategory>> aligns = change.getJustificationMap();
if(!aligns.isEmpty()) {
for(Explanation<OWLAxiom> exp : aligns.keySet()) {
for(IneffectualRemovalCategory catc : aligns.get(exp)) {
if(catc.equals(cat)) {
Element src = d.createElement("Source");
ele.appendChild(src);
for(OWLAxiom ax : exp.getAxioms()) {
Element srcAx = d.createElement("Axiom");
if(sharedAxioms != null && sharedAxioms.contains(ax))
srcAx.setAttribute("shared", "true");
else if(((CategorisedChangeSet)changeSet).getIneffectualAdditionAxioms().contains(ax))
srcAx.setAttribute("ineffectual", "true");
else if(((CategorisedChangeSet)changeSet).getEffectualAdditionAxioms().contains(ax))
srcAx.setAttribute("effectual", "true");
srcAx.setTextContent(getManchesterRendering(ax, sf));
src.appendChild(srcAx);
}
}
}
}
}
}
/**
* Add element with given name and Id to an XML document
* @param name Name of the element
* @param id Id of the element
* @param size Size of the elements children (axioms)
* @param d Document to be added to
* @param parent Parent of this new element
* @param includeSize Include the size of the children as an attribute of the new element
*/
private void addElement(String name, String id, int size, Document d, String parent, boolean includeSize) {
Element ele = d.createElement(name);
if(includeSize)
ele.setAttribute("size", "" + size);
ele.setAttribute("id", id);
ele.setIdAttribute("id", true);
Element root = d.getElementById(parent);
root.appendChild(ele);
}
/**
* Prepare output XML document
* @param d Document to prepare
* @param suffix Suffix for the document identifier
*/
private void prepDocument(Document d, String suffix) {
Element root = d.createElement("root");
root.setAttribute("id", "root");
root.setIdAttribute("id", true);
String id = uuid + suffix;
root.setAttribute("uuid", id);
d.appendChild(root);
}
/**
* Get Manchester syntax of an OWL object
* @param obj OWL object
* @param sf Short form provider
* @return A string with the object's conversion to Manchester syntax
*/
protected String getManchesterRendering(OWLObject obj, ShortFormProvider sf) {
StringWriter wr = new StringWriter();
ManchesterOWLSyntaxObjectRenderer render = new ManchesterOWLSyntaxObjectRenderer(wr, sf);
obj.accept(render);
String str = wr.getBuffer().toString();
str = str.replace("<", "");
str = str.replace(">", "");
return str;
}
/**
* Get a string with the given set of entities rendered in Manchester syntax, and comma-separated
* @param entities Set of entities
* @param sf Short form provider
* @return String with entities rendered in Manchester syntax, comma-separated
*/
private String getManchesterRendering(Set<OWLEntity> entities, ShortFormProvider sf) {
String out = "";
OWLEntity[] arr = entities.toArray(new OWLEntity[entities.size()]);
for(int i = 0; i < arr.length; i++) {
OWLEntity e = arr[i];
if(!e.isTopEntity() && !e.isBottomEntity()) {
if(i < 1)
out += sf.getShortForm(e);
else
out += ", " + sf.getShortForm(e);
}
}
out = out.replace("<", "");
out = out.replace(">", "");
return out;
}
@Override
public String getReportAsString(Document doc) {
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = null;
try { trans = transfac.newTransformer(); }
catch (TransformerConfigurationException e) { e.printStackTrace(); }
return getXMLAsString(trans, doc);
}
@Override
public String getReportAsHTML(Document doc, String xsltPath) {
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = null;
try { trans = transfac.newTransformer(new StreamSource(xsltPath)); }
catch (TransformerConfigurationException e) { e.printStackTrace(); }
return getXMLAsString(trans, doc);
}
/**
* Transform the document using the given transformer and return the transformation as a string
* @param trans Transformer
* @param doc XML document
* @return String result of transforming the XML document
*/
private String getXMLAsString(Transformer trans, Document doc) {
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
trans.setParameter("encoding", "UTF-8");
// Create string from XML tree
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(doc);
try { trans.transform(source, result); }
catch (TransformerException e) { e.printStackTrace(); }
return sw.toString();
}
/**
* Map entities to their respective rdfs:label, where applicable
* @param ont Ontology
*/
private void mapLabels(OWLOntology ont) {
Set<OWLEntity> ents = ont.getSignature();
for(OWLEntity e : ents) {
Set<OWLAnnotationAssertionAxiom> ann_axs = ont.getAnnotationAssertionAxioms(e.getIRI());
if(!ann_axs.isEmpty()) {
for(OWLAnnotationAssertionAxiom ax : ann_axs) {
if(ax.getProperty().isLabel()) {
OWLAnnotation a = ax.getAnnotation();
// String entry = a.getValue().asLiteral().get().getLiteral();
// TODO above for owl api 4
String entry = a.getValue().toString();
if(entry.startsWith("\"")) {
entry = entry.substring(1);
entry = entry.substring(0, entry.indexOf("\""));
}
if(!entry.equals(""))
labelMap.put(e, entry);
else
labelMap.put(e, sf.getShortForm(e));
}
}
}
else labelMap.put(e, sf.getShortForm(e));
}
}
/**
* Sort a given set of categorised changes into a list
* @param set Set of changes
* @param sf Short form provider
* @return List of ordered categorised changes
*/
private List<? extends CategorisedChange> sort(Set<? extends CategorisedChange> set, ShortFormProvider sf) {
Map<String,CategorisedChange> map = new HashMap<String,CategorisedChange>();
for(CategorisedChange c : set) {
String ax = getManchesterRendering(c.getAxiom(), sf);
map.put(ax, c);
}
List<String> axStrings = new ArrayList<String>(map.keySet());
Collections.sort(axStrings);
List<CategorisedChange> output = new ArrayList<CategorisedChange>();
for(String s : axStrings) {
output.add(map.get(s));
}
return output;
}
/**
* Sort a given set of axioms into a list
* @param set Set of axioms
* @return List of ordered axioms
*/
private List<OWLAxiom> sortAxioms(Set<OWLAxiom> set) {
Map<String,OWLAxiom> map = new HashMap<String,OWLAxiom>();
for(OWLAxiom axiom : set) {
String ax = getManchesterRendering(axiom, sf);
map.put(ax, axiom);
}
List<String> axStrings = new ArrayList<String>(map.keySet());
Collections.sort(axStrings);
List<OWLAxiom> output = new ArrayList<OWLAxiom>();
for(String s : axStrings) {
output.add(map.get(s));
}
return output;
}
@Override
public AxiomChangeSet getChangeSet() {
return changeSet;
}
/**
* Generate GenSyms for entities
*/
private void generateGenSyms() {
HashSet<OWLEntity> entSet = new HashSet<OWLEntity>();
entSet.addAll(ont1.getSignature());
entSet.addAll(ont2.getSignature());
int classCounter = 0, propCounter = 0, indCounter = 0;
char curChar1 = 'A', curChar2 = 'A', curChar3 = 'A';
boolean twoChars = false, threeChars = false;
for(OWLEntity e : entSet) {
if(e.isOWLClass()) {
if(!twoChars && !threeChars) {
classCounter++;
String base = "" + curChar1 + classCounter;
genSymMap.put(e, base);
if(curChar1 == 'Z' && classCounter == 9) {
twoChars = true; curChar1 = 'A'; classCounter = 0;
}
else if(classCounter == 9) {
curChar1++; classCounter = 0;
}
}
else if(twoChars) {
classCounter++;
String base = "" + curChar1 + curChar2 + classCounter;
genSymMap.put(e, base);
if(curChar1 == 'Z' && curChar2 == 'Z' && classCounter == 9) {
threeChars = true; twoChars = false; curChar1 = 'A'; curChar2 = 'A'; classCounter = 0;
}
else if(curChar2 == 'Z' && classCounter == 9) {
curChar1 ++; curChar2 = 'A'; classCounter = 0;
}
else if(classCounter == 9) {
curChar2++; classCounter = 0;
}
}
else if(threeChars) {
classCounter++;
String base = "" + curChar1 + curChar2 + curChar3 + classCounter;
genSymMap.put(e, base);
if(curChar2 == 'Z' && curChar3 == 'Z' && classCounter == 9) {
curChar1++; curChar2 = 'A'; curChar3 = 'A'; classCounter = 0;
}
else if(curChar3 == 'Z' && classCounter == 9) {
curChar2 ++; curChar3 = 'A'; classCounter = 0;
}
else if(classCounter == 9) {
curChar3++; classCounter = 0;
}
}
}
else if(e.isOWLDataProperty() || e.isOWLObjectProperty() || e.isOWLAnnotationProperty()) {
propCounter++; genSymMap.put(e, "prop" + propCounter);
}
else if(e.isOWLNamedIndividual()) {
indCounter++; genSymMap.put(e, "ind" + indCounter);
}
}
}
}