/*******************************************************************************
// * 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;
import java.io.File;
import java.io.InputStream;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.IRIDocumentSource;
import org.semanticweb.owlapi.io.StreamDocumentSource;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.MissingImportHandlingStrategy;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyLoaderConfiguration;
import org.semanticweb.owlapi.util.VersionInfo;
import uk.ac.manchester.cs.diff.exception.DuplicateArgumentException;
import uk.ac.manchester.cs.diff.exception.InsufficientArgumentsException;
import uk.ac.manchester.cs.diff.exception.MissingArgumentException;
import uk.ac.manchester.cs.diff.exception.UnrecognizedArgumentException;
/**
* @author Rafael S. Goncalves <br>
* Information Management Group (IMG) <br>
* School of Computer Science <br>
* University of Manchester <br>
*/
public class EccoRunner {
private OWLOntologyLoaderConfiguration config;
private EccoSettings settings;
private static final String
versionInfo = "2.7",
releaseDate = "16-Feb-2015",
owlapiVersion = VersionInfo.getVersionInfo().getVersion(),
programTitle =
"-------------------------------------------------------------------\n" +
" ecco: a diff tool for OWL 2 ontologies\n" +
" v" + versionInfo + " released on " + releaseDate + "\n" +
"-------------------------------------------------------------------\n" +
"by Rafael Goncalves. Powered by the OWL API version " + owlapiVersion + "\n";
/**
* Constructor
* @param settings ecco settings
*/
public EccoRunner(EccoSettings settings) {
this.settings = settings;
config = new OWLOntologyLoaderConfiguration();
config = config.setLoadAnnotationAxioms(false);
if(!settings.isProcessingImports()) {
config = config.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT);
config = config.setFollowRedirects(false);
}
}
/**
* Start ecco diff
* @param ont1filePath Ontology 1 file path
* @param localOnt1 true if ontology 1 is a file in the local file system, false otherwise
* @param ont2filePath Ontology 2 file path
* @param localOnt2 true if ontology 2 is a file in the local file system, false otherwise
*/
public void start(String ont1filePath, boolean localOnt1, String ont2filePath, boolean localOnt2) {
OWLOntology ont1 = loadOntology(1, ont1filePath, localOnt1);
OWLOntology ont2 = loadOntology(2, ont2filePath, localOnt2);
if(ont1 != null && ont2 != null) {
Ecco ecco = new Ecco(ont1, ont2, settings);
ecco.computeDiff();
}
}
/**
* Load ontology from a file path
* @param ontNr Ontology number
* @param filepath Ontology file path
* @param localFile true if local file, false otherwise
* @return Loaded ontology
*/
public OWLOntology loadOntology(int ontNr, String filepath, boolean localFile) {
String filename = filepath.substring(filepath.lastIndexOf(File.separator)+1, filepath.length());
System.out.println("Input " + ontNr + ": " + filename + " (" + filepath + ")");
if(filepath.contains("\\")) filepath = filepath.replace("\\", "/");
// Load ontology
OWLOntology ont = null;
try {
if(localFile) ont = OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(new IRIDocumentSource(IRI.create("file:///" + filepath)), config);
else ont = OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(new IRIDocumentSource(IRI.create(filepath)), config);
} catch (OWLOntologyCreationException e) {
e.printStackTrace();
}
return ont;
}
/**
* Load ontology from an input stream
* @param ontNr Ontology nunmber
* @param stream Input stream
* @return OWL ontology
*/
public OWLOntology loadOntology(int ontNr, InputStream stream) {
OWLOntology ont = null;
try {
ont = OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(new StreamDocumentSource(stream), config);
} catch (OWLOntologyCreationException e) {
e.printStackTrace();
}
return ont;
}
/**
* Print usage message
*/
private static void printUsage() {
System.out.println(" Usage:\n\t-ont1 [ONTOLOGY] -ont2 [ONTOLOGY] [OPTIONS]");
System.out.println();
System.out.println(" [ONTOLOGY] An input ontology file path or URL");
System.out.println();
System.out.println(" [OPTIONS]");
System.out.println(" -o absolute output directory [default: ECCO-JAR-FOLDER" + File.separator + Ecco.outputDir + "]");
System.out.println(" -t transform resulting XML report into HTML");
System.out.println(" -c compute one of: [ at | sub | gr | cvs ] concept diff");
System.out.println(" -r analyze root ontologies only, i.e., ignore imports");
System.out.println(" -n normalize entity URIs, i.e. if two ontologies have the same entity names");
System.out.println(" in a different namespace, this trigger establishes a common namespace");
System.out.println(" -i ignore Abox axioms");
System.out.println(" -j maximum number of justifications computed per ineffectual change. Reducing");
System.out.println(" this can significantly speed up computation [default: 10]");
System.out.println(" -v verbose mode");
System.out.println(" -h -help print help message\n");
}
/**
* main
* @param args Arguments
*/
public static void main(String[] args) {
boolean isOnt1Set = false, isOnt2Set = false, localOnt1 = true, localOnt2 = true;
String ont1filePath = null, ont2filePath = null;
EccoSettings settings = new EccoSettings();
System.out.println("\n" + programTitle);
for(int i = 0; i < args.length; i++) {
String arg = args[i].trim();
if(arg.equalsIgnoreCase("-ont1")) { // Ontology 1
if(isOnt1Set) throw new DuplicateArgumentException("\nToo many -ont1 options provided.\n");
if(++i == args.length) throw new MissingArgumentException("\n-ont1 must be followed by an ontology URI.\n");
ont1filePath = args[i].trim(); isOnt1Set = true;
if(ont1filePath.contains("http") || ont1filePath.contains("ftp")) localOnt1 = false;
}
else if(arg.equalsIgnoreCase("-ont2")) { // Ontology 2
if(isOnt2Set) throw new DuplicateArgumentException("\nToo many -ont2 options provided.\n");
if(++i == args.length) throw new MissingArgumentException("\n-ont2 must be followed by an ontology URI.\n");
ont2filePath = args[i].trim(); isOnt2Set = true;
if(ont2filePath.contains("http") || ont2filePath.contains("ftp")) localOnt2 = false;
}
else if(arg.equalsIgnoreCase("-o")) { // Output directory
if(++i == args.length) throw new MissingArgumentException("\n-o must be followed by an output directory.\n");
arg = args[i].trim(); settings.setOutputDirectory(arg);
}
else if(arg.equalsIgnoreCase("-c")) { // Concept diff type
if(++i == args.length) throw new MissingArgumentException("\n-c must be followed by one of [ atomic | subconcept | grammar | contentcvs ].\n");
arg = args[i].trim(); settings.setConceptDiffType(arg);
}
else if(arg.equalsIgnoreCase("-n")) settings.setNormalizeURIs(true); // Normalize entity namespaces
else if(arg.equalsIgnoreCase("-t")) settings.setTransformToHTML(true); // Transform XML into HTML
else if(arg.equalsIgnoreCase("-r")) settings.setProcessImports(false); // Process root ontologies only
else if(arg.equalsIgnoreCase("-i")) settings.setIgnoreAbox(true); // Ignore Abox axioms
else if(arg.equalsIgnoreCase("-v")) settings.setVerbose(true); // Verbose mode
else if(arg.equalsIgnoreCase("-j")) { // Number of justifications per ineffectual change
if(++i == args.length) throw new MissingArgumentException("\n-j must be followed by a positive integer.");
int nrJusts = Integer.parseInt(args[i].trim());
if(nrJusts > 0) settings.setNumberOfJustifications(nrJusts);
}
else if(arg.equalsIgnoreCase("-h") || arg.equalsIgnoreCase("-help")) { // Print help message
printUsage(); System.exit(0);
}
else if(arg.startsWith("-")) { // Unknown argument
printUsage();
throw new UnrecognizedArgumentException("\nUnrecognized option: " + arg + ". See usage above.\n");
}
else {
printUsage();
throw new InsufficientArgumentsException("\nThere are not enough arguments to start ecco. "
+ "The minimum parameters are -ont1 and -ont2. See full usage above.\n");
}
}
System.out.println();
if(ont1filePath == null) {
printUsage();
throw new MissingArgumentException("\nMissing -ont1 argument, which should be followed by a file path or URL.\n");
}
if(ont2filePath == null) {
printUsage();
throw new MissingArgumentException("\nMissing -ont2 argument, which should be followed by a file path or URL.\n");
}
if(ont1filePath != null && ont2filePath != null) {
EccoRunner runner = new EccoRunner(settings);
runner.start(ont1filePath, localOnt1, ont2filePath, localOnt2);
}
}
}