/******************************************************************************* * 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/inference/OntologyProperty.java,v $ * Created by: * Created on: 01/23/2007 * Revision: $Id: OntologyProperty.java 172 2007-07-31 14:22:23Z mroy $ * * Contributors: * IBM Corporation - initial API and implementation * C Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.rdf.jastor.inference; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; 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.INamedGraph; import org.openanzo.rdf.Literal; import org.openanzo.rdf.Resource; import org.openanzo.rdf.Statement; import org.openanzo.rdf.TypedLiteral; import org.openanzo.rdf.URI; import org.openanzo.rdf.Value; import org.openanzo.rdf.datatype.TypedValueMapper; import org.openanzo.rdf.jastor.JastorContext; import org.openanzo.rdf.jastor.JastorException; import org.openanzo.rdf.jastor.JavaIdentifierEncoder; import org.openanzo.rdf.jastor.Thing; import org.openanzo.rdf.owl.DataRange; import org.openanzo.rdf.owl.DatatypeProperty; import org.openanzo.rdf.owl.FunctionalProperty; 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.query.QuadStoreEngineConfig; import org.openanzo.rdf.query.QueryEncoder; import org.openanzo.rdf.rdfs._Property; import org.openanzo.rdf.utils.StatementUtils; import org.openanzo.rdf.vocabulary.OWL; import org.openanzo.rdf.vocabulary.RDF; import org.openanzo.rdf.vocabulary.RDFS; import org.openanzo.rdf.vocabulary.XMLSchema; /** * Represents an Ontology Property * * @author Ben Szekely ( <a href="mailto:bhszekel@us.ibm.com">bhszekel@us.ibm.com </a>) * */ public class OntologyProperty { /** * this uri is a placeholder for the default range of a property that is returned by getAllReturnTypes. We don't use the actual default return type URI in * that call because it might be null. */ public static final URI DEFAULT_RANGE = Constants.valueFactory.createURI("http://jastor.adtech.ibm.com/defaultRange"); /** This property is defined within itself */ public static final int ROLE_HERE = 0; /** This property is defined in an extension class */ protected static final int ROLE_EXTENSIONCLASS = 1; /** This property is a placeholder for a loose restriction to send downstream */ private static final int ROLE_LOOSE_RESTRICTION = 2; /** List of restrictions where the end of the list contains the most downstream restriction */ private final List<Restriction> restrictions = new ArrayList<Restriction>(); /** * this list stores multiple ranges in the case that the the range of the property is defined as a Union. Otherwise, the list will not be used. These will * considered as coming from the active class. we may eventually clean this up when we see more clearly how these multiple ranges are used. */ private final List<Resource> ranges = new ArrayList<Resource>(); /** * The ontology class where this property was originally defined, i.e. the top of the hierarchy. */ private final OntologyClass ontologyClass; private final _Property ontProperty; private final org.openanzo.rdf.owl.Class ontClass; private final INamedGraph ontGraph; private final JastorContext ctx; private final OntologyComment comment; /** * the active class is the ontology class that this property is being used to generate, not to be confused with the ontologyClass where the property was * originally defined */ private OntologyClass activeClass; /** * The role of this property class, see above for the different options */ private int role = ROLE_HERE; /** * If this flag is true, it means that this property exists in the frame of an ontology class that has another property with the same local name */ private boolean duplicateProperty = false; /** * Create a new Property * * @param ontProperty * the underlying Jastor property bean * @param ontologyClass * The parent class for this property * @throws JastorException */ public OntologyProperty(_Property ontProperty, OntologyClass ontologyClass) throws JastorException { long start = System.currentTimeMillis(); this.ontProperty = ontProperty; this.ontologyClass = ontologyClass; this.ontClass = ontologyClass.getOntClass(); this.activeClass = ontologyClass; ctx = ontologyClass.getContext(); this.ontGraph = ctx.getOntGraph(); computePrimaryRestrictions(); checkForMultipleBaseRanges(); this.comment = OntologyComment.getOntologyComment(this.ontGraph, this.ontProperty.resource()); if (RequestAnalysis.isAnalysisEnabled()) { long end = System.currentTimeMillis(); RequestAnalysis.incrementAnalysisPropertyCount("makeProp", end - start); } } /** * This version of the constructor should only be use if the instance is used for utility methods on the property..i.e. getName, etc... * * @param ontProperty * the underlying Jastor property bean * @param ctx * the parent jastor context * @throws JastorException */ public OntologyProperty(_Property ontProperty, JastorContext ctx) throws JastorException { this.ontProperty = ontProperty; this.ctx = ctx; comment = null; ontClass = null; ontGraph = null; ontologyClass = null; } /** * This constructor is used to create a place holder for loose restriciton on a property that might not actually be found in the search because of the * visited list. OntologyClasses should return instances of these properties if they have restrictions on properties not found in their recursive search. * * @param ontProperty */ OntologyProperty(_Property ontProperty, Restriction restriction) { this.ontProperty = ontProperty; restrictions.add(restriction); role = ROLE_LOOSE_RESTRICTION; comment = null; ctx = null; ontClass = null; ontGraph = null; ontologyClass = null; } /** * Returns whether or not this instance is a placeholder for a restriction on a property * * @return whether or not this instance is a placeholder for a restriction on a property */ public boolean isLooseRestriction() { return (ontologyClass == null); } /** * Get the role of the property's participation in the owning class. * * @return the role of the property's participation in the owning class. */ public int getRole() { return role; } /** * set the role of the property * * @param role * the role of the property */ public void setRole(int role) { this.role = role; } /** * Get the ontology class begin generated. * * @return the ontology class begin generated. */ public OntologyClass getActiveClass() { return activeClass; } /** * Set the active class for the property * * @param activeClass * the active class for the property */ public void setActiveClass(OntologyClass activeClass) { this.activeClass = activeClass; } /** * Get the ontology class that declares this property * * @return the ontology class that declares this property */ public OntologyClass getOntologyClass() { return ontologyClass; } /** * Get the jastor Property bean for this property * * @return the jastor Property bean for this property */ public _Property getOntProperty() { return ontProperty; } /** * Get the comment info for this property * * @return the comment info for this property */ public OntologyComment getComment() { return comment; } /** * yields the restriction declared with the original declaration of the property * * @return the restriction declared with the original declaration of the property */ public Restriction getPrimaryRestriction() { return restrictions.get(0); } /** * Add a restriction to the property * * @param res * restriction to add */ protected void addRestriction(Restriction res) { // must check if we already have this restriction if (!restrictions.contains(res)) restrictions.add(res); } /** * Add a list of restrictions to the property * * @param res * a list of restrictions to the property */ protected void addRestrictions(List<Restriction> res) { for (Restriction r : res) { addRestriction(r); } } /** * Get the list of restrictions for the property * * @return the list of restrictions for the property */ public List<Restriction> getRestrictions() { return restrictions; } /** * Determine if this property can take on multiple values * * @return true if this property can take on multiple values */ public boolean isMultiValued() { // find the first cardinality restriction we see if (ontProperty.isRDFType(FunctionalProperty.TYPE)) return false; for (int i = restrictions.size() - 1; i >= 0; i--) { Restriction res = restrictions.get(i); Iterable<Integer> cardinal = res.getCardinality(); if (cardinal.iterator().hasNext()) { Integer cr = cardinal.iterator().next(); if (cr.longValue() > 1) return true; else return false; } Iterable<Integer> maxCardinal = res.getMaxCardinality(); if (maxCardinal.iterator().hasNext()) { Integer cr = maxCardinal.iterator().next(); if (cr.longValue() > 1) return true; else return false; } } return true; } /** * Is this property required * * @return true if this property is required */ public boolean isRequired() { for (int i = restrictions.size() - 1; i >= 0; i--) { Restriction res = restrictions.get(i); Iterable<Integer> cardinal = res.getCardinality(); if (cardinal.iterator().hasNext()) { Integer cr = cardinal.iterator().next(); if (cr.longValue() >= 1) return true; else return false; } Iterable<Integer> minCardinal = res.getMinCardinality(); if (minCardinal.iterator().hasNext()) { Integer cr = minCardinal.iterator().next(); if (cr.longValue() >= 1) return true; else return false; } } return false; } /** * Determine if this property is single valued * * @return if this property is single valued */ public boolean isSingleValued() { return !isMultiValued(); } /** * Determine if this is an Object property * * @return if this is an Object property */ public boolean isObjectProperty() { return ontProperty.isRDFType(ObjectProperty.TYPE); } /** * Determine if this is a Datatype property * * @return if this is a Datatype property */ public boolean isDatatypeProperty() { return ontProperty.isRDFType(DatatypeProperty.TYPE); } /** * Determine if the given value is contained in the property's DataRange. If the property does not have a data range, returns true. * * @param value * @return true if the given value is contained in the property's DataRange */ public boolean isValueInRange(Value value) { if (restrictions.isEmpty()) return true; Restriction restriction = getPrimaryRestriction(); Collection<Thing> valueRanges = restriction.getAllValuesFrom(); if (valueRanges.isEmpty()) return true; Thing valueRange = valueRanges.iterator().next(); // for now, assume that the oneOf contains all the same type. DataRange dr = OWL11Factory.getDataRange(valueRange.resource(), ontGraph); Thing oneOf = dr.getOneOf(); if (oneOf != null) { for (Value dataRangeVal : StatementUtils.getCollectionMembers(oneOf.resource(), ontGraph)) { if (dataRangeVal.equals(value)) return true; } } return false; } /** * Return the name of the property to be used for variable names and as a prefix for vocabulary property constants * * @return the name of the property to be used for variable names and as a prefix for vocabulary property constants */ public String getPropertyName() { if (ctx == null) { System.err.println(getURI()); System.err.println(isLooseRestriction()); } if (ctx != null && ctx.isUseEntireURIForIdentifiers()) return JavaIdentifierEncoder.encode(ontProperty.uri()); else { String name = JavaIdentifierEncoder.encode(Constants.valueFactory.createURI(ontProperty.uri()).getLocalName()); if (duplicateProperty) { name = addPrefix(name); } return name; } } /** * Return the name of the property to be used for variable names and constants using the restricted range argument * * @param restrictedRange * restrictedRange argument * @return the name of the property to be used for variable names and constants using the restricted range argument */ public String getPropertyName(Resource restrictedRange) { // handle the case where we are being called with the default range if (restrictedRange != null && restrictedRange.equals(DEFAULT_RANGE)) return getPropertyName(); String resrange = getReturnType(restrictedRange); if (ctx.isUsePackageNameForRestrictedRanges()) resrange = resrange.replace('.', '_'); else resrange = resrange.substring(resrange.lastIndexOf('.') + 1); String name = getPropertyName() + "_as" + resrange; if (duplicateProperty) { name = addPrefix(name); } return name; } /** * Return the name of the property capitalized, should be prepended for use in method names * * @return the name of the property capitalized, should be prepended for use in method names */ public String getPropertyCapped() { if (ctx.isUseEntireURIForIdentifiers()) return capitalize(JavaIdentifierEncoder.encode(ontProperty.uri())); else { String name = capitalize(JavaIdentifierEncoder.encode(Constants.valueFactory.createURI(ontProperty.uri()).getLocalName())); if (duplicateProperty) { name = capitalize(addPrefix(name)); } return name; } } /** * Return the name of the property capitalized, should be prepended for use in method names * * * @param restrictedRange * restrictedRange argument * @return the name of the property capitalized, should be prepended for use in method names */ public String getPropertyCapped(Resource restrictedRange) { // handle the case where we are being called with the default range if (restrictedRange != null && restrictedRange.equals(DEFAULT_RANGE)) return getPropertyCapped(); String resrange = getReturnType(restrictedRange); if (ctx.isUsePackageNameForRestrictedRanges()) resrange = resrange.replace('.', '_'); else resrange = resrange.substring(resrange.lastIndexOf('.') + 1); String toappend = ""; if (restrictedRange != null) { toappend = "_as" + resrange; } if (ctx.isUseEntireURIForIdentifiers()) return capitalize(JavaIdentifierEncoder.encode(ontProperty.uri()) + toappend); else { String name = capitalize(JavaIdentifierEncoder.encode(Constants.valueFactory.createURI(ontProperty.uri()).getLocalName()) + toappend); if (duplicateProperty) { name = capitalize(addPrefix(name)); } return name; } } // We need both of the next methods because some template sections will operate on all ranges // separately while others will operate on the default and alt together. Also, some will be interested in // alt ranges for the entire hierarchy, or just the activeClass /** * Return an Iterable of ranges for this property * * @param all * whether or not to include the default range in addition to all alt ranges * @param activeClassOnly * whether or not to include ranges in the activeClass only * @return an Iterable of ranges for this property */ public Iterable<Resource> listRanges(boolean all, boolean activeClassOnly) { if (all) return listAllRanges(activeClassOnly); else return listAlternativeRanges(activeClassOnly); } /** * Return an an Iterable of Resources that represent additional ranges for this property. The activeClassOnly flag determines if we consider only those * restrictions declared in the active class * * @param activeClassOnly * only return active class ranges * @return an Iterable of alternative ranges for this property */ public Iterable<Resource> listAlternativeRanges(boolean activeClassOnly) { List<Resource> list = listAlternativeRangesList(activeClassOnly); return list; } /** * Return an an Iterable of Resources that represent all possible ranges for this property gathered from the entire hierarchy. An element in the iterator * will be a special Resource indicating the default return type. As such, the items in the Iterator may be used in calls to getReturnType(), * getPropertyName(), and getPropertyCapped() but should not be treated as verbatim. * * @return an Iterable of all ranges */ public Iterable<Resource> listAllRanges() { return listAllRanges(false); } /** * Return an an interator or Resources that represent all possible ranges for this property. the boolean parameter indicates whether we should include * return types declared in the activeClass only or in the entire hiearchy. The active class is the class we are generating for. * * * @param activeClassOnly * only return active class ranges * @return an Iterable of all ranges */ private Iterable<Resource> listAllRanges(boolean activeClassOnly) { List<Resource> list = listAlternativeRangesList(activeClassOnly); // list.addAll(list); // we have to make sure that ranges don't get added twice because some ontologies // might cause this. if (!ranges.isEmpty()) { for (Resource range : ranges) { if (!list.contains(range)) list.add(range); } } else { if (!list.contains(DEFAULT_RANGE)) list.add(0, DEFAULT_RANGE); } return list; } /** * Get the string representation of the full java name of the return type for this property. The return type is based on the original range declaration of * the property. * * @return the string representation of the full java name of the return type for this property */ public String getReturnType() { Resource range = null; // check for multiple base ranges. if (!ranges.isEmpty()) { range = ranges.get(0); } else { range = getRange(); } return getReturnType(range); } /** * Get the string representation of the full java name of the return type for this property. * * @param range * indicates an alternative range or the DEFAULT_RANGE * @return the string representation of the full java name of the return type for this property */ public String getReturnType(Resource range) { if (range != null && range.equals(DEFAULT_RANGE)) return getReturnType(); try { if (isObjectProperty()) { if (range == null || range.equals(_Thing.TYPE) || range instanceof BlankNode) { return ctx.getThingInterface().getName(); } else { org.openanzo.rdf.owl.Class rangeclass = OWL11Factory.getClass(range, ontGraph); if (rangeclass == null || !rangeclass.isRDFType(org.openanzo.rdf.owl.Class.TYPE)) return ctx.getThingInterface().getName(); OntologyClass oc = new OntologyClass(rangeclass, ctx); return oc.getInterfaceFullClassname(); } } else { if (range == null || range.equals(RDFS.literal)) return ctx.getBaseLiteralClass().getName(); if (ontGraph.contains(range, RDF.TYPE, DataRange.TYPE)) { // for now, assume that the oneOf contains all the same time. DataRange dr = OWL11Factory.getDataRange(range, ontGraph); Thing oneOf = dr.getOneOf(); if (oneOf != null) { Iterable<Value> oneOfs = StatementUtils.getCollectionMembers(oneOf.resource(), ontGraph); Iterator<Value> it = oneOfs.iterator(); while (it.hasNext()) { Value val = it.next(); if (val instanceof Literal) { Literal lit = (Literal) val; if (lit instanceof TypedLiteral) { range = ((TypedLiteral) lit).getDatatypeURI(); } else { range = XMLSchema.STRING; } continue; } } } } java.lang.Class<?> cls = TypedValueMapper.getNativeClass((URI) range); if (cls == null) { return ctx.getBaseLiteralClass().getName(); } /* * what we had here seems decidedly wrong! if (cls == null) { cls = type.getClass(); } // not sure if this is better, but it seems to be what other reasoners // do if the didn't have a java class registered, ala XMLLiteral if (cls == null) cls = String.class;*/ return cls.getName(); } } catch (JastorException e) { e.printStackTrace(); return isDatatypeProperty() ? ctx.getBaseLiteralClass().getName() : ctx.getThingInterface().getName(); } } /** * Get the string representation of the full range datatype URI * * @param res * resource to get string representation * @return the string representation of the full range datatype URI */ public String getRangeURI(Resource res) { if (res != null && res.equals(DEFAULT_RANGE)) { if (!ranges.isEmpty()) { return (ranges.get(0)).toString(); } else { Resource propRange = getRange(); if (propRange == null) { if (isDatatypeProperty()) { return RDFS.literal.toString(); } else { return RDFS.RESOURCE.toString(); } } if (isDatatypeProperty() /*&& propRange instanceof BlankNode */) { if (ontGraph.contains(propRange, RDF.TYPE, DataRange.TYPE)) { // for now, assume that the oneOf contains all the same time. DataRange dr = OWL11Factory.getDataRange(propRange, ontGraph); Thing oneOf = dr.getOneOf(); if (oneOf != null) { Iterable<Value> oneOfs = StatementUtils.getCollectionMembers(oneOf.resource(), ontGraph); Iterator<Value> it = oneOfs.iterator(); while (it.hasNext()) { Value val = it.next(); if (val instanceof Literal) { Literal lit = (Literal) val; if (lit instanceof TypedLiteral) { propRange = ((TypedLiteral) lit).getDatatypeURI(); } else { propRange = XMLSchema.STRING; } continue; } } return propRange.toString(); } } } return propRange.toString(); } } else if (res != null) { return res.toString(); } else { return null; } } /** * Get the string representation of the full range datatype URI * * @return the string representation of the full range datatype URI */ public String getRangeURI() { return getRangeURI(DEFAULT_RANGE); } /** * Get the ontology class for the default range of this property * * @return the ontology class for the default range of this property */ public OntologyClass getRangeOntologyClass() { Resource propRange = getRange(); return getRangeOntologyClass(propRange); } /** * Get the ontology class for the given range of this property * * @param range * indicates an alternative range or the DEFAULT_RANGE * @return the ontology class for the given range of this property */ public OntologyClass getRangeOntologyClass(Resource range) { if (range != null && range.equals(DEFAULT_RANGE)) return getRangeOntologyClass(); if (isObjectProperty()) { if (range == null || range.equals(_Thing.TYPE) || range instanceof BlankNode) { return new OntologyClass(ctx); // OntologyClass for Thing } else { org.openanzo.rdf.owl.Class rangeclass = OWL11Factory.getClass(range, ctx.getOntGraph()); if (rangeclass == null || !rangeclass.isRDFType(org.openanzo.rdf.owl.Class.TYPE)) return new OntologyClass(ctx); OntologyClass oc = new OntologyClass(rangeclass, ctx); return oc; } } else { return null; } } /** * Return a list of RDFNodes that are values of hasValue for this property * * @return a list of RDFNodes that are values of hasValue for this property */ public List<Value> getHasValueValues() { List<Value> list = new ArrayList<Value>(); computePrimaryRestrictions(); Iterator<Restriction> it = restrictions.iterator(); while (it.hasNext()) { Restriction res = it.next(); // have to find the hasValue values manually because the generated Jastor OWL classes // assume its always a datatype property Iterable<Statement> stmts = ontGraph.find(res.resource(), Restriction.hasValueProperty, null); for (Statement stmt : stmts) { list.add(stmt.getObject()); } } return list; } /** * Set whether there can be duplicate properties * * @param duplicateProperty * whether there can be duplicate properties */ public void setDuplicateProperty(boolean duplicateProperty) { this.duplicateProperty = duplicateProperty; } /** * Get the Property's URI * * @return the Property's URI */ public String getURI() { return ontProperty.resource().toString(); } @Override public String toString() { return ontProperty.resource().toString(); } @Override public boolean equals(Object o) { if (isLooseRestriction()) return super.equals(o); // test equality only on actual properties if (!(o instanceof OntologyProperty)) { return false; } OntologyProperty other = (OntologyProperty) o; return getURI().equals(other.getURI()); } @Override public int hashCode() { if (isLooseRestriction()) return super.hashCode(); return getURI().hashCode(); } /** * Capitalize the first letter of a String * * @param string * String to Capitalize * @return Capitalize version of string */ private static String capitalize(String string) { return Character.toUpperCase(string.charAt(0)) + string.substring(1); } /** * list all possible return types other than the originally defined range. * * @param activeClassOnly * determines whether we consider range restrictions declared in the activeClass or the entire hierarchy * @return */ private List<Resource> listAlternativeRangesList(boolean activeClassOnly) { List<Resource> list = new ArrayList<Resource>(); for (int i = restrictions.size() - 1; i >= 0; i--) { Restriction res = restrictions.get(i); if (activeClassOnly) { // check if the restriction belongs to the active class if (!activeClass.getOntClass().graph().contains(activeClass.getOntClass().resource(), RDFS.subClassOf, res.resource())) { Thing intersectionOf = activeClass.getOntClass().getIntersectionOf(); if (intersectionOf != null) { List<Resource> intersectionClasses = new ArrayList<Resource>(); for (Value value : StatementUtils.getCollectionMembers(intersectionOf.resource(), ontGraph)) { if (value instanceof Resource) { intersectionClasses.add((Resource) value); } } if (!intersectionClasses.contains(res.resource())) continue; } else continue; } } Iterable<Thing> allValuesFrom = res.getAllValuesFrom(); Iterable<Thing> someValuesFrom = res.getAllValuesFrom(); if (allValuesFrom.iterator().hasNext()) { for (Thing nextThing : allValuesFrom) { Resource range = nextThing.resource(); Resource propRange = getRange(); if (propRange != null && propRange.equals(range)) { continue; } if (ontGraph.contains(range, RDF.TYPE, DataRange.TYPE)) continue; // don't support DataRange yet if (ontGraph.contains(range, OWL.ONEOF, null)) continue; // don't support owl:oneOf yet if (ontGraph.contains(range, org.openanzo.rdf.owl.Class.unionOfProperty, null)) addUnionOperands(range, list); else { if (!list.contains(range)) list.add(range); } } } else if (someValuesFrom.iterator().hasNext()) { for (Thing nextThing : someValuesFrom) { Resource range = nextThing.resource(); Resource propRange = getRange(); if (propRange != null && propRange.equals(range)) { continue; } if (ontGraph.contains(range, RDF.TYPE, DataRange.TYPE)) continue; // don't support DataRange yet if (ontGraph.contains(range, org.openanzo.rdf.owl.Class.unionOfProperty, null)) addUnionOperands(range, list); else { if (!list.contains(range)) list.add(range); } } } } return list; } private void addUnionOperands(Resource range, List<Resource> list) { Iterable<Statement> union = ontGraph.find(range, org.openanzo.rdf.owl.Class.unionOfProperty, null); for (Statement stmt : union) { if (stmt.getObject() instanceof Resource) { for (Value value : StatementUtils.getCollectionMembers((Resource) stmt.getObject(), ontGraph)) { if (value instanceof Resource) { ranges.add((Resource) value); } } } } } /** * Find the restriction(s) on this property in the enclosing class. Will also look for a cardinality restriction in the subclasses if one is not found here * * @throws JastorException */ private void computePrimaryRestrictions() throws JastorException { Restriction[] baseRestrictions = ctx.getRestriction(ontClass.resource().toString(), ontProperty.resource().toString()); if (baseRestrictions == null) { String query = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX owl: <http://www.w3.org/2002/07/owl#> SELECT ?res WHERE {" + QueryEncoder.encodeForQuery(ontClass.resource()) + " rdfs:subClassOf ?res . ?res owl:onProperty " + QueryEncoder.encodeForQuery(ontProperty.resource()) + "}"; QuadStoreEngineConfig config = new QuadStoreEngineConfig(ctx.getOntGraphQuadStore()); Engine glitter = new Engine(config); try { long start = 0; if (RequestAnalysis.isAnalysisEnabled()) { start = System.currentTimeMillis(); } QueryResults results = glitter.executeQuery(null, query, Collections.singleton(ontGraph.getNamedGraphUri()), Collections.<URI> emptySet()); Iterator<PatternSolution> iter = results.getSelectResults().iterator(); baseRestrictions = new Restriction[results.getSelectResults().size()]; int i = 0; while (iter.hasNext()) { Resource restrictionRes = (Resource) iter.next().getBinding("res"); Restriction restriction = OWL11Factory.getRestriction(restrictionRes, ontGraph); baseRestrictions[i++] = restriction; } ctx.addRestriction(ontClass.resource().toString(), ontProperty.resource().toString(), baseRestrictions); if (RequestAnalysis.isAnalysisEnabled()) { long end = System.currentTimeMillis(); RequestAnalysis.incrementAnalysisPropertyCount("cardQuery", end - start); } } catch (Exception e) { throw new JastorException(e, "Error querying for restriction"); } } Restriction cardrestriction = null; for (Restriction restriction : baseRestrictions) { Iterable<Integer> res = restriction.getCardinality(); if (res.iterator().hasNext()) { cardrestriction = restriction; } restrictions.add(restriction); } if (cardrestriction == null && ctx.isSearchSubClassHierarchyForCardRes()) { cardrestriction = ontologyClass.findCardinalityRestrictionInSubClassHierarchy(this); } if (cardrestriction != null) { restrictions.add(cardrestriction); } } private String addPrefix(String name) { String prefix = ctx.getNamespacePrefix(((URI) ontProperty.resource()).getNamespace()); return prefix + "_" + name; } /** * Determine if this property has multiple ranges defined in the base declaration of the property. Note, this is different from multiple ranges via-all * values from. */ private void checkForMultipleBaseRanges() { Resource range = getRange(); if (range != null && range instanceof BlankNode) { org.openanzo.rdf.owl.Class clazz = OWL11Factory.getClass(range, ontGraph); Thing union = clazz.getUnionOf(); if (union != null) { for (Value value : StatementUtils.getCollectionMembers(union.resource(), ontGraph)) { if (value instanceof Resource) { ranges.add((Resource) value); } } } } } private Resource getRange() { Thing range = getRange(ontProperty); if (range != null) { return range.resource(); } return null; } /** * Get the range bean for the given property * * @param ontProperty * property to get bean * @return the range bean for given property */ public static Thing getRange(_Property ontProperty) { return ontProperty.getRange(); } /** * Get the domain bean for the given property * * @param ontProperty * property to get bean * @return the domain bean for given property */ public static org.openanzo.rdf.rdfs.Class getDomain(_Property ontProperty) { return ontProperty.getDomain(); } /** * Set the range bean for the given property * * @param ontProperty * property to get bean * @param range * the range resource to set */ public static void setRange(_Property ontProperty, Resource range) { ontProperty.setRange(range); } /** * Set the domain bean for the given property * * @param ontProperty * property to get bean * @param domain * the domain resource to set */ public static void setDomain(_Property ontProperty, Resource domain) { ontProperty.setDomain(domain); } }