package org.openflexo.foundation.ontology.xsd; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.openflexo.foundation.ontology.DuplicateURIException; import org.openflexo.foundation.ontology.FlexoOntology; import org.openflexo.foundation.ontology.OntologicDataType; import org.openflexo.foundation.ontology.OntologyClass; import org.openflexo.foundation.ontology.OntologyDataProperty; import org.openflexo.foundation.ontology.OntologyLibrary; import org.openflexo.foundation.ontology.OntologyObject; import org.openflexo.foundation.ontology.OntologyObjectProperty; import org.openflexo.foundation.ontology.OntologyProperty; import org.openflexo.foundation.ontology.W3URIDefinitions; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.localization.Language; import org.w3c.dom.Document; import com.sun.xml.xsom.XSAttGroupDecl; import com.sun.xml.xsom.XSAttributeDecl; import com.sun.xml.xsom.XSAttributeUse; import com.sun.xml.xsom.XSComplexType; import com.sun.xml.xsom.XSDeclaration; import com.sun.xml.xsom.XSElementDecl; import com.sun.xml.xsom.XSModelGroupDecl; import com.sun.xml.xsom.XSSchemaSet; import com.sun.xml.xsom.XSSimpleType; public abstract class XSOntology extends AbstractXSOntObject implements FlexoOntology, XSOntologyURIDefinitions, W3URIDefinitions { private static final java.util.logging.Logger logger = org.openflexo.logging.FlexoLogger.getLogger(XSOntology.class.getPackage() .getName()); private final File originalXsdFile; private final OntologyLibrary library; private XSSchemaSet schemaSet; private XSDeclarationsFetcher fetcher; private boolean isLoaded = false; private boolean isLoading = false; private boolean isReadOnly = true; private XSOntClass thingClass; private final Map<String, XSOntClass> classes = new HashMap<String, XSOntClass>(); private final Map<String, XSOntDataProperty> dataProperties = new HashMap<String, XSOntDataProperty>(); private final Map<String, XSOntObjectProperty> objectProperties = new HashMap<String, XSOntObjectProperty>(); private final Map<String, XSOntIndividual> individuals = new HashMap<String, XSOntIndividual>(); public XSOntology(String ontologyURI, File xsdFile, OntologyLibrary library) { super(null, computeName(xsdFile), ontologyURI); this.originalXsdFile = xsdFile; this.library = library; } private static String computeName(File xsdFile) { return xsdFile.getName(); } @Override public String getOntologyURI() { return getURI(); } @Override public FlexoProject getProject() { return getOntologyLibrary().getProject(); } @Override public boolean getIsReadOnly() { return isReadOnly; } public void setReadOnly(boolean isReadOnly) { this.isReadOnly = isReadOnly; } @Override public XSOntology getFlexoOntology() { return this; } @Override public XSOntology getOntology() { return this; } protected XSDeclarationsFetcher getFetcher() { return fetcher; } @Override public OntologyLibrary getOntologyLibrary() { return library; } private boolean addClass(XSOntClass c) { if (classes.containsKey(c.getURI()) == false) { classes.put(c.getURI(), c); return true; } return false; } @Override public XSOntClass getThingConcept() { return thingClass; } private static boolean mapsToClass(XSElementDecl element) { if (element.getType().isComplexType()) { return true; } return false; // TODO check if there's a need to check for attribute if SimpleType. } private XSOntClass loadClass(XSDeclaration declaration) { String name = declaration.getName(); String uri = fetcher.getUri(declaration); XSOntClass xsClass = new XSOntClass(this, name, uri); classes.put(uri, xsClass); return xsClass; } private void loadClasses() { // TODO if a declaration (base) type is derived, get the correct superclass classes.clear(); thingClass = new XSOntClass(this, "Thing", XS_THING_URI); addClass(thingClass); for (XSComplexType complexType : fetcher.getComplexTypes()) { XSOntClass xsClass = loadClass(complexType); xsClass.addSuperClass(getThingConcept()); } for (XSElementDecl element : fetcher.getElementDecls()) { if (mapsToClass(element)) { XSOntClass xsClass = loadClass(element); try { XSOntClass superClass = classes.get(fetcher.getUri(element.getType())); xsClass.addSuperClass(superClass); } catch (Exception e) { } } } for (XSAttGroupDecl attGroup : fetcher.getAttGroupDecls()) { XSOntClass xsClass = loadClass(attGroup); xsClass.addSuperClass(getThingConcept()); } for (XSModelGroupDecl modelGroup : fetcher.getModelGroupDecls()) { XSOntClass xsClass = loadClass(modelGroup); xsClass.addSuperClass(getThingConcept()); } } public static boolean isFromW3(XSDeclaration decl) { return decl.getTargetNamespace().equals(W3_NAMESPACE); } private static OntologicDataType computeDataType(XSSimpleType simpleType) { String dataTypeURI = null; if (isFromW3(simpleType)) { dataTypeURI = W3_URI + "#" + simpleType.getName(); } else { dataTypeURI = W3_URI + "#" + simpleType.getBaseType().getName(); } OntologicDataType result = OntologicDataType.fromURI(dataTypeURI); if (result == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Could not map a data type: " + dataTypeURI + ", String will be used instead."); } return OntologicDataType.String; } return result; } private void addDomainIfPossible(XSOntProperty property, String conceptUri) { String ownerUri = fetcher.getOwnerUri(conceptUri); if (ownerUri != null) { XSOntClass owner = getClass(ownerUri); if (owner != null) { property.newDomainFound(owner); owner.addPropertyTakingMyselfAsDomain(property); } } } private XSOntDataProperty loadDataProperty(XSDeclaration declaration) { String name = declaration.getName(); String uri = fetcher.getUri(declaration); XSOntDataProperty xsDataProperty = new XSOntDataProperty(this, name, uri); dataProperties.put(uri, xsDataProperty); addDomainIfPossible(xsDataProperty, uri); return xsDataProperty; } private void loadDataProperties() { dataProperties.clear(); for (XSSimpleType simpleType : fetcher.getSimpleTypes()) { XSOntDataProperty xsDataProperty = loadDataProperty(simpleType); xsDataProperty.setDataType(computeDataType(simpleType)); } for (XSElementDecl element : fetcher.getElementDecls()) { if (mapsToClass(element) == false) { XSOntDataProperty xsDataProperty = loadDataProperty(element); xsDataProperty.setDataType(computeDataType(element.getType().asSimpleType())); } } for (XSAttributeDecl attribute : fetcher.getAttributeDecls()) { XSOntDataProperty xsDataProperty = loadDataProperty(attribute); xsDataProperty.setIsFromAttribute(true); xsDataProperty.setDataType(computeDataType(attribute.getType())); } } private XSOntObjectProperty loadPrefixedProperty(XSDeclaration declaration, XSOntObjectProperty parent) { String prefix = parent.getName(); String name = prefix + declaration.getName(); String uri = fetcher.getNamespace(declaration) + "#" + name; XSOntObjectProperty property = new XSOntObjectProperty(this, name, uri); property.addSuperProperty(parent); objectProperties.put(property.getURI(), property); return property; } private void loadObjectProperties() { objectProperties.clear(); XSOntObjectProperty hasChild = new XSOntObjectProperty(this, XS_HASCHILD_PROPERTY_NAME); objectProperties.put(hasChild.getURI(), hasChild); XSOntObjectProperty hasParent = new XSOntObjectProperty(this, XS_HASPARENT_PROPERTY_NAME); objectProperties.put(hasParent.getURI(), hasParent); for (XSElementDecl element : fetcher.getElementDecls()) { if (mapsToClass(element)) { String uri = fetcher.getUri(element); XSOntClass ontClass = getClass(uri); ontClass.addPropertyTakingMyselfAsRange(hasChild); ontClass.addPropertyTakingMyselfAsDomain(hasChild); ontClass.addPropertyTakingMyselfAsRange(hasParent); ontClass.addPropertyTakingMyselfAsDomain(hasParent); } } for (XSComplexType complexType : fetcher.getComplexTypes()) { XSOntClass c = getClass(fetcher.getUri(complexType)); XSOntObjectProperty cHasChild = loadPrefixedProperty(complexType, hasChild); cHasChild.newRangeFound(c); addDomainIfPossible(cHasChild, c.getURI()); XSOntObjectProperty cHasParent = loadPrefixedProperty(complexType, hasParent); cHasParent.newRangeFound(c); addDomainIfPossible(cHasParent, c.getURI()); } for (XSElementDecl element : fetcher.getElementDecls()) { if (mapsToClass(element)) { XSOntClass c = getClass(fetcher.getUri(element)); XSOntObjectProperty cHasChild = loadPrefixedProperty(element, hasChild); cHasChild.newRangeFound(c); addDomainIfPossible(cHasChild, c.getURI()); XSOntObjectProperty cHasParent = loadPrefixedProperty(element, hasParent); cHasParent.newRangeFound(c); addDomainIfPossible(cHasParent, c.getURI()); } } } private void loadRestrictions() { // Attributes for (XSOntClass xsClass : classes.values()) { XSDeclaration declaration = fetcher.getDeclaration(xsClass.getURI()); if (fetcher.getAttributeUses(declaration) != null) { for (XSAttributeUse attributeUse : fetcher.getAttributeUses(declaration)) { XSOntAttributeRestriction restriction = new XSOntAttributeRestriction(this, attributeUse); xsClass.addSuperClass(restriction); } } } // Elements // TODO } private void loadIndividuals() { individuals.clear(); } private void clearAllRangeAndDomain() { clearPropertiesTakingMyselfAsRangeOrDomain(); for (AbstractXSOntObject o : classes.values()) { o.clearPropertiesTakingMyselfAsRangeOrDomain(); } for (XSOntDataProperty o : dataProperties.values()) { o.clearPropertiesTakingMyselfAsRangeOrDomain(); o.resetDomain(); } for (XSOntObjectProperty o : objectProperties.values()) { o.clearPropertiesTakingMyselfAsRangeOrDomain(); o.resetDomain(); o.resetRange(); o.clearSuperProperties(); } for (AbstractXSOntObject o : individuals.values()) { o.clearPropertiesTakingMyselfAsRangeOrDomain(); } } public boolean load() { // TODO Should I create a w3 ontology? possibly .owl? // TODO Seems I should. if (isLoading() == true) { return false; } isLoading = true; isLoaded = false; schemaSet = XSOMUtils.read(originalXsdFile); if (schemaSet != null) { fetcher = new XSDeclarationsFetcher(); fetcher.fetch(schemaSet); clearAllRangeAndDomain(); loadClasses(); loadDataProperties(); loadObjectProperties(); loadRestrictions(); loadIndividuals(); isLoaded = true; } isLoading = false; return isLoaded; } @Override public boolean loadWhenUnloaded() { if (isLoaded() == false) { return load(); } return false; } @Override public boolean isLoaded() { return isLoaded; } @Override public boolean isLoading() { return isLoading; } private Set<XSOntIndividual> getRootElements() { Set<XSOntIndividual> result = new HashSet<XSOntIndividual>(); for (XSOntIndividual individual : this.getIndividuals()) { if (individual.getParent() == null) { result.add(individual); } } return result; } public Document toXML() throws ParserConfigurationException { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document doc = docBuilder.newDocument(); for (XSOntIndividual individual : getRootElements()) { doc.appendChild(individual.toXML(doc)); } return doc; } @Override public List<XSOntology> getAllImportedOntologies() { List<XSOntology> result = new ArrayList<XSOntology>(1); result.add(this); return result; } @Override public List<XSOntology> getImportedOntologies() { List<XSOntology> result = new ArrayList<XSOntology>(1); result.add(this); return result; } @Override public List<XSOntClass> getClasses() { return new ArrayList<XSOntClass>(classes.values()); } @Override public XSOntClass getClass(String classURI) { XSOntClass result = classes.get(classURI); if (result == null) { for (XSOntology o : getAllImportedOntologies()) { if (o != this) { result = o.getClass(classURI); if (result != null) { return result; } } } if (logger.isLoggable(Level.WARNING)) { logger.warning("Couldn't find ontology class from URI " + classURI); } } return result; } @Override public List<XSOntClass> getAccessibleClasses() { Map<String, XSOntClass> result = new HashMap<String, XSOntClass>(); for (XSOntology o : getAllImportedOntologies()) { for (XSOntClass c : o.getClasses()) { result.put(c.getURI(), c); } } return new ArrayList<XSOntClass>(result.values()); } @Override public List<XSOntDataProperty> getDataProperties() { return new ArrayList<XSOntDataProperty>(dataProperties.values()); } @Override public List<XSOntDataProperty> getAccessibleDataProperties() { Map<String, XSOntDataProperty> result = new HashMap<String, XSOntDataProperty>(); for (XSOntology o : getAllImportedOntologies()) { for (XSOntDataProperty c : o.getDataProperties()) { result.put(c.getURI(), c); } } return new ArrayList<XSOntDataProperty>(result.values()); } @Override public XSOntDataProperty getDataProperty(String propertyURI) { return dataProperties.get(propertyURI); } @Override public List<XSOntObjectProperty> getObjectProperties() { return new ArrayList<XSOntObjectProperty>(objectProperties.values()); } @Override public XSOntObjectProperty getObjectProperty(String propertyURI) { return objectProperties.get(propertyURI); } @Override public List<XSOntObjectProperty> getAccessibleObjectProperties() { Map<String, XSOntObjectProperty> result = new HashMap<String, XSOntObjectProperty>(); for (XSOntology o : getAllImportedOntologies()) { for (XSOntObjectProperty op : o.getObjectProperties()) { result.put(op.getURI(), op); } } return new ArrayList<XSOntObjectProperty>(result.values()); } @Override public OntologyProperty getProperty(String objectURI) { OntologyProperty result = getDataProperty(objectURI); if (result == null) { result = getObjectProperty(objectURI); } return result; } @Override public List<XSOntIndividual> getIndividuals() { return new ArrayList<XSOntIndividual>(individuals.values()); } @Override public XSOntIndividual getIndividual(String individualURI) { return individuals.get(individualURI); } @Override public List<XSOntIndividual> getAccessibleIndividuals() { Map<String, XSOntIndividual> result = new HashMap<String, XSOntIndividual>(); for (XSOntology o : getAllImportedOntologies()) { for (XSOntIndividual i : o.getIndividuals()) { result.put(i.getURI(), i); } } return new ArrayList<XSOntIndividual>(result.values()); } @Override public XSOntIndividual createOntologyIndividual(String name, OntologyClass type) throws DuplicateURIException { String uri = getURI() + "#" + name; if (getOntologyObject(uri) != null) { throw new DuplicateURIException(uri); } if (type instanceof XSOntClass == false) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Individual '" + name + "' with type '" + type.getURI() + "' can't be created in a XSOntology"); } return null; } XSOntIndividual individual = new XSOntIndividual(this, name, uri); individual.addType(type); individuals.put(individual.getURI(), individual); return individual; } @Override public OntologyObject getOntologyObject(String objectURI) { OntologyObject result = getClass(objectURI); if (result == null) { result = getProperty(objectURI); } if (result == null) { result = getIndividual(objectURI); } return result; } @Override public OntologyClass createOntologyClass(String name) throws DuplicateURIException { throw new UnsupportedOperationException(); } @Override public OntologyDataProperty createDataProperty(String name, OntologyDataProperty superProperty, OntologyClass domain, OntologicDataType dataType) throws DuplicateURIException { throw new UnsupportedOperationException(); } @Override public OntologyObjectProperty createObjectProperty(String name, OntologyObjectProperty superProperty, OntologyClass domain, OntologyClass range) throws DuplicateURIException { throw new UnsupportedOperationException(); } @Override public OntologyClass createOntologyClass(String name, OntologyClass superClass) throws DuplicateURIException { throw new UnsupportedOperationException(); } @Override public Object addDataPropertyStatement(OntologyDataProperty property, Object value) { throw new UnsupportedOperationException(); } @Override public Object addPropertyStatement(OntologyObjectProperty property, OntologyObject object) { throw new UnsupportedOperationException(); } @Override public Object addPropertyStatement(OntologyProperty property, Object value) { throw new UnsupportedOperationException(); } @Override public Object addPropertyStatement(OntologyProperty property, String value, Language language) { throw new UnsupportedOperationException(); } @Override public boolean isOntology() { return true; } public static String findOntologyURI(File f) { // TODO Auto-generated method stub return null; } @Override public String getDisplayableDescription() { return "Ontology " + getName(); } }