/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source: /cvsroot/slrp/boca/com.ibm.adtech.boca.jastor/src/com/ibm/adtech/boca/jastor/JastorContext.java,v $
* Created by:
* Created on: 01/23/2007
* Revision: $Id: JastorContext.java 172 2007-07-31 14:22:23Z mroy $
*
* Contributors:
* IBM Corporation - initial API and implementation
* Cambridge Semantics Incorporated - Fork to Anzo
*******************************************************************************/
package org.openanzo.rdf.jastor;
import java.io.File;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.openanzo.analysis.RequestAnalysis;
import org.openanzo.glitter.Engine;
import org.openanzo.glitter.query.PatternSolution;
import org.openanzo.glitter.query.QueryResults;
import org.openanzo.rdf.BlankNode;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.Dataset;
import org.openanzo.rdf.IDataset;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.IQuadStore;
import org.openanzo.rdf.Literal;
import org.openanzo.rdf.MemQuadStore;
import org.openanzo.rdf.NamedGraph;
import org.openanzo.rdf.RDFFormat;
import org.openanzo.rdf.Resource;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.openanzo.rdf.jastor.inference.Ontology;
import org.openanzo.rdf.jastor.inference.OntologyClass;
import org.openanzo.rdf.jastor.inference.OntologyProperty;
import org.openanzo.rdf.jastor.jet.OntologyClassFileProvider;
import org.openanzo.rdf.jastor.jet.OntologyClassTemplate;
import org.openanzo.rdf.jastor.jet.OntologyFileProvider;
import org.openanzo.rdf.jastor.jet.OntologyTemplate;
import org.openanzo.rdf.jastor.rdfs.Rdfs2Owl;
import org.openanzo.rdf.jastor.templates.FactoryTemplate;
import org.openanzo.rdf.jastor.templates.ImplementationTemplate;
import org.openanzo.rdf.jastor.templates.InterfaceTemplate;
import org.openanzo.rdf.jastor.templates.ListenerTemplate;
import org.openanzo.rdf.jastor.util.graph.DFS;
import org.openanzo.rdf.jastor.util.graph.EdgeMem;
import org.openanzo.rdf.jastor.util.graph.GraphMem;
import org.openanzo.rdf.jastor.util.graph.IEdge;
import org.openanzo.rdf.jastor.util.graph.IGraph;
import org.openanzo.rdf.jastor.util.graph.INode;
import org.openanzo.rdf.jastor.util.graph.NodeMem;
import org.openanzo.rdf.owl.DatatypeProperty;
import org.openanzo.rdf.owl.OWL11Factory;
import org.openanzo.rdf.owl.ObjectProperty;
import org.openanzo.rdf.owl.Restriction;
import org.openanzo.rdf.owl._Thing;
import org.openanzo.rdf.owl.utils.OntologyUtils;
import org.openanzo.rdf.query.QuadStoreEngineConfig;
import org.openanzo.rdf.query.QueryEncoder;
import org.openanzo.rdf.rdfs.RDFSFactory;
import org.openanzo.rdf.rdfs._Property;
import org.openanzo.rdf.utils.ReadWriteUtils;
import org.openanzo.rdf.utils.StatementUtils;
import org.openanzo.rdf.vocabulary.OWL;
import org.openanzo.rdf.vocabulary.RDF;
import org.openanzo.rdf.vocabulary.RDFS;
/**
*
* This class holds context information for code generation: ontGraphs, options, names, etc...
*
* @author Ben Szekely ( <a href="mailto:bhszekel@us.ibm.com">bhszekel@us.ibm.com </a>)
*
*/
public class JastorContext {
/** OWL type extension */
private static final String ONT_LANG_OWL = "owl";
/** RDFS type extension */
public static final String ONT_LANG_RDFS = "rdfs";
private static final List<String> ONT_LANGS = new ArrayList<String>();
static {
ONT_LANGS.add(ONT_LANG_OWL);
ONT_LANGS.add(ONT_LANG_RDFS);
}
private static final String GEN_NS = "http://jastor.openanzo.org/gen#";
private final INamedGraph ontGraph;
// this is a simple dataset containing each original ont graph..used by the ontologies
private final Dataset ontDataset = new Dataset();
// this is a dataset containing all the ontologies in a single graph..used to query the collected graph
private final IQuadStore ontGraphQuadStore = new MemQuadStore();
/** map from ontology class URI to the containing ontology Resource->URI */
private final HashMap<Resource, URI> ontologyClassMap = new HashMap<Resource, URI>();
/** map from ontology propery uri to the containing onotology Resource->URI */
private final HashMap<Resource, URI> ontologyPropertyMap = new HashMap<Resource, URI>();
/** from from ontology class URI to package Resource->String */
private final HashMap<Resource, String> ontologyClassPackageMap = new HashMap<Resource, String>();
/** from the ontology URI to package Resource->String */
private final HashMap<Resource, String> ontologyPackageMap = new HashMap<Resource, String>();
/** from the package to ontology URI String->URI */
private final HashMap<String, URI> packageOntologyMap = new HashMap<String, URI>();
/** from class uri to a List(OntologyClass) that are classes that class uri should extend */
private final HashMap<Resource, List<OntologyClass>> unionTable = new HashMap<Resource, List<OntologyClass>>();
/**
* from class uri to a List(OntProperty) that are properties whose domain comes from a union. We must compute this table initially because some such
* properties won't have restrictions so they would be ignored
*/
private final HashMap<Resource, List<OntologyProperty>> unionDomainTable = new HashMap<Resource, List<OntologyProperty>>();
private final List<Resource> classesToGenerate;
private final List<Ontology> ontologiesToGenerate = new ArrayList<Ontology>();
private int curPrefixNumber = 1;
private final HashMap<String, String> namespacePrefixes = new HashMap<String, String>();
private final HashMap<String, String> namespaceRemapper = new HashMap<String, String>();
// generation flags
private boolean generateStandardCode = true;
private boolean generateListeners = true;
private boolean generateVocabularyOnly = false;
private boolean useEntireURIForIdentifiers = false;
private boolean generateCacheInFactory = true;
private boolean usePackageNameForRestrictedRanges = false;
private boolean useStrictTypeChecking = false;
private boolean returnNullOnMissingTypes = false;
private boolean useTypedLiterals = true;
private boolean addAllRDFTypesInHierarchy = true;
private boolean includeCopyright = true;
private boolean searchSubClassHierarchyForCardRes = true;
// Thing implementation
private Class<?> thingInterface = Thing.class;
private Class<?> thingImpl = ThingImpl.class;
private Class<?> thingFactory = ThingFactory.class;
// base literal implementation
private Class<?> baseLiteralClass = Literal.class;
// generation templates
private final Map<String, OntologyTemplate> ontologyTemplates = new HashMap<String, OntologyTemplate>();
private final Map<String, OntologyClassTemplate> ontologyClassTemplates = new HashMap<String, OntologyClassTemplate>();
// memoization for the computation of property restrictions in subClasses
// <classUri><propUri> => Restriction
Map<String, Restriction[]> subClassRestrictions = new HashMap<String, Restriction[]>();
// memoization for the computation of property restrictions
// <classUri><propUri> => Restriction
Map<String, Restriction[]> baseRestrictions = new HashMap<String, Restriction[]>();
List<_Property> odProps = null;
Map<URI, List<_Property>> declProps = new HashMap<URI, List<_Property>>();
/**
* Construct an empty context with initially nothing to generate
*
*/
public JastorContext() {
ontGraph = createOntGraph(false, null);
OWL11Factory.createClass(_Thing.TYPE, ontGraph);
//OWL11Factory.createClass(RDFS.RESOURCE, ontGraph);
classesToGenerate = new ArrayList<Resource>();
}
/**
* Should be called to finalize the context after all ontologies have been added but before generation
*/
public void finalizeContext() {
ontGraphQuadStore.add(ontGraph.getStatements());
long start = 0;
if (RequestAnalysis.isAnalysisEnabled()) {
start = System.currentTimeMillis();
}
buildUnionTable();
buildUnionDomainTable();
if (isGenerateStandardCode())
setupDefaultTemplates();
fillInDomainRangeFromSuperProperties();
addRDFTypeToEnumerationClassMembers();
if (RequestAnalysis.isAnalysisEnabled()) {
long end = System.currentTimeMillis();
RequestAnalysis.incrementAnalysisPropertyCount("finalizeContext", end - start);
}
ontGraphQuadStore.clear();
ontGraphQuadStore.add(ontGraph.getStatements());
}
/**
* Set a custom thing implementation.
*
* @param thingInterface
* - the classname of an extension of Thing
* @param thingImpl
* - the classname of an extension of ThingImpl
* @param thingFactory
* the classname of an extension of ThingFactory
* @throws JastorException
*/
public void setCustomThing(String thingInterface, String thingImpl, String thingFactory) throws JastorException {
try {
this.thingInterface = Class.forName(thingInterface);
this.thingImpl = Class.forName(thingImpl);
this.thingFactory = Class.forName(thingFactory);
} catch (ClassNotFoundException e) {
throw new JastorException(e, "Error loading custom thing class");
}
}
/**
* Return the Class of the base Thing interface
*
* @return the Class of the base Thing interface
*/
public Class<?> getThingInterface() {
return thingInterface;
}
/**
* Return the Class of the base Thing implementation
*
* @return the Class of the base Thing implementation
*/
public Class<?> getThingImpl() {
return thingImpl;
}
/**
* Return the Class of the base Thing factory
*
* @return the Class of the base Thing factory
*/
public Class<?> getThingFactory() {
return thingFactory;
}
/**
* Specify an OWL ontology to generate
*
* @param ontologyFile
* The Reader containing the ontology document
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*/
public void addOntologyToGenerate(Reader ontologyFile, String ontologyURI, String packagename) {
addOntologyToGenerate(ontologyFile, null, ontologyURI, packagename);
}
/**
* Specify an OWL ontology to generate
*
* @param ontologyFile
* The Reader containing the ontology document
* @param rdflang
* The seriazation format of the ontology file (N3,RDF/XM)
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*/
public void addOntologyToGenerate(Reader ontologyFile, String rdflang, String ontologyURI, String packagename) {
addOntologyToGenerate(ontologyFile, ONT_LANG_OWL, rdflang, ontologyURI, packagename);
}
/**
* Specify an ontology to generate
*
* @param ontologyFile
* The Reader containing the ontology document
* @param ontLang
* The Ontology Language, owl or rdfs.
* @param rdflang
* The serialization format of the ontology file (N3,RDF/XM,)
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*/
public void addOntologyToGenerate(Reader ontologyFile, String ontLang, String rdflang, String ontologyURI, String packagename) {
try {
RDFFormat rdfFormat = null;
if (rdflang != null) {
if (rdflang.equals("RDF/XML")) {
rdflang = "RDFXML";
}
rdfFormat = RDFFormat.valueOf(rdflang);
} else {
rdfFormat = RDFFormat.RDFXML;
}
INamedGraph temp = createOntGraph(false, ontLang);
ReadWriteUtils.loadGraph(temp, ontologyFile, rdfFormat, ontologyURI);
if (ontLang != null && ontLang.equals(ONT_LANG_RDFS)) {
temp = Rdfs2Owl.convertToOwl(temp, ontologyURI);
}
addConcreteEnumClasses(temp);
ReadWriteUtils.addGraph(temp, ontGraph);
registerOntology(temp, ontologyURI, packagename, true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Specify an ontology to generate
*
* @param ontGraph
* An INamedGraph containing the ontology
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*/
public void addOntologyToGenerate(INamedGraph ontGraph, String ontologyURI, String packagename) {
ReadWriteUtils.addGraph(ontGraph, this.ontGraph);
registerOntology(ontGraph, ontologyURI, packagename, true);
}
/**
* Specify an ontology dependency
*
* @param ontGraph
* An INamedGraph containing the ontology
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*/
public void addOntologyDependency(INamedGraph ontGraph, String ontologyURI, String packagename) {
ReadWriteUtils.addGraph(ontGraph, this.ontGraph);
registerOntology(ontGraph, ontologyURI, packagename, false);
}
/**
* Specify an ontology needed by one of the generation ontologies. One of these entries should be added for every import in every ontology to generate. We
* have this call because imports aren't automatically loaded.
*
* @param ontologyFile
* The Reader containing the ontology document
* @param rdflang
* The seriazation format of the ontology file (N3,RDF/XM,...all supported formats)
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*
* private void addOntologyDependency(Reader ontologyFile, String rdflang, String ontologyURI, String packagename) {
* addOntologyDependency(ontologyFile, ONT_LANG_OWL, rdflang, ontologyURI, packagename); }
*/
/**
* Specify an ontology needed by one of the generation ontologies. One of these entries should be added for every import in every ontology to generate. We
* have this call because imports aren't automatically loaded.
*
* @param ontologyFile
* The Reader containing the ontology document
* @param ontLang
* The Ontology Language, owl or rdfs.
* @param rdflang
* The serialization format of the ontology file (N3,RDF/XM)
* @param ontologyURI
* The URI of the ontology
* @param packagename
* The Java package that generate classes should be in.
*/
public void addOntologyDependency(Reader ontologyFile, String ontLang, String rdflang, String ontologyURI, String packagename) {
try {
INamedGraph temp = createOntGraph(false, ontLang);
if (rdflang != null && !rdflang.equals("RDF/XML"))
ReadWriteUtils.loadGraph(temp, ontologyFile, RDFFormat.valueOf(rdflang), ontologyURI);
else
ReadWriteUtils.loadGraph(temp, ontologyFile, RDFFormat.RDFXML, ontologyURI);
if (ontLang != null && ontLang.equals(ONT_LANG_RDFS)) {
temp = Rdfs2Owl.convertToOwl(temp, ontologyURI);
}
addConcreteEnumClasses(temp);
ReadWriteUtils.addGraph(temp, ontGraph);
registerOntology(temp, ontologyURI, packagename, false);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Return a List of OntologyClass objects representing all the classes to be generated.
*
* @return a List of OntologyClass objects representing all the classes to be generated.
*/
public List<OntologyClass> listOntologyClassesToGenerate() {
List<OntologyClass> classes = new ArrayList<OntologyClass>();
for (Resource resource : classesToGenerate) {
org.openanzo.rdf.owl.Class oc = OWL11Factory.getClass(resource, ontGraph);
classes.add(new OntologyClass(oc, this));
}
return classes;
}
/**
* Return a list of Ontology objects representing all the ontologies to be generated
*
* @return a list of Ontology objects representing all the ontologies to be generated
*/
public List<Ontology> listOntologiesToGenerate() {
return ontologiesToGenerate;
}
/**
* Determine if we generate listeners for the beans
*
* @return true if we generate listeners for the beans, default true
*/
public boolean isGenerateListeners() {
return generateListeners;
}
/**
* Indicate whether or not to generate listeners, default true
*
* @param generateListeners
* set whether or not to generate listeners
*/
public void setGenerateListeners(boolean generateListeners) {
this.generateListeners = generateListeners;
}
/**
* Determine if we generate only vocabulary files for the ontology
*
* @return true if we generate only vocabulary files for the ontology
*/
public boolean isGenerateVocabularyOnly() {
return generateVocabularyOnly;
}
/**
* Set if we generate only vocabulary files for the ontology
*
* @param generateVocabularyOnly
* sets if we generate only vocabulary files for the ontology
*/
public void setGenerateVocabularyOnly(boolean generateVocabularyOnly) {
this.generateVocabularyOnly = generateVocabularyOnly;
}
/**
* Determine if we use the entire URI for identifiers
*
* @return true if we use the entire URI for identifiers
*/
public boolean isUseEntireURIForIdentifiers() {
return useEntireURIForIdentifiers;
}
/**
* Set if we use the entire URI for identifiers
*
* @param useEntireURIForIdentifiers
* sets if we use the entire URI for identifiers
*/
public void setUseEntireURIForIdentifiers(boolean useEntireURIForIdentifiers) {
this.useEntireURIForIdentifiers = useEntireURIForIdentifiers;
}
public boolean isSearchSubClassHierarchyForCardRes() {
return searchSubClassHierarchyForCardRes;
}
public void setSearchSubClassHierarchyForCardRes(boolean searchSubClassHierarchyForCardRes) {
this.searchSubClassHierarchyForCardRes = searchSubClassHierarchyForCardRes;
}
/**
* Determine if we generate a cache of objects within the ontology factory
*
* @return true if we generate a cache of objects within the ontology factory
*/
public boolean isGenerateCacheInFactory() {
return generateCacheInFactory;
}
/**
* Set if we generate a cache of objects within the ontology factory
*
* @param generateCacheInFactory
* sets if we generate a cache of objects within the ontology factory
*/
public void setGenerateCacheInFactory(boolean generateCacheInFactory) {
this.generateCacheInFactory = generateCacheInFactory;
}
/**
* Determine if we use package names for restricted ranges
*
* @return true if we use package names for restricted ranges
*/
public boolean isUsePackageNameForRestrictedRanges() {
return usePackageNameForRestrictedRanges;
}
/**
* Set if we use package names for restricted ranges
*
* @param usePackageNameForRestrictedRanges
* sets if we use package names for restricted ranges
*/
public void setUsePackageNameForRestrictedRanges(boolean usePackageNameForRestrictedRanges) {
this.usePackageNameForRestrictedRanges = usePackageNameForRestrictedRanges;
}
/**
* Determine if we use strict type checking
*
* @return true if we use strict type checking
*/
public boolean isUseStrictTypeChecking() {
return useStrictTypeChecking;
}
/**
* Set if we use strict type checking
*
* @param useStrictTypeChecking
* sets if we use strict type checking
*/
public void setUseStrictTypeChecking(boolean useStrictTypeChecking) {
this.useStrictTypeChecking = useStrictTypeChecking;
}
/**
* Determine if we generate standard code
*
* @return true if we generate standard code
*/
public boolean isGenerateStandardCode() {
return generateStandardCode;
}
/**
* Set if we generate standard code
*
* @param generateStandardCode
* sets if we generate standard code
*/
public void setGenerateStandardCode(boolean generateStandardCode) {
this.generateStandardCode = generateStandardCode;
}
/**
* Determine if we used typed literals
*
* @return true if we used typed literals
*/
public boolean isUseTypedLiterals() {
return useTypedLiterals;
}
/**
* Set if we used typed literals
*
* @param useTypedLiterals
* sets if we used typed literals
*/
public void setUseTypedLiterals(boolean useTypedLiterals) {
this.useTypedLiterals = useTypedLiterals;
}
/**
* Determine if all RDF types in the classes hierarchy should be added
*
* @return true if all RDF types in the classes hierarchy should be added
*/
public boolean isAddAllRDFTypesInHierarchy() {
return addAllRDFTypesInHierarchy;
}
/**
* Set if all RDF types in the classes hierarchy should be added
*
* @param addAllRDFTypesInHierarchy
* sets if all RDF types in the classes hierarchy should be added
*/
public void setAddAllRDFTypesInHierarchy(boolean addAllRDFTypesInHierarchy) {
this.addAllRDFTypesInHierarchy = addAllRDFTypesInHierarchy;
}
/**
* Get the INamedGraph that contains the ontology data
*
* @return the INamedGraph that contains the ontology data
*/
public INamedGraph getOntGraph() {
return ontGraph;
}
/**
*
* @return ont dataset
*/
public IDataset getOntDataset() {
return ontDataset;
}
/**
*
* @return ont dataset
*/
public IQuadStore getOntGraphQuadStore() {
return ontGraphQuadStore;
}
/**
* Get the Ontology for the given class URI
*
* @param ontClassURI
* URI of class for which to get ontology
* @return URI of ontology for given class
*/
public URI getOntologyForClass(Resource ontClassURI) {
return ontologyClassMap.get(ontClassURI);
}
/**
* Get the Package name for the given class URI
*
* @param ontClassURI
* URI of class for which to get Package
* @return Package for given class
*/
public String getPackageForClass(Resource ontClassURI) {
return ontologyClassPackageMap.get(ontClassURI);
}
/**
* Get the Ontology for the given Package
*
* @param pkg
* Package for which to get ontology
* @return URI of ontology for given Package
*/
public URI getOntologyForPackage(String pkg) {
return packageOntologyMap.get(pkg);
}
/**
* Return a list of OntologyClass that the given class should extend because the returned classes are unions of classuri. Returns an empty list if no
* extensions exist. We pre-compute this table because the corresponding per-class query is messy and inefficient.
*
* @param classURI
* URI of class to get OntologyClasses for
* @return list of OntologyClass that the given class
*/
public List<OntologyClass> getUnionClassExtensions(Resource classURI) {
List<OntologyClass> list = unionTable.get(classURI);
if (list == null)
return new ArrayList<OntologyClass>();
return list;
}
/**
* Return a list or OntologyProperty that are properies declared with a domain that is a union of classes.
*
* @param classuri
* URI of union domain
* @return list or OntProperty that are properies declared with a domain
*/
public List<OntologyProperty> getUnionDomainProperties(Resource classuri) {
List<OntologyProperty> list = unionDomainTable.get(classuri);
if (list == null)
return new ArrayList<OntologyProperty>();
return list;
}
/**
* Add a generation template to be run for each ontology class
*
* @param name
* template name
* @param ontgen
* template for code generation
*/
public void addOntologyClassTemplate(String name, OntologyClassTemplate ontgen) {
ontologyClassTemplates.put(name, ontgen);
}
/**
* Add a generation template to be run for each ontology
*
* @param name
* template name
* @param ontgen
* template for code generation
*/
public void addOntologyTemplate(String name, OntologyTemplate ontgen) {
ontologyTemplates.put(name, ontgen);
}
/**
* Get the mapping of ontology class template names to their template class
*
* @return the mapping of ontology class template names to their template class
*/
public Map<String, OntologyClassTemplate> getOntologyClassTemplates() {
return ontologyClassTemplates;
}
/**
* Get the mapping of ontology template names to their template class
*
* @return the mapping of ontology template names to their template class
*/
public Map<String, OntologyTemplate> getOntologyTemplates() {
return ontologyTemplates;
}
/**
* Add a new mapping between a prefix and a full namespace.
*
* @param ns
* full namespace
* @param prefix
* prefixed namespace
*/
public void setNamespacePrefix(String ns, String prefix) {
namespacePrefixes.put(ns, prefix);
}
/**
* Get the prefix for a namespace
*
* @param ns
* namespace to lookup
* @return prefix for the namespace, or if no prefix is found, ns[number] is used
*/
public String getNamespacePrefix(String ns) {
String prefix = namespacePrefixes.get(ns);
if (prefix == null) {
prefix = "ns" + curPrefixNumber++;
namespacePrefixes.put(ns, prefix);
}
return prefix;
}
/**
* Check if ontology and class are part of same ontology
*
* @param ontPropertyUri
* URI of property to check
* @param ontClassUri
* URI of class to check
* @return true if ontology and class are part of same ontology
*/
public boolean isPropetyAndClassDefinedInSameOntology(Resource ontPropertyUri, Resource ontClassUri) {
Resource propOnt = ontologyPropertyMap.get(ontPropertyUri);
Resource classOnt = ontologyClassMap.get(ontClassUri);
if (propOnt == null || ontClassUri == null)
return false;
return propOnt.equals(classOnt);
}
private void registerOntology(INamedGraph tempont, String ontURI, String packagename, boolean generate) {
URI ontologyURI = Constants.valueFactory.createURI(ontURI);
ontDataset.addNamedGraph(ontologyURI).add(tempont.getStatements());
ontologyPackageMap.put(ontologyURI, packagename);
packageOntologyMap.put(packagename, ontologyURI);
List<org.openanzo.rdf.owl.Class> classes = OWL11Factory.getAllClass(tempont);
List<Resource> classuris = new ArrayList<Resource>();
for (org.openanzo.rdf.owl.Class oc : classes) {
if (!(oc.resource() instanceof BlankNode)) {
ontologyClassPackageMap.put(oc.resource(), packagename);
ontologyClassMap.put(oc.resource(), ontologyURI);
if (generate) {
classuris.add(oc.resource());
classesToGenerate.add(oc.resource());
}
}
}
List<org.openanzo.rdf.owl.DatatypeProperty> dataProps = OWL11Factory.getAllDatatypeProperty(tempont);
for (DatatypeProperty prop : dataProps) {
if (ontologyPropertyMap.containsKey(prop.resource())) {
System.err.println("Warning: " + prop.resource() + " defined in multiple ontologies");
} else {
ontologyPropertyMap.put(prop.resource(), ontologyURI);
}
}
List<org.openanzo.rdf.owl.ObjectProperty> objProps = OWL11Factory.getAllObjectProperty(tempont);
for (ObjectProperty prop : objProps) {
if (ontologyPropertyMap.containsKey(prop.resource())) {
System.err.println("Warning: " + prop.resource() + " defined in multiple ontologies");
} else {
ontologyPropertyMap.put(prop.resource(), ontologyURI);
}
}
if (generate) {
ontologiesToGenerate.add(new org.openanzo.rdf.jastor.inference.Ontology(ontURI, packagename, this, classuris));
}
}
private INamedGraph createOntGraph(boolean processImports, String ontLang) {
return new NamedGraph(Constants.valueFactory.createURI("http://openanzo.org/jastor/graph"));
}
private void buildUnionTable() {
List<OntologyClass> list = listOntologyClassesToGenerate();
for (int i = 0; i < list.size(); i++) {
OntologyClass oc = list.get(i);
org.openanzo.rdf.owl.Class ontClass = oc.getOntClass();
if (ontClass.resource() instanceof URI) {
Thing unionOf = ontClass.getUnionOf();
if (unionOf != null) {
Iterable<Value> unions = StatementUtils.getCollectionMembers(unionOf.resource(), getOntGraph());
for (Value val : unions) {
if (val instanceof Resource) {
org.openanzo.rdf.owl.Class op = OWL11Factory.getClass((Resource) val, getOntGraph());
if (op != null) {
List<OntologyClass> l = unionTable.get(op.resource());
if (l == null) {
l = new ArrayList<OntologyClass>();
unionTable.put(op.resource(), l);
}
l.add(oc);
}
}
}
}
}
}
}
private void buildUnionDomainTable() {
buildDPUnionDomainTable(OWL11Factory.getAllDatatypeProperty(ontGraph));
buildOPUnionDomainTable(OWL11Factory.getAllObjectProperty(ontGraph));
}
private void buildDPUnionDomainTable(List<DatatypeProperty> it) {
for (DatatypeProperty prop : it) {
OntologyProperty op = new OntologyProperty(prop, this);
if (prop.getDomain() != null && (prop.getDomain().resource() instanceof BlankNode)) {
org.openanzo.rdf.owl.Class clazz = OWL11Factory.getClass(prop.getDomain().resource(), getOntGraph());
Thing union = clazz.getUnionOf();
Iterable<Value> unions = StatementUtils.getCollectionMembers(union.resource(), getOntGraph());
for (Value val : unions) {
if (val instanceof Resource) {
org.openanzo.rdf.owl.Class oc = OWL11Factory.getClass((Resource) val, getOntGraph());
if (oc != null) {
List<OntologyProperty> l = unionDomainTable.get(oc.resource());
if (l == null) {
l = new ArrayList<OntologyProperty>();
unionDomainTable.put(oc.resource(), l);
}
l.add(op);
}
}
}
}
}
}
private void buildOPUnionDomainTable(List<ObjectProperty> it) {
for (ObjectProperty prop : it) {
OntologyProperty op = new OntologyProperty(prop, this);
if (prop.getDomain() != null && (prop.getDomain().resource() instanceof BlankNode)) {
org.openanzo.rdf.owl.Class clazz = OWL11Factory.getClass(prop.getDomain().resource(), getOntGraph());
Thing union = clazz.getUnionOf();
Iterable<Value> unions = StatementUtils.getCollectionMembers(union.resource(), getOntGraph());
for (Value val : unions) {
if (val instanceof Resource) {
org.openanzo.rdf.owl.Class oc = OWL11Factory.getClass((Resource) val, getOntGraph());
if (oc != null) {
List<OntologyProperty> l = unionDomainTable.get(oc.resource());
if (l == null) {
l = new ArrayList<OntologyProperty>();
unionDomainTable.put(oc.resource(), l);
}
l.add(op);
}
}
}
}
}
}
private void fillInDomainRangeFromSuperProperties() {
List<DatatypeProperty> properties = OWL11Factory.getAllDatatypeProperty(getOntGraph());
for (DatatypeProperty property : properties) {
fillIn(property, new ArrayList<_Property>());
}
List<ObjectProperty> properties2 = OWL11Factory.getAllObjectProperty(getOntGraph());
for (ObjectProperty property : properties2) {
fillIn(property, new ArrayList<_Property>());
}
}
private Resource[] fillIn(_Property prop, List<_Property> visited) {
if (visited.contains(prop))
return new Resource[2];
visited.add(prop);
// while the proper behavior of this method is undefined,
// use the following guidelines:
// - if a property defines it own domain/range, use it.
// - takethe domain or range from a super-property.
// - super-prop domain/ranges yield to a complete
// complete d/r range pairs from super property
org.openanzo.rdf.rdfs.Class domain = OntologyProperty.getDomain(prop);
Thing range = OntologyProperty.getRange(prop);
Resource domainResource = (domain != null) ? domain.resource() : null;
Resource rangeResource = (range != null) ? range.resource() : null;
Resource[] vals = { domainResource, rangeResource };
if (domain == null || range == null) {
final int DOMAIN = 0;
final int RANGE = 1;
boolean domainSet = domain != null;
boolean rangeSet = range != null;
List<_Property> it = OntologyUtils.getSuperProperties(prop, false);
for (_Property ontProp : it) {
Resource[] parVals = fillIn(ontProp, visited);
if (!domainSet && parVals[DOMAIN] != null)
vals[DOMAIN] = parVals[DOMAIN];
if (!rangeSet && parVals[RANGE] != null)
vals[RANGE] = parVals[RANGE];
if ((domainSet && vals[RANGE] != null) || (rangeSet && vals[DOMAIN] != null) || (vals[DOMAIN] != null && vals[RANGE] != null)) {
break;
}
}
if (!domainSet && vals[DOMAIN] != null)
OntologyProperty.setDomain(prop, vals[DOMAIN]);
if (!rangeSet && vals[RANGE] != null)
OntologyProperty.setRange(prop, vals[RANGE]);
return vals;
} else {
return new Resource[] { domainResource, rangeResource };
}
}
private void setupDefaultTemplates() {
addOntologyClassTemplate("Interface", new InterfaceTemplate(new OntologyClassFileProvider() {
public File getFile(OntologyClass oc, File outputDir) {
return oc.getInterfaceFile(outputDir);
}
}));
if (!isGenerateVocabularyOnly()) {
addOntologyClassTemplate("Implementation", new ImplementationTemplate(new OntologyClassFileProvider() {
public File getFile(OntologyClass oc, File outputDir) {
return oc.getImplFile(outputDir);
}
}));
addOntologyTemplate("Factory", new FactoryTemplate(new OntologyFileProvider() {
public File getFile(Ontology ont, File outputDir) {
return ont.getFactoryFile(outputDir);
}
}));
if (isGenerateListeners()) {
addOntologyClassTemplate("Listener", new ListenerTemplate(new OntologyClassFileProvider() {
public File getFile(OntologyClass oc, File outputDir) {
return oc.getListenerFile(outputDir);
}
}));
}
}
}
private void addRDFTypeToEnumerationClassMembers() {
List<org.openanzo.rdf.owl.Class> itr = OWL11Factory.getAllClass(ontGraph);
for (org.openanzo.rdf.owl.Class clazz : itr) {
Thing oneOf = clazz.getOneOf();
if (oneOf != null) {
Iterable<Value> unions = StatementUtils.getCollectionMembers(oneOf.resource(), getOntGraph());
for (Value val : unions) {
if (val instanceof Resource) {
if (!ontGraph.contains((Resource) val, RDF.TYPE, clazz.resource())) {
ontGraph.add((Resource) val, RDF.TYPE, clazz.resource());
}
}
}
}
}
}
private void addConcreteEnumClasses(INamedGraph tempOnt) {
List<org.openanzo.rdf.owl.Class> itr = OWL11Factory.getAllClass(tempOnt);
List<org.openanzo.rdf.owl.Class> list = new LinkedList<org.openanzo.rdf.owl.Class>();
for (org.openanzo.rdf.owl.Class clazz : itr) {
Thing oneOf = clazz.getOneOf();
if (oneOf != null) {
list.add(clazz);
}
}
for (org.openanzo.rdf.owl.Class clazz : list) {
if (clazz.resource() instanceof BlankNode) {
try {
Iterable<Statement> stmts = tempOnt.find(null, RDFS.range, clazz.resource());
for (Statement stmt : stmts) {
Resource prop = stmt.getSubject();
_Property ontProp = RDFSFactory.get_Property(prop, tempOnt);
OntologyProperty op = new OntologyProperty(ontProp, this);
String uri = GEN_NS + op.getPropertyCapped() + "Enum";
org.openanzo.rdf.owl.Class ec2 = OWL11Factory.createClass(uri, tempOnt);
ec2.setOneOf(clazz.getOneOf());
if (ontProp.isRDFType(DatatypeProperty.TYPE)) {
DatatypeProperty dp = OWL11Factory.getDatatypeProperty(ontProp.resource(), tempOnt);
dp.setRange(ec2);
} else if (ontProp.isRDFType(ObjectProperty.TYPE)) {
ObjectProperty objp = OWL11Factory.getObjectProperty(ontProp.resource(), tempOnt);
objp.setRange(ec2);
}
for (Value value : StatementUtils.getCollectionMembers(ec2.getOneOf().resource(), tempOnt)) {
tempOnt.add(Constants.valueFactory.createURI(value.toString()), RDF.TYPE, Constants.valueFactory.createURI(uri));
}
}
} catch (Exception e) {
System.err.println("Warning, bad anonymous Enum (oneOf) class found");
}
}
}
}
/**
* Get the base literal Class for this context
*
* @return the base literal Class for this context
*/
public Class<?> getBaseLiteralClass() {
return baseLiteralClass;
}
/**
* Set the base literal Class for this context
*
* @param baseLiteralClass
* the name of the base literal Class for this context
* @throws JastorException
* if the Class does not exist
*/
public void setBaseLiteralClass(String baseLiteralClass) throws JastorException {
try {
this.baseLiteralClass = Class.forName(baseLiteralClass);
} catch (Exception e) {
throw new JastorException(e, "Error loading base literal class");
}
}
/**
* Determine if code returns null on missing types
*
* @return true if code returns null on missing types
*/
public boolean isReturnNullOnMissingTypes() {
return returnNullOnMissingTypes;
}
/**
* Set if code returns null on missing types
*
* @param returnNullOnMissingTypes
* Set if code returns null on missing types
*/
public void setReturnNullOnMissingTypes(boolean returnNullOnMissingTypes) {
this.returnNullOnMissingTypes = returnNullOnMissingTypes;
}
/**
* Determine if generated code should include copyright statements
*
* @return true if generated code should include copyright statements
*/
public boolean isIncludeCopyright() {
return includeCopyright;
}
/**
* Set if generated code should include copyright statements
*
* @param includeCopyright
* Set if generated code should include copyright statements
*/
public void setIncludeCopyright(boolean includeCopyright) {
this.includeCopyright = includeCopyright;
}
/**
* Set a remapped namespace for the given namespace
*
* @param namespace
* namespace to replace
* @param remappedNamesapce
* remapped namespace to use in its place
*/
public void setNamespaceRemapper(String namespace, String remappedNamesapce) {
this.namespaceRemapper.put(namespace, remappedNamesapce);
}
/**
* Determine if the namespace for a URI needs to be replace, and replace if necessary
*
* @param uri
* URI to check
* @return a new URI with its namespace remapped, if there is a remapping for the namespace
*/
public String remapUri(URI uri) {
String result = uri.toString();
for (Map.Entry<String, String> entry : namespaceRemapper.entrySet()) {
if (result.contains(entry.getKey())) {
return result.replace(entry.getKey(), entry.getValue());
}
}
return result;
}
/**
* Determine if the namespace for a URI needs to be replace, and replace if necessary
*
* @param uri
* URI to check
* @return a new URI with its namespace remapped, if there is a remapping for the namespace
*/
public String remapUri(String uri) {
String result = uri;
for (Map.Entry<String, String> entry : namespaceRemapper.entrySet()) {
if (result.contains(entry.getKey())) {
return result.replace(entry.getKey(), entry.getValue());
}
}
return result;
}
/**
* Get sorted classes
*
* @return sorted classes
* @throws JastorException
*/
public List<OntologyClass> getClassesSorted() throws JastorException {
List<OntologyClass> classes = new ArrayList<OntologyClass>();
for (Ontology ont : ontologiesToGenerate) {
classes.addAll(ont.getClasses());
}
IGraph graph = new GraphMem("classes");
for (OntologyClass oc : classes) {
INode node = new NodeMem(oc.getURI().toString());
node.setData(oc);
graph.addNode(node);
}
for (OntologyClass oc : classes) {
INode src = graph.getNodeByName(oc.getURI().toString());
for (OntologyClass oc2 : oc.listImmediateExtensionClasses()) {
INode dst = graph.getNodeByName(oc2.getURI().toString());
if (dst == null)
continue;
IEdge edge = new EdgeMem(oc.getURI() + "->" + oc2.getURI(), src, dst);
graph.addEdge(edge);
}
}
DFS dfs = new DFS();
dfs.setGraph(graph);
dfs.execute();
List<OntologyClass> sorted = new ArrayList<OntologyClass>();
for (INode node : dfs.getNodesByFinishTime()) {
OntologyClass oc = (OntologyClass) node.getData();
sorted.add(0, oc);
}
return sorted;
}
/**
*
* @param classUri
* @param propUri
* @param res
*/
public void addSubClassRestriction(String classUri, String propUri, Restriction res) {
Restriction[] holder = new Restriction[] { res };
subClassRestrictions.put(classUri + "|" + propUri, holder);
}
/**
*
* @param classUri
* @param propUri
* @return sub class restrictions
*/
public Restriction[] getSubClassRestriction(String classUri, String propUri) {
return subClassRestrictions.get(classUri + "|" + propUri);
}
/**
*
* @param classUri
* @param propUri
* @param res
*/
public void addRestriction(String classUri, String propUri, Restriction[] res) {
baseRestrictions.put(classUri + "|" + propUri, res);
}
/**
*
* @param classUri
* @param propUri
* @return sub class restrictions
*/
public Restriction[] getRestriction(String classUri, String propUri) {
return baseRestrictions.get(classUri + "|" + propUri);
}
/**
*
* @return the open domain properties within the context
*/
public List<_Property> getOpenDomainProperties() {
if (odProps != null) {
return odProps;
} else {
odProps = new ArrayList<_Property>();
// There might be inconsistent behavior when adding open domain properties to the
// class frames..so, we basically have to do it ourselves, and rule out duplicates
// in the case that they are provided
Resource[] openDomainResources = new Resource[] { RDFS.RESOURCE, _Thing.TYPE };
for (int i = 0; i < openDomainResources.length; i++) {
Iterable<Statement> stmts = getOntGraph().find(null, RDFS.domain, openDomainResources[i]);
for (Statement stmt : stmts) {
Resource propres = stmt.getSubject();
_Property prop = RDFSFactory.get_Property(propres, ontGraph);
if (!odProps.contains(prop))
odProps.add(prop);
}
}
Resource[] propTypes = new Resource[] { OWL.DATATYPEPROPERTY, OWL.OBJECTPROPERTY };
for (int i = 0; i < propTypes.length; i++) {
String sparql = "SELECT ?res " + " { ?res a " + QueryEncoder.encodeForQuery(propTypes[i]) + " . " + " OPTIONAL { ?res <" + RDFS.domain + "> ?prop . } " + " FILTER (!bound(?prop)) . " + " } ";
QuadStoreEngineConfig config = new QuadStoreEngineConfig(getOntGraphQuadStore());
Engine glitter = new Engine(config);
try {
QueryResults results = glitter.executeQuery(null, sparql, Collections.singleton(ontGraph.getNamedGraphUri()), Collections.<URI> emptySet());
Iterator<PatternSolution> iter = results.getSelectResults().iterator();
while (iter.hasNext()) {
PatternSolution next = iter.next();
Resource propres = (Resource) next.getBinding("res");
_Property prop = RDFSFactory.get_Property(propres, ontGraph);
if (!odProps.contains(prop))
odProps.add(prop);
}
} catch (Exception ge) {
ge.printStackTrace();
}
}
return odProps;
}
}
/**
*
* @param classUri
* @param properties
*/
public void setDeclaredProperties(URI classUri, List<_Property> properties) {
this.declProps.put(classUri, properties);
}
/**
*
* @param classUri
* @return declared properties
*/
public List<_Property> getDeclaredProperties(URI classUri) {
return this.declProps.get(classUri);
}
}