/*******************************************************************************
* 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.test;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.w3c.dom.Document;
import uk.ac.manchester.cs.diff.concept.change.ConceptChange;
import uk.ac.manchester.cs.diff.concept.change.LHSConceptChange;
import uk.ac.manchester.cs.diff.concept.change.RHSConceptChange;
import uk.ac.manchester.cs.diff.concept.changeset.ConceptChangeSet;
import uk.ac.manchester.cs.diff.concept.witnesses.WitnessAxioms;
import uk.ac.manchester.cs.diff.concept.witnesses.WitnessGroup;
import uk.ac.manchester.cs.diff.output.xml.XMLConceptDiffReport;
/**
* @author Rafael S. Goncalves <br>
* Information Management Group (IMG) <br>
* School of Computer Science <br>
* University of Manchester <br>
*/
public class SubconceptDiffAlternative {
private File ont1, ont2;
private String outputDir;
private boolean verbose;
/**
* Constructor for subconcept diff w.r.t. Sigma = sig(O1) U sig(O2)
* @param ont1 Ontology 1 file
* @param ont2 Ontology 2 file
* @param outputDir Output directory
* @param verbose Verbose mode
*/
public SubconceptDiffAlternative(File ont1, File ont2, String outputDir, boolean verbose) {
this.ont1 = ont1;
this.ont2 = ont2;
this.outputDir = outputDir;
this.verbose = verbose;
}
/**
* Distinguish between directly and indirectly affected concepts
* @return Concept-based change set
* @throws ExecutionException Execution exception
* @throws InterruptedException Interruption exception
*/
public ConceptChangeSet getDiff() throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
Set<OWLClass> affected = new HashSet<OWLClass>();
if(verbose) System.out.println("Initialising diff workers...");
ExecutorService exec = Executors.newCachedThreadPool();
Diff diffL = new Diff(ont1, ont2, "L", verbose);
Diff diffR = new Diff(ont1, ont2, "R", verbose);
Future<DiffResult> diffLfuture = exec.submit(diffL);
Future<DiffResult> diffRfuture = exec.submit(diffR);
DiffResult diffLresults = diffLfuture.get();
DiffResult diffRresults = diffRfuture.get();
exec.shutdown();
if(verbose) System.out.println("done (" + (System.currentTimeMillis()-start)/1000.0 + " secs)");
Set<RHSConceptChange> rhsConceptChanges = new HashSet<RHSConceptChange>();
Set<LHSConceptChange> lhsConceptChanges = new HashSet<LHSConceptChange>();
Set<ConceptChange> conceptChanges = new HashSet<ConceptChange>();
WitnessGroup lhs_spec = diffLresults.getLHSWitnessPack();
WitnessGroup lhs_gen = diffRresults.getLHSWitnessPack();
WitnessGroup rhs_spec = diffLresults.getRHSWitnessPack();
WitnessGroup rhs_gen = diffRresults.getRHSWitnessPack();
affected.addAll(diffL.getAffectedConcepts());
affected.addAll(diffR.getAffectedConcepts());
for(OWLClass c : affected) {
WitnessAxioms ls = new WitnessAxioms(lhs_spec.getDirectWitnesses(c), lhs_spec.getIndirectWitnesses(c));
WitnessAxioms rs = new WitnessAxioms(rhs_spec.getDirectWitnesses(c), rhs_spec.getIndirectWitnesses(c));
WitnessAxioms lg = new WitnessAxioms(lhs_gen.getDirectWitnesses(c), lhs_gen.getIndirectWitnesses(c));
WitnessAxioms rg = new WitnessAxioms(rhs_gen.getDirectWitnesses(c), rhs_gen.getIndirectWitnesses(c));
if(!ls.isEmpty() || !lg.isEmpty())
lhsConceptChanges.add(new LHSConceptChange(c, ls, lg));
if(!rs.isEmpty() || !rg.isEmpty())
rhsConceptChanges.add(new RHSConceptChange(c, rs, rg));
// Create overall change
if(!ls.isEmpty() || !lg.isEmpty() || !rs.isEmpty() || !rg.isEmpty()) {
Set<OWLAxiom> dirSpec = new HashSet<OWLAxiom>(ls.getDirectWitnesses());
dirSpec.addAll(rs.getDirectWitnesses());
Set<OWLAxiom> indirSpec = new HashSet<OWLAxiom>(ls.getIndirectWitnesses());
indirSpec.addAll(rs.getIndirectWitnesses());
Set<OWLAxiom> dirGen = new HashSet<OWLAxiom>(lg.getDirectWitnesses());
dirGen.addAll(rg.getDirectWitnesses());
Set<OWLAxiom> indirGen = new HashSet<OWLAxiom>(lg.getIndirectWitnesses());
indirGen.addAll(rg.getIndirectWitnesses());
ConceptChange change = new ConceptChange(c, dirSpec, indirSpec, dirGen, indirGen);
conceptChanges.add(change);
}
}
ConceptChangeSet changeSet = new ConceptChangeSet(lhsConceptChanges, rhsConceptChanges, conceptChanges);
if(verbose) printDiff(changeSet);
long end = System.currentTimeMillis();
System.out.println("finished (total diff time: " + (end-start)/1000.0 + " secs)");
return changeSet;
}
/**
* Print diff
* @param changeSet Concept-based change set
*/
public void printDiff(ConceptChangeSet changeSet) {
System.out.println("\nSubconcept diff results:");
System.out.println(" [ont1]" +
"\tSpecialised: " + changeSet.getLHSSpecialisedConcepts().size() +
"\tGeneralised: " + changeSet.getLHSGeneralisedConcepts().size() +
"\tTotal affected: " + changeSet.getLHSAffectedConcepts().size());
System.out.println(" [ont2]" +
"\tSpecialised: " + changeSet.getRHSSpecialisedConcepts().size() +
"\tGeneralised: " + changeSet.getRHSGeneralisedConcepts().size() +
"\tTotal affected: " + changeSet.getRHSAffectedConcepts().size());
System.out.println(" [total]" +
"\tSpecialised: " + changeSet.getAllSpecialisedConcepts().size() +
"\tGeneralised: " + changeSet.getAllGeneralisedConcepts().size() +
"\tTotal affected: " + changeSet.getAllAffectedConcepts().size());
System.out.println("\n Overall affected concepts categorisation:");
System.out.println(" Direct Generalised: " + changeSet.getAllDirectlyGeneralised().size());
System.out.println(" Direct Specialised: " + changeSet.getAllDirectlySpecialised().size());
System.out.println(" Purely directly generalised: " + changeSet.getAllPurelyDirectlyGeneralised().size());
System.out.println(" Purely directly specialised: " + changeSet.getAllPurelyDirectlySpecialised().size());
System.out.println(" Purely indirectly generalised: " + changeSet.getAllPurelyIndirectlyGeneralised().size());
System.out.println(" Purely indirectly specialised: " + changeSet.getAllPurelyIndirectlySpecialised().size());
System.out.println(" Mixed generalised: " + changeSet.getAllMixedGeneralised().size());
System.out.println(" Mixed specialised: " + changeSet.getAllMixedSpecialised().size());
serializeXMLReport(changeSet);
}
/**
* Get the XML change set and serialise it
* @param changeSet Concept diff change set
*/
private void serializeXMLReport(ConceptChangeSet changeSet) {
XMLConceptDiffReport report = getXMLReport(changeSet);
Document doc = report.getReport();
Transformer transformer = null;
try {
transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
} catch(TransformerConfigurationException e) {
e.printStackTrace();
} catch(TransformerFactoryConfigurationError e) {
e.printStackTrace();
}
if(!outputDir.endsWith(File.separator)) outputDir += File.separator;
Result output = new StreamResult(new File(outputDir + "difflog.xml"));
Source input = new DOMSource(doc);
try {
transformer.transform(input, output);
} catch (TransformerException e) {
e.printStackTrace();
}
}
/**
* Get the XML report for concept diff
* @param changeSet Concept change set
* @return Concept diff report object
*/
public XMLConceptDiffReport getXMLReport(ConceptChangeSet changeSet) {
return new XMLConceptDiffReport(changeSet);
}
}