package org.mindswap.swoop.renderer.ontology; import java.io.Reader; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringEscapeUtils; import org.mindswap.swoop.SwoopModel; import org.semanticweb.owl.io.ParserException; import org.semanticweb.owl.io.abstract_syntax.ObjectRenderer; import org.semanticweb.owl.io.owl_rdf.OWLRDFErrorConstants; import org.semanticweb.owl.io.owl_rdf.OWLRDFErrorHandler; import org.semanticweb.owl.io.owl_rdf.OWLRDFParser; import org.semanticweb.owl.io.vocabulary.OWLVocabularyAdapter; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLDataProperty; import org.semanticweb.owl.model.OWLDataRange; import org.semanticweb.owl.model.OWLDataType; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLIndividual; import org.semanticweb.owl.model.OWLNamedObject; import org.semanticweb.owl.model.OWLObject; import org.semanticweb.owl.model.OWLObjectProperty; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.helper.OntologyHelper; import org.semanticweb.owl.util.OWLConnection; import org.semanticweb.owl.util.OWLManager; import org.semanticweb.owl.validation.SpeciesValidatorReporter; import org.xml.sax.SAXException; //import uk.ac.man.cs.img.owl.validation.SpeciesValidator; /** * @author Evren Sirin modiefied by Dave */ public class SwoopSpeciesValidator implements org.semanticweb.owl.validation.SpeciesValidator, org.semanticweb.owl.validation.OWLValidationConstants { // popular registered URI transfer scheme names (see // http://www.iana.org/assignments/uri-schemes) // private static final String [] POPULAR_SCHEME_NAMES = {"http://"};//, // "ftp://", "gopher://", "https://", "tftp://" }; private static final String SPACE = " "; private static final String LT = "<"; private static final String GT = ">"; protected static final int OTHER = 7; /* 0111 */ protected SwoopModel myModel = null; private SpeciesValidatorReporter reporter; private Map options; private OWLConnection connection; private OWLOntology ontology; private Set allOntologies; private Set reservedVocabulary; /* * Those things from the reserved vocabulary that can be defined as classes. * rdf:Statement, rdf:Seq, rdf:Bag, and rdf:Alt */ private Set classOnlyVocabulary; /* * Those things from the reserved vocabulary that can be defined as classes. * rdf:subject, rdf:predicate, rdf:object, and all the container membership * properties, i.e., rdf:_1, rdf:_2, etc. */ private Set propertyOnlyVocabulary; /** * Indicates whether the separation of names for classes, individuals and * properties has been observed */ private boolean namespacesSeparated; /** * Indicates whether the conditions regarding the usage and redefinition of * elements from the RDF, RDFS and OWL vocabularies have been observed. */ private boolean correctOWLUsage; private boolean correctOWLNamespaceUsage; /** Indicates whether all individuals have at least one explicit type. */ private boolean individualsTyped; /* * Indicates whether classAxioms from a particular species are used. */ private int classAxiomLevel; /* * Indicates whether propertyAxioms from a particular species are used. */ private int propertyAxiomLevel; /* * Indicates the level of expressivity used in expressions within the * ontology. */ private int expressivityLevel; /* * Indicates whether syntactic constraints have been violated which pushes * us into a particular level, e.g. untyped URIs => Full */ private int syntaxLevel; /* Collections of URIs taken from the ontology. */ private Set allURIs; private Set classURIs; private Set individualURIs; private Set objectPropertyURIs; private Set dataPropertyURIs; private Set annotationPropertyURIs; /* * There may still be some nasty corner cases that slip through the net * here.... */ private Set datatypeURIs; private ObjectRenderer objectRenderer; private OWLRDFParser parser; /** * Create a new validator. Will report to stdout by default. * * */ public SwoopSpeciesValidator(SwoopModel model) throws OWLException { myModel = model; /* Sets up a default reporter that writes to stdout. */ setReporter(new SpeciesValidatorReporter() { public void ontology(OWLOntology onto) { // System.out.println( onto.getURI() ); } public void done(String str) { // System.out.println( str ); } public void message(String str) { System.out.println(str); } public void explain(int l, int code, String str) { System.out.println(level(l) + " [" + readableCode(code) + "]:\t" + str); // System.out.println( level( l ) + ":\t" + str ); } }); reservedVocabulary = OWLVocabularyAdapter.INSTANCE.getReservedVocabulary(); classOnlyVocabulary = new HashSet(); classOnlyVocabulary.add(OWLVocabularyAdapter.INSTANCE.getStatement()); classOnlyVocabulary.add(OWLVocabularyAdapter.INSTANCE.getSeq()); classOnlyVocabulary.add(OWLVocabularyAdapter.INSTANCE.getBag()); classOnlyVocabulary.add(OWLVocabularyAdapter.INSTANCE.getAlt()); options = new HashMap(); /* Get a default connection */ connection = OWLManager.getOWLConnection(); parser = new OWLRDFParser(); /* * Tell the parser to ignore annotation content. This is not needed for * validation. */ Map options = new HashMap(); options.put("includeAnnotationContent", new Boolean(false)); parser.setOptions(options); } /** * Set the connection (e.g. the implementation that the validator will * choose to use when constructing ontologies. */ public void setConnection(OWLConnection connection) { this.connection = connection; } /** * Set the reporter that this speciesValidator will use. By default, the * validator will write to stdout. If you want to stop this happening, set * the reporter to null */ public void setReporter(SpeciesValidatorReporter reporter) { this.reporter = reporter; } /** * Provide an explanation as to why the validator considers the ontology to * be in a particular species. * * @param l * an <code>int</code> value * @param str * a <code>String</code> value */ public void explain(int l, int code, String str) { if (reporter != null) { reporter.explain(l, code, str); } } /** * Write a message. * * @param str * a <code>String</code> value */ public void message(String str) { if (reporter != null) { reporter.message(str); } } protected static String level(int l) { if (l == LITE) { return "OWL-Lite"; } else if (l == DL) { return "OWL-DL "; } else if (l == FULL) { return "OWL-Full"; } else { return "OTHER "; } } /** * Set the ontology that the validator will work with. Note that this * performs some initialisation. This particular implementation does not * track ontology changes, so if the ontology is changed before validation * takes place, the results may not be as expected. * * * * @param ontology * an <code>OWLOntology</code> value * @param checkImport * if true, grab the imports closure and check the species of any * imported ontologies. If false, just look here. Allows us to * catch situations where an ontology is imported that has a * higher expressivity, but the classes involved in that aren't * explicitly used in the importer. */ private int species(OWLOntology ontology, boolean checkImport) { int result = LITE; try { this.ontology = ontology; // logger.info( "Validating: " // + (checkImport?"[imports] ":"") // + ontology.getURI() ); if (reporter != null) { reporter.ontology(ontology); } /* Find the import closure */ this.allOntologies = OntologyHelper.importClosure(ontology); /* Do some initial processing */ gatherURIs(); /* Set up all the variables */ this.namespacesSeparated = true; this.correctOWLUsage = true; this.correctOWLNamespaceUsage = true; this.individualsTyped = true; this.classAxiomLevel = FULL; this.propertyAxiomLevel = FULL; this.expressivityLevel = FULL; /* A helper used when reporting stuff. */ objectRenderer = new ObjectRenderer(ontology); /* Now do all the relevant checks */ checkNamespaceSeparation(); checkCorrectOWLUsage(); checkCorrectOWLNamespaceUsage(); /* This should be done during parsing */ // checkIndividualTyping(); checkClassAxioms(); checkPropertyAxioms(); checkExpressivity(); if (!correctOWLNamespaceUsage) { /* * If there are things in the OWL namespace, we're in OTHER. See * http://lists.w3.org/Archives/Public/www-webont-wg/2003Feb/0157.html */ /* * This doesn't seem right though. I think it's actually the * case that any RDF document is an OWL FULL document. See * Section 1.3 of the Overview. */ // result = OTHER; result = FULL; } else if (!namespacesSeparated || !correctOWLUsage || !individualsTyped) { /* * If namespaces aren't separated, or redefinitions have * occurred, or individuals aren't all explicitly typed, we're * in Full */ result = FULL; } else { /* * Otherwise, it's the highest level that's used for classes, * properties and expressivity */ result = (classAxiomLevel | propertyAxiomLevel | expressivityLevel); } if (reporter != null) { reporter.done(level(result)); } } catch (OWLException e) { result = FULL; reporter.explain(FULL, UNKNOWN, "Exception occurred: " + e.getMessage()); } return result; } /** * Set options for this validator * * @param options * a <code>Map</code> value. Should contain a map from * {@link String String}s to {@link String String}s. */ public void setOptions(Map options) { options = new HashMap(options); }; /** * * Get options for this validator * * @return a <code>Map</code> value. Contains a map from * {@link String String}s to {@link String String}s. */ public Map getOptions() { return options; } /** Record the fact that some particular syntax has been noticed. */ private void setSyntaxLevel(int l) { syntaxLevel = l; } /** * Parse an ontology from a given URI. * * @param handler * an <code>OWLRDFErrorHandler</code> value * @param uri * an <code>URI</code> value * @return an <code>OWLOntology</code> value * @exception ParserException * if an error occurs * @exception OWLException * if an error occurs */ private OWLOntology parseFromURI(OWLRDFErrorHandler handler, URI uri) throws ParserException, OWLException { parser.setConnection(connection); /* Error handler for the parser */ parser.setOWLRDFErrorHandler(handler); // OWLOntology onto = connection.createOWLOntology( uri,uri ); OWLOntology onto = parser.parseOntology(uri); // message( onto.toString() ); return onto; } /** * Returns <code>true</code> if the ontology obtained by parsing the URI * is in OWL Lite. Will report findings to the reporter as it goes. Note * that the inner workings of the validator assume that the ontology has * <strong>not</strong> already been parsed. * * @param uri * an <code>URI</code> value * @return a <code>boolean</code> value */ public boolean isOWLLite(URI uri) { boolean result = false; try { /* Handler that's strict about OWLFullExceptions */ syntaxLevel = LITE; OWLRDFErrorHandler handler = new OWLRDFErrorHandler() { public void owlFullConstruct(int code, String message) throws SAXException { /* Doesn't throw an error, but keeps going.... */ setSyntaxLevel(FULL); explain(FULL, code, message); // throw new OWLFullConstructRDFException( message ); } public void error(String message) throws SAXException { throw new SAXException(message.toString()); } public void warning(String message) throws SAXException { message(message.toString()); } public void owlFullConstruct(int code, String message, Object obj) throws SAXException { // TODO Auto-generated method stub } }; OWLOntology o = parseFromURI(handler, uri); int species = species(o, true) | syntaxLevel; result = (species == LITE); // releaseOntology( o ); } catch (ParserException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); } return result; } /** * Returns <code>true</code> if the ontology obtained by parsing the URI * is in OWL DL. Will report findings to the reporter as it goes. Note that * the inner workings of the validator assume that the ontology has * <strong>not</strong> already been parsed. * * @param uri * an <code>URI</code> value * @return a <code>boolean</code> value */ public boolean isOWLDL(URI uri) { boolean result = false; try { /* Handler that's strict about OWLFullExceptions */ syntaxLevel = LITE; OWLRDFErrorHandler handler = new OWLRDFErrorHandler() { public void owlFullConstruct(int code, String message) throws SAXException { /* Doesn't throw an error, but keeps going.... */ setSyntaxLevel(FULL); explain(FULL, code, message); // throw new OWLFullConstructRDFException( message ); } public void error(String message) throws SAXException { throw new SAXException(message.toString()); } public void warning(String message) throws SAXException { message(message.toString()); } public void owlFullConstruct(int code, String message, Object obj) throws SAXException { // TODO Auto-generated method stub } }; OWLOntology o = parseFromURI(handler, uri); int species = species(o, true) | syntaxLevel; result = (species == DL || species == LITE); // releaseOntology( o ); } catch (ParserException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); } return result; } /** * Returns <code>true</code> if the ontology obtained by parsing the URI * is in OWL Full. Will report findings to the reporter as it goes. Note * that the inner workings of the validator assume that the ontology has * <strong>not</strong> already been parsed. * * @param uri * an <code>URI</code> value * @return a <code>boolean</code> value */ public boolean isOWLFull(URI uri) { /* * An ontology is OWL Full if: * * 1) There are OWL Full constructs used in the syntax, e.g. things have * not been explicitly typed * * or * * 2) The expressivity is Full. * */ boolean result = false; try { /* Handler that doesn't care about OWLFullExceptions */ syntaxLevel = LITE; OWLRDFErrorHandler handler = new OWLRDFErrorHandler() { public void owlFullConstruct(int code, String message) throws SAXException { /* * We know that there's some syntactic Full stuff going on, * but we don't necessarily want to throw an exception as * there may be stuff that comes up later that pushed us out * of Full, e.g. malformed RDF. */ setSyntaxLevel(FULL); explain(FULL, code, message); } public void error(String message) throws SAXException { throw new SAXException(message); } public void warning(String message) throws SAXException { message(message.toString()); } public void owlFullConstruct(int code, String message, Object obj) throws SAXException { // TODO Auto-generated method stub } }; OWLOntology o = parseFromURI(handler, uri); int species = species(o, true) | syntaxLevel; result = (species == DL || species == LITE || species == FULL); // releaseOntology( o ); } catch (ParserException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); } return result; } /** * Returns <code>true</code> if the ontology is OWL-Lite. Will report * findings to the reporter as it goes. * * * @param ontology * an <code>OWLOntology</code> value * @return a <code>boolean</code> value * @exception OWLException * if an error occurs */ public boolean isOWLLite(OWLOntology ontology) throws OWLException { return species(ontology, true) == LITE; } /** * Returns <code>true</code> if the ontology is OWL-DL. Will report * findings to the reporter as it goes. * * @param ontology * an <code>OWLOntology</code> value * @return a <code>boolean</code> value * @exception OWLException * if an error occurs */ public boolean isOWLDL(OWLOntology ontology) throws OWLException { int species = species(ontology, true); return (species == LITE || species == DL); } /** * Returns <code>true</code> if the ontology is OWL-Full. Will report * findings to the reporter as it goes. * * @param ontology * an <code>OWLOntology</code> value * @return a <code>boolean</code> value * @exception OWLException * if an error occurs */ public boolean isOWLFull(OWLOntology ontology) throws OWLException { int species = species(ontology, true); return (species == LITE || species == DL || species == FULL); } /** * Gather togther all the URIs that are used by this ontology. * */ private void gatherURIs() throws OWLException { /* Initialise the collections. */ this.classURIs = new HashSet(); this.individualURIs = new HashSet(); this.objectPropertyURIs = new HashSet(); this.dataPropertyURIs = new HashSet(); this.annotationPropertyURIs = new HashSet(); this.datatypeURIs = new HashSet(); this.allURIs = new HashSet(); /* Collect together all the URIs */ for (Iterator it = allOntologies.iterator(); it.hasNext();) { OWLOntology onto = (OWLOntology) it.next(); for (Iterator cit = onto.getClasses().iterator(); cit.hasNext();) { OWLNamedObject entity = (OWLNamedObject) cit.next(); classURIs.add(entity.getURI()); allURIs.add(entity.getURI()); } for (Iterator cit = onto.getIndividuals().iterator(); cit.hasNext();) { OWLNamedObject entity = (OWLNamedObject) cit.next(); individualURIs.add(entity.getURI()); allURIs.add(entity.getURI()); } for (Iterator cit = onto.getObjectProperties().iterator(); cit .hasNext();) { OWLNamedObject entity = (OWLNamedObject) cit.next(); objectPropertyURIs.add(entity.getURI()); allURIs.add(entity.getURI()); } for (Iterator cit = onto.getDataProperties().iterator(); cit .hasNext();) { OWLNamedObject entity = (OWLNamedObject) cit.next(); dataPropertyURIs.add(entity.getURI()); allURIs.add(entity.getURI()); } for (Iterator cit = onto.getAnnotationProperties().iterator(); cit .hasNext();) { OWLNamedObject entity = (OWLNamedObject) cit.next(); annotationPropertyURIs.add(entity.getURI()); allURIs.add(entity.getURI()); } for (Iterator cit = onto.getDatatypes().iterator(); cit.hasNext();) { OWLDataType entity = (OWLDataType) cit.next(); datatypeURIs.add(entity.getURI()); allURIs.add(entity.getURI()); } } } /** * Check that namespace separation has been correctly obeyed. In other * words, no URI has been used as both an individual and class name, or * property and class name etc. */ private void checkNamespaceSeparation() { try { /* Check that the collections are all disjoint */ for (Iterator it = classURIs.iterator(); it.hasNext();) { URI u = (URI) it.next(); if (individualURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Class and Individual"); } else if (objectPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Class and ObjectProperty"); } else if (dataPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Class and DataProperty"); } else if (annotationPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Class and AnnotationProperty"); } else if (datatypeURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Class and Datatype"); } } for (Iterator it = individualURIs.iterator(); it.hasNext();) { URI u = (URI) it.next(); if (objectPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Individual and Property"); } else if (dataPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Individual and DataProperty"); } else if (annotationPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Individual and AnnotationProperty"); } else if (datatypeURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as Individual and Datatype"); } } for (Iterator it = objectPropertyURIs.iterator(); it.hasNext();) { URI u = (URI) it.next(); if (dataPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as ObjectProperty and DataProperty"); } else if (annotationPropertyURIs.contains(u)) { namespacesSeparated = false; explain( FULL, SEPARATIONVIOLATION, encodeHLink(u.toString(), myModel.shortForm(u)) + "\t used as ObjectProperty and AnnotationProperty"); } else if (datatypeURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as ObjectProperty and Datatype"); } } for (Iterator it = dataPropertyURIs.iterator(); it.hasNext();) { URI u = (URI) it.next(); if (annotationPropertyURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as DataProperty and AnnotationProperty"); } else if (datatypeURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as DataProperty and Datatype"); } } for (Iterator it = annotationPropertyURIs.iterator(); it.hasNext();) { URI u = (URI) it.next(); if (datatypeURIs.contains(u)) { namespacesSeparated = false; explain(FULL, SEPARATIONVIOLATION, encodeHLink( u.toString(), myModel.shortForm(u)) + "\t used as AnnotationProperty and Datatype"); } } // namespacesSeparated = true; } catch (Exception ex) { ex.printStackTrace(); } return; } /** * Check the level of class axioms. Involves checking whether things like * disjoint axioms have been used. */ private void checkClassAxioms() throws OWLException { classAxiomLevel = LITE; /* Grab all the axioms and check their level */ for (Iterator it = allOntologies.iterator(); it.hasNext();) { OWLOntology onto = (OWLOntology) it.next(); for (Iterator axit = onto.getClassAxioms().iterator(); axit.hasNext();) { OWLObject oo = (OWLObject) axit.next(); SwoopSpeciesValidatorVisitor visitor = new SwoopSpeciesValidatorVisitor( this, objectRenderer); try { oo.accept(visitor); classAxiomLevel = classAxiomLevel | visitor.getLevel(); } catch (OWLException ex) { classAxiomLevel = OTHER; } } } } /** * Check that all individuals have been given at least one type. */ private void checkIndividualTyping() throws OWLException { try { /* Grab all the individuals and check their typing */ Set allIndividuals = new HashSet(); for (Iterator it = allOntologies.iterator(); it.hasNext();) { OWLOntology onto = (OWLOntology) it.next(); for (Iterator indit = onto.getIndividuals().iterator(); indit.hasNext();) { allIndividuals.add(indit.next()); } } for (Iterator it = allIndividuals.iterator(); it.hasNext();) { OWLIndividual i = (OWLIndividual) it.next(); if (i.getTypes(allOntologies).size() == 0) { individualsTyped = false; URI uri = i.getURI(); explain(FULL, UNTYPEDINDIVIDUAL, "Individual with no explicit type: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } } } catch (Exception ex) { ex.printStackTrace(); throw new OWLException(ex.getMessage()); } } private void checkPropertyAxioms() throws OWLException { /* * There isn't really anything to do here. Property axioms can be in all * species */ propertyAxiomLevel = LITE; }; private void checkExpressivity() throws OWLException { try { /* * Here, we need to look at all the expressions used anywhere within * the ontology and check their level. */ /* For each ontology, we need to check everything within it */ expressivityLevel = LITE; SwoopExpressionValidatorVisitor evv = new SwoopExpressionValidatorVisitor( this, objectRenderer); for (Iterator it = allOntologies.iterator(); it.hasNext();) { OWLOntology onto = (OWLOntology) it.next(); for (Iterator cit = onto.getClasses().iterator(); cit.hasNext();) { OWLClass clazz = (OWLClass) cit.next(); if (!clazz.getEnumerations(onto).isEmpty()) { /* We're in DL. */ expressivityLevel = expressivityLevel | DL; URI uri = clazz.getURI(); explain(DL, ONEOF, "Enumeration used: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } for (Iterator superit = clazz.getSuperClasses(onto).iterator(); superit.hasNext();) { /* Check the expressivity of any superclasses */ /* * Tricky bit here -- if there's an intersection used at * the top level, we're still ok for LITE. This is *not* * currently catered for, so we will get some stuff * wrong. */ OWLDescription description = (OWLDescription) superit.next(); evv.reset(); evv.setTopLevelDescription(true); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } for (Iterator superit = clazz.getEquivalentClasses(onto).iterator(); superit.hasNext();) { /* Check the expressivity of any equivalences */ /* * This is tricky, as these expressions *can* be * intersections, as long as they're intersections of * Lite constructs. This is the only place that it can * happen in Lite. */ OWLDescription description = (OWLDescription) superit.next(); evv.reset(); evv.setTopLevelDescription(true); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } } for (Iterator iit = onto.getObjectProperties().iterator(); iit.hasNext();) { OWLObjectProperty op = (OWLObjectProperty) iit.next(); for (Iterator dit = op.getDomains(onto).iterator(); dit.hasNext();) { /* Check the expressivity of any equivalences */ OWLDescription description = (OWLDescription) dit.next(); evv.reset(); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } for (Iterator dit = op.getRanges(onto).iterator(); dit.hasNext();) { /* Check the expressivity of any equivalences */ OWLDescription description = (OWLDescription) dit.next(); evv.reset(); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } } for (Iterator iit = onto.getDataProperties().iterator(); iit.hasNext();) { OWLDataProperty dp = (OWLDataProperty) iit.next(); for (Iterator dit = dp.getDomains(onto).iterator(); dit.hasNext();) { /* Check the expressivity of any equivalences */ OWLDescription description = (OWLDescription) dit.next(); evv.reset(); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } for (Iterator dit = dp.getRanges(onto).iterator(); dit .hasNext();) { /* Check the expressivity of any equivalences */ OWLDataRange description = (OWLDataRange) dit.next(); evv.reset(); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } } for (Iterator iit = onto.getIndividuals().iterator(); iit.hasNext();) { OWLIndividual ind = (OWLIndividual) iit.next(); for (Iterator typeit = ind.getTypes(onto).iterator(); typeit.hasNext();) { /* Check the expressivity of any equivalences */ OWLDescription description = (OWLDescription) typeit.next(); evv.reset(); try { description.accept(evv); expressivityLevel = expressivityLevel | evv.getLevel(); } catch (OWLException ex) { explain(OTHER, UNKNOWN, ex.getMessage()); expressivityLevel = OTHER; } } } } Set complexProperties = evv.getComplexProperties(); /* * Gather all the properties that are known to be functional or * inverse functional */ for (Iterator it = allOntologies.iterator(); it.hasNext();) { OWLOntology onto = (OWLOntology) it.next(); for (Iterator pit = onto.getObjectProperties().iterator(); pit.hasNext();) { OWLObjectProperty prop = (OWLObjectProperty) pit.next(); if (prop.isFunctional(onto) || prop.isInverseFunctional(onto)) { complexProperties.add(prop); } } } /* * We aren't doing everything yet as we still need to grab those * that have complex superproperties. */ /* * Now check to see if they've been said to be transitive, in which * case we're in FULL. */ for (Iterator pit = complexProperties.iterator(); pit.hasNext();) { OWLObjectProperty prop = (OWLObjectProperty) pit.next(); for (Iterator it = allOntologies.iterator(); it.hasNext();) { OWLOntology onto = (OWLOntology) it.next(); if (prop.isTransitive(onto)) { expressivityLevel = FULL; URI uri = prop.getURI(); explain(FULL, COMPLEXTRANSITIVE, "Complex property " + encodeHLink(uri.toString(), myModel.shortForm(uri)) + " asserted to be transitive."); } } } } catch (Exception ex) { ex.printStackTrace(); throw new OWLException(ex.getMessage()); } } private void checkCorrectOWLUsage() throws OWLException { /* Check that nothing in the OWL vocabulary has been redefined. */ /* * This was too strong. We are actually allowed to say that some things * e.g. Bag, Set, Alt and Statement are classes. Also some other stuff * in the RDF vocabulary. SKB. */ try { for (Iterator it = classURIs.iterator(); it.hasNext();) { URI uri = (URI) it.next(); if (uri != null && reservedVocabulary.contains(uri.toString())) { if (!classOnlyVocabulary.contains(uri.toString())) { /* * It's a redefinition of something that we can't * redefine. */ correctOWLUsage = false; explain(FULL, BUILTINREDEFINITION, "Redefinition of: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } } } for (Iterator it = individualURIs.iterator(); it.hasNext();) { URI uri = (URI) it.next(); if (uri != null && reservedVocabulary.contains(uri.toString())) { /* It's a redefinition of something that we can't redefine. */ correctOWLUsage = false; explain(FULL, BUILTINREDEFINITION, "Redefinition of: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } } for (Iterator it = objectPropertyURIs.iterator(); it.hasNext();) { URI uri = (URI) it.next(); if (uri != null && reservedVocabulary.contains(uri.toString())) { /* It's a redefinition of something that we can't redefine. */ correctOWLUsage = false; explain(FULL, BUILTINREDEFINITION, "Redefinition of: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } } for (Iterator it = dataPropertyURIs.iterator(); it.hasNext();) { URI uri = (URI) it.next(); if (uri != null && reservedVocabulary.contains(uri.toString())) { /* It's a redefinition of something that we can't redefine. */ correctOWLUsage = false; explain(FULL, BUILTINREDEFINITION, "Redefinition of: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } } for (Iterator it = datatypeURIs.iterator(); it.hasNext();) { URI uri = (URI) it.next(); if (uri != null && reservedVocabulary.contains(uri.toString()) || /* * Nasty. Need to check that thing/nothing aren't * redefined as datatypes. */ uri.toString().equals(OWLVocabularyAdapter.INSTANCE.getThing()) || uri.toString().equals(OWLVocabularyAdapter.INSTANCE.getNothing())) { /* It's a redefinition of something that we can't redefine. */ correctOWLUsage = false; explain(FULL, BUILTINREDEFINITION, "Redefinition of: " + encodeHLink(uri.toString(), myModel.shortForm(uri))); } } } catch (Exception ex) { ex.printStackTrace(); throw new OWLException(ex.getMessage()); } } private void checkCorrectOWLNamespaceUsage() throws OWLException { /* Check that nothing's been defined in the OWL namespace. */ try { for (Iterator it = allURIs.iterator(); it.hasNext();) { URI uri = (URI) it.next(); if (uri != null) { String str = uri.toString(); if (str.startsWith(OWLVocabularyAdapter.OWL) && !str.equals(OWLVocabularyAdapter.INSTANCE.getThing()) && !str.equals(OWLVocabularyAdapter.INSTANCE.getNothing()) && /* Added check for built ins */ !OWLVocabularyAdapter.INSTANCE.getAnnotationProperties().contains(str)) { correctOWLNamespaceUsage = false; explain(FULL, OWLNAMESPACEUSED, encodeHLink(str, myModel.shortForm(uri)) + " in OWL Namespace"); } } } } catch (Exception ex) { ex.printStackTrace(); throw new OWLException(ex.getMessage()); } } /* * Returns a readable string corresponding to the error or validation code */ public static String readableCode(int code) { switch (code) { case OWLRDFErrorConstants.OTHER: return "Unknown RDF Error"; case OWLRDFErrorConstants.UNTYPED_CLASS: return "Untyped Class"; case OWLRDFErrorConstants.UNTYPED_PROPERTY: return "Untyped Property"; case OWLRDFErrorConstants.UNTYPED_INDIVIDUAL: return "Untyped Individual"; case OWLRDFErrorConstants.UNTYPED_ONTOLOGY: return "Untyped Ontology"; case OWLRDFErrorConstants.UNTYPED_DATATYPE: return "Untyped Datatype"; case OWLRDFErrorConstants.UNTYPED_URI: return "Untyped URI"; case OWLRDFErrorConstants.MALFORMED_LIST: return "Malformed List"; case OWLRDFErrorConstants.INVERSE_FUNCTIONAL_DATA_PROPERTY: return "Inverse Functional Data Property"; case OWLRDFErrorConstants.UNSPECIFIED_FUNCTIONAL_PROPERTY: return "Unspecified Functional Property"; case OWLRDFErrorConstants.STRUCTURE_SHARING: return "Structure Sharing"; case OWLRDFErrorConstants.CYCLICAL_BNODES: return "Cyclical BNodes"; case OWLRDFErrorConstants.MULTIPLE_DEFINITIONS: return "Multiple Definitions"; case OWLRDFErrorConstants.MALFORMED_RESTRICTION: return "Malformed Restriction"; case OWLRDFErrorConstants.MALFORMED_DESCRIPTION: return "Malformed Description"; case OWLRDFErrorConstants.UNUSED_TRIPLES: return "Unused Triples"; case OWLRDFErrorConstants.ILLEGAL_SUBPROPERTY: return "Illegal Sub Property"; case OWLRDFErrorConstants.MALFORMED_IMPORT: return "Malformed Import"; case UNKNOWN: return "Unknown"; case INTERSECTION: return "Intersection"; case UNION: return "Union"; case COMPLEMENT: return "Complement"; case ZEROONECARDINALITY: return "0/1 Cardinality"; case CARDINALITY: return "Cardinality"; case ONEOF: return "One Of"; case DATATYPE: return "DataType"; case DATARANGE: return "DataRange"; case SUBCLASS: return "SubClass"; case EQUIVALENCE: return "Equivalence"; case DISJOINT: return "Disjoint"; case PARTIAL: return "Partial"; case COMPLETE: return "Complete"; case SUBPROPERTY: return "SubProperty"; case EQUIVALENTPROPERTY: return "EquivalentProperty"; case INVERSE: return "Inverse"; case TRANSITIVE: return "Transitive"; case SYMMETRIC: return "Symmetric"; case FUNCTIONAL: return "Functional"; case INVERSEFUNCTIONAL: return "InverseFunctional"; case INDIVIDUALS: return "Individuals"; case RELATEDINDIVIDUALS: return "RelatedIndividuals"; case INDIVIDUALDATA: return "IndividualData"; case SAMEINDIVIDUAL: return "SameIndividual"; case DIFFERENTINDIVIDUAL: return "DifferentIndividuals"; case SEPARATIONVIOLATION: return "Name Separation Violated"; case UNTYPEDINDIVIDUAL: return "Untyped Individual"; case COMPLEXTRANSITIVE: return "Complex Transitive Property"; case BUILTINREDEFINITION: return "Redefinition of Builtin Vocabulary"; case OWLNAMESPACEUSED: return "Definition in OWL Namespace"; case EXPRESSIONINAXIOM: return "Expression used in Axiom"; case EXPRESSIONINRESTRICTION: return "Expression used in Restriction"; } return "---"; } private String encodeHLink(String uri_string, String name) throws URISyntaxException { // System.out.println("linking: >>"+uri_string); //URI uri = new URI(uri_string); return ("<a href=" + StringEscapeUtils.escapeHtml(uri_string) + ">" + StringEscapeUtils.escapeHtml(name) + "</a>"); } /* * (non-Javadoc) * * @see org.semanticweb.owl.validation.SpeciesValidator#isOWLLite(java.io.Reader, * java.net.URI) */ public boolean isOWLLite(Reader r, URI physicalURI) throws OWLException { // TODO Auto-generated method stub return false; } /* * (non-Javadoc) * * @see org.semanticweb.owl.validation.SpeciesValidator#isOWLDL(java.io.Reader, * java.net.URI) */ public boolean isOWLDL(Reader r, URI physicalURI) throws OWLException { // TODO Auto-generated method stub return false; } /* * (non-Javadoc) * * @see org.semanticweb.owl.validation.SpeciesValidator#isOWLFull(java.io.Reader, * java.net.URI) */ public boolean isOWLFull(Reader r, URI physicalURI) throws OWLException { // TODO Auto-generated method stub return false; } } /* * public void render(OWLOntology ontology, SwoopModel swoopModel, Writer * writer) throws RendererException { * * myModel = swoopModel; * * PrintWriter out = new PrintWriter(writer); * * SpeciesValidator sv = null; try { sv = new SpeciesValidator(); * } catch (OWLException e1) { throw new RendererException(e1.getMessage()); } * StringWriter lw = new StringWriter(); StringWriter dw = new StringWriter(); * StringWriter fw = new StringWriter(); StringWriter rw = new StringWriter(); * StringWriter mw = new StringWriter(); final PrintWriter lpw = new * PrintWriter(lw); final PrintWriter dpw = new PrintWriter(dw); final * PrintWriter fpw = new PrintWriter(fw); final PrintWriter rpw = new * PrintWriter(rw); final PrintWriter mpw = new PrintWriter(mw); * * final StringBuffer level = new StringBuffer(); * * sv.setReporter(new SpeciesValidatorReporter() { public void * ontology(OWLOntology onto) { } * * public void done(String str) { level.setLength(0); level.append(str); } * * public void message(String str) { mpw.println( "<li>" + reformatInHTML(str) + "</li>"); * //mpw.println("<li>" + str + "</li>"); } * * public void explain(int l, String str) { switch (l) { case * SpeciesValidator.LITE : lpw.println( "<li>" + reformatInHTML(str) + "</li>"); * //lpw.println("<li>" + (str) + "</li>"); break; case SpeciesValidator.DL : * dpw.println( "<li>" + reformatInHTML(str) + "</li>"); //dpw.println("<li>" + * (str) + "</li>"); break; case SpeciesValidator.FULL : fpw.println( "<li>" + * reformatInHTML(str) + "</li>"); //fpw.println("<li>" + (str) + "</li>"); * break; } } * * public void explain(int l, int code, String str) { switch (l) { case * SpeciesValidator.LITE : lpw.println( "<li>" + reformatInHTML(str) + "</li>"); * //lpw.println("<li>" + (str) + "</li>"); break; case SpeciesValidator.DL : * dpw.println( "<li>" + reformatInHTML(str) + "</li>"); //dpw.println("<li>" + * (str) + "</li>"); break; case SpeciesValidator.FULL : fpw.println( "<li>" + * reformatInHTML(str) + "</li>"); //fpw.println("<li>" + (str) + "</li>"); * break; } } }); * * try { int l = SpeciesValidator.LITE; // check for OWL lite so we get all the * messages sv.isOWLLite(ontology); * * out.println("<FONT FACE=\"Verdana\" SIZE=2>"); out.println("<b>DL * Expressivity:</b> " + swoopModel.getReasoner().getExpressivity()+"<br>"); * out.println("<p><b>Level: " + level +"</b>"); * * //out.println( "<li>"+"asdf adfd "+ encodeHLink("http://www.google.com", * "http://www.google.com") + "</li>"); * * * if ((l < SpeciesValidator.LITE) && !lw.toString().equals("")) { out.println("<ul>"); * out.println( reformatInHTML(lw.toString()) ); //out.println( lw.toString() ); * out.println("</ul>"); } // end of if () if ((l < SpeciesValidator.DL) && * !dw.toString().equals("")) { out.println("<ul>"); out.println( * reformatInHTML(dw.toString()) ) ; //out.println( dw.toString() ) ; * out.println("</ul>"); } // end of if () if ((l < SpeciesValidator.FULL) && * !fw.toString().equals("")) { out.println("<ul>"); out.println( * reformatInHTML(fw.toString()) ); //out.println( fw.toString()); // * System.out.println(fw.toString() ); out.println("</ul>"); } // end of if () * if (!mw.toString().equals("")) { out.println("<b>Additional Messages</b>"); * out.println("<ul>"); out.println( reformatInHTML(mw.toString()) ); * //out.println( mw.toString() ); out.println("</ul>"); } // end of if () * * out.println("</FONT>"); * } catch (Exception e) { out.println("Exception: " + e.getMessage()); * e.printStackTrace(); } // end of try-catch * } * * * public void setOptions(Map options) { } * * * public Map getOptions() { return null; } * * * private String reformatInHTML(String source) { source = * source.replaceAll(SPACE, " "); try{ StringTokenizer tokens = new * StringTokenizer(source); String result = ""; while (tokens.hasMoreTokens()) { * String token = tokens.nextToken(); String temp = ""; for (int i = 0; i < * POPULAR_SCHEME_NAMES.length; i++) { int index = -1; if ((index = * token.indexOf(POPULAR_SCHEME_NAMES[i])) != -1) { String head = * token.substring(0, index); String tail = token.substring(index); String tip = * ""; * * int x = 0; int y = 0; int z = 0; int w = 0; int ind = Integer.MAX_VALUE; if * ((x = tail.indexOf("<")) != -1) ind = Math.min(ind, x); //if ((y = * tail.indexOf(")")) != -1) // ind = Math.min(ind, y); //if ((z = * tail.indexOf("(")) != -1) // ind = Math.min(ind, z); if ((w = * tail.indexOf(">")) != -1) ind = Math.min(ind, w); * * if (ind != Integer.MAX_VALUE) { tail = tail.substring(0, ind); if (ind == y) * tip = ")"; } * * temp = head + encodeHLink(tail, myModel.shortForm(new URI(tail))) + tip; * break; } temp = token; } result = result + SPACE + temp; } return result ; } * catch (URISyntaxException ex) { ex.printStackTrace(); } * * return source; // exception has occurred. No 'pretty printing' is returned } * * private String encodeHLink(String uri_string, String name) throws * URISyntaxException { //System.out.println("linking: >>"+uri_string); URI uri = * new URI(uri_string); return "<a href="+uri+">"+name+"</a>"; } */