/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Package /////////////// package org.apache.jena.ontology.impl; // Imports /////////////// import java.util.*; import java.util.function.Predicate; import org.apache.jena.enhanced.* ; import org.apache.jena.graph.* ; import org.apache.jena.ontology.* ; import org.apache.jena.rdf.model.* ; import org.apache.jena.util.iterator.* ; /** * <p> * Implementation of the abstraction representing a general ontology property. * </p> */ public class OntPropertyImpl extends OntResourceImpl implements OntProperty { // Constants ////////////////////////////////// // Static variables ////////////////////////////////// /** * A factory for generating OntProperty facets from nodes in enhanced graphs. * Note: should not be invoked directly by user code: use * {@link org.apache.jena.rdf.model.RDFNode#as as()} instead. */ @SuppressWarnings("hiding") public static Implementation factory = new Implementation() { @Override public EnhNode wrap( Node n, EnhGraph eg ) { if (canWrap( n, eg )) { return new OntPropertyImpl( n, eg ); } else { throw new ConversionException( "Cannot convert node " + n + " to OntProperty"); } } @Override public boolean canWrap( Node node, EnhGraph eg ) { // node will support being an OntProperty facet if it has rdf:type owl:Property or equivalent Profile profile = (eg instanceof OntModel) ? ((OntModel) eg).getProfile() : null; return (profile != null) && profile.isSupported( node, eg, OntProperty.class ); } }; // Instance variables ////////////////////////////////// // Constructors ////////////////////////////////// /** * <p> * Construct an ontology property represented by the given node in the given graph. * </p> * * @param n The node that represents the resource * @param g The enh graph that contains n */ public OntPropertyImpl( Node n, EnhGraph g ) { super( n, g ); } // External signature methods ////////////////////////////////// /** * <p> * Answer true to indicate that this resource is an RDF property. * </p> * * @return True. */ @Override public boolean isProperty() { return true; } /** * @see Property#getOrdinal() */ @Override public int getOrdinal() { return (as( Property.class )).getOrdinal(); } // subPropertyOf /** * <p>Assert that this property is sub-property of the given property. Any existing * statements for <code>subPropertyOf</code> will be removed.</p> * @param prop The property that this property is a sub-property of * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public void setSuperProperty( Property prop ) { setPropertyValue( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF", prop ); } /** * <p>Add a super-property of this property.</p> * @param prop A property that is a super-property of this property. * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public void addSuperProperty( Property prop ) { addPropertyValue( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF", prop ); } /** * <p>Answer a property that is the super-property of this property. If there is * more than one such property, an arbitrary selection is made.</p> * @return A super-property of this property * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public OntProperty getSuperProperty() { return objectAsProperty( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF" ); } /** * <p>Answer an iterator over all of the properties that are declared to be super-properties of * this property. Each element of the iterator will be an {@link OntProperty}.</p> * @return An iterator over the super-properties of this property. * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntProperty> listSuperProperties() { return listSuperProperties( false ); } /** * <p>Answer an iterator over all of the properties that are declared to be super-properties of * this property. Each element of the iterator will be an {@link OntProperty}.</p> * @param direct If true, only answer the directly adjacent properties in the * property hierarchy: i.e. eliminate any property for which there is a longer route * to reach that child under the super-property relation. * @return An iterator over the super-properties of this property. * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntProperty> listSuperProperties( boolean direct ) { return listDirectPropertyValues( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF", OntProperty.class, getProfile().SUB_PROPERTY_OF(), direct, false ) .filterDrop( this::equals ); } /** * <p>Answer true if the given property is a super-property of this property.</p> * @param prop A property to test. * @param direct If true, only consider the directly adjacent properties in the * property hierarchy * @return True if the given property is a super-property of this property. */ @Override public boolean hasSuperProperty( Property prop, boolean direct ) { return hasPropertyValue( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF", prop ); } /** * <p>Remove the given property from the super-properties of this property. If this statement * is not true of the current model, nothing happens.</p> * @param prop A property to be removed from the super-properties of this property * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public void removeSuperProperty( Property prop ) { removePropertyValue( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF", prop ); } /** * <p>Assert that this property is super-property of the given property. Any existing * statements for <code>subPropertyOf</code> on <code>prop</code> will be removed.</p> * @param prop The property that is a sub-property of this property * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public void setSubProperty( Property prop ) { // first we have to remove all of the inverse sub-prop links checkProfile( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF" ); for (StmtIterator i = getModel().listStatements( null, getProfile().SUB_PROPERTY_OF(), this ); i.hasNext(); ) { i.removeNext(); } prop.as( OntProperty.class ).addSuperProperty( this ); } /** * <p>Add a sub-property of this property.</p> * @param prop A property that is a sub-property of this property. * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public void addSubProperty( Property prop ) { prop.as( OntProperty.class ).addSuperProperty( this ); } /** * <p>Answer a property that is the sub-property of this property. If there is * more than one such property, an arbitrary selection is made.</p> * @return A sub-property of this property * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public OntProperty getSubProperty() { checkProfile( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF" ); return getModel().listStatements( null, getProfile().SUB_PROPERTY_OF(), this ) .nextStatement() .getSubject() .as( OntProperty.class ); } /** * <p>Answer an iterator over all of the properties that are declared to be sub-properties of * this property. Each element of the iterator will be an {@link OntProperty}.</p> * @return An iterator over the sub-properties of this property. * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntProperty> listSubProperties() { return listSubProperties( false ); } /** * <p>Answer an iterator over all of the properties that are declared to be sub-properties of * this property. Each element of the iterator will be an {@link OntProperty}.</p> * @param direct If true, only answer the direcly adjacent properties in the * property hierarchy: i.e. eliminate any property for which there is a longer route * to reach that child under the sub-property relation. * @return An iterator over the sub-properties of this property. * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntProperty> listSubProperties( boolean direct ) { return listDirectPropertyValues( getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF", OntProperty.class, getProfile().SUB_PROPERTY_OF(), direct, true ); } /** * <p>Answer true if the given property is a sub-property of this property.</p> * @param prop A property to test. * @param direct If true, only consider the direcly adjacent properties in the * property hierarchy * @return True if the given property is a sub-property of this property. */ @Override public boolean hasSubProperty( Property prop, boolean direct ) { return prop.as( OntProperty.class ).hasSuperProperty( this, direct ); } /** * <p>Remove the given property from the sub-properties of this property. If this statement * is not true of the current model, nothing happens.</p> * @param prop A property to be removed from the sub-properties of this property * @exception ProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile. */ @Override public void removeSubProperty( Property prop ) { prop.as( OntProperty.class ).removeSuperProperty( this ); } // domain /** * <p>Assert that the given resource represents the class of individuals that form the * domain of this property. Any existing <code>domain</code> statements for this property are removed.</p> * @param res The resource that represents the domain class for this property. * @exception ProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile. */ @Override public void setDomain( Resource res ) { setPropertyValue( getProfile().DOMAIN(), "DOMAIN", res ); } /** * <p>Add a resource representing the domain of this property.</p> * @param res A resource that represents a domain class for this property. * @exception ProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile. */ @Override public void addDomain( Resource res ) { addPropertyValue( getProfile().DOMAIN(), "DOMAIN", res ); } /** * <p>Answer a resource that represents the domain class of this property. If there is * more than one such resource, an arbitrary selection is made.</p> * @return An resource representing the class that forms the domain of this property * @exception ProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile. */ @Override public OntResource getDomain() { return objectAsResource( getProfile().DOMAIN(), "DOMAIN" ); } /** * <p>Answer an iterator over all of the declared domain classes of this property. * Each element of the iterator will be an {@link OntResource}.</p> * @return An iterator over the classes that form the domain of this property. * @exception ProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntClass> listDomain() { return listAs( getProfile().DOMAIN(), "DOMAIN", OntClass.class ); } /** * <p>Answer true if the given resource a class specifying the domain of this property.</p> * @param res A resource representing a class * @return True if the given resource is one of the domain classes of this property. */ @Override public boolean hasDomain( Resource res ) { return hasPropertyValue( getProfile().DOMAIN(), "DOMAIN", res ); } /** * <p>Remove the given class from the stated domain(s) of this property. If this statement * is not true of the current model, nothing happens.</p> * @param cls A class to be removed from the declared domain(s) of this property * @exception ProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile. */ @Override public void removeDomain( Resource cls ) { removePropertyValue( getProfile().DOMAIN(), "DOMAIN", cls ); } // range /** * <p>Assert that the given resource represents the class of individuals that form the * range of this property. Any existing <code>range</code> statements for this property are removed.</p> * @param res The resource that represents the range class for this property. * @exception ProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile. */ @Override public void setRange( Resource res ) { setPropertyValue( getProfile().RANGE(), "RANGE", res ); } /** * <p>Add a resource representing the range of this property.</p> * @param res A resource that represents a range class for this property. * @exception ProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile. */ @Override public void addRange( Resource res ) { addPropertyValue( getProfile().RANGE(), "RANGE", res ); } /** * <p>Answer a resource that represents the range class of this property. If there is * more than one such resource, an arbitrary selection is made.</p> * @return An resource representing the class that forms the range of this property * @exception ProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile. */ @Override public OntResource getRange() { return objectAsResource( getProfile().RANGE(), "RANGE" ); } /** * <p>Answer an iterator over all of the declared range classes of this property. * Each element of the iterator will be an {@link OntResource}.</p> * @return An iterator over the classes that form the range of this property. * @exception ProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntClass> listRange() { return listAs( getProfile().RANGE(), "RANGE", OntClass.class ); } /** * <p>Answer true if the given resource a class specifying the range of this property.</p> * @param res A resource representing a class * @return True if the given resource is one of the range classes of this property. */ @Override public boolean hasRange( Resource res ) { return hasPropertyValue( getProfile().RANGE(), "RANGE", res ); } /** * <p>Remove the given class from the stated range(s) of this property. If this statement * is not true of the current model, nothing happens.</p> * @param cls A class to be removed from the declared range(s) of this property * @exception ProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile. */ @Override public void removeRange( Resource cls ) { removePropertyValue( getProfile().RANGE(), "RANGE", cls ); } // relationships between properties // equivalentProperty /** * <p>Assert that the given property is equivalent to this property. Any existing * statements for <code>equivalentProperty</code> will be removed.</p> * @param prop The property that this property is a equivalent to. * @exception ProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile. */ @Override public void setEquivalentProperty( Property prop ) { setPropertyValue( getProfile().EQUIVALENT_PROPERTY(), "EQUIVALENT_PROPERTY", prop ); } /** * <p>Add a property that is equivalent to this property.</p> * @param prop A property that is equivalent to this property. * @exception ProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile. */ @Override public void addEquivalentProperty( Property prop ) { addPropertyValue( getProfile().EQUIVALENT_PROPERTY(), "EQUIVALENT_PROPERTY", prop ); } /** * <p>Answer a property that is equivalent to this property. If there is * more than one such property, an arbitrary selection is made.</p> * @return A property equivalent to this property * @exception ProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile. */ @Override public OntProperty getEquivalentProperty() { return objectAsProperty( getProfile().EQUIVALENT_PROPERTY(), "EQUIVALENT_PROPERTY" ); } /** * <p>Answer an iterator over all of the properties that are declared to be equivalent properties to * this property. Each element of the iterator will be an {@link OntProperty}.</p> * @return An iterator over the properties equivalent to this property. * @exception ProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile. */ @Override public ExtendedIterator<OntProperty> listEquivalentProperties() { return listAs( getProfile().EQUIVALENT_PROPERTY(), "EQUIVALENT_PROPERTY", OntProperty.class ); } /** * <p>Answer true if the given property is equivalent to this property.</p> * @param prop A property to test for * @return True if the given property is equivalent to this property. */ @Override public boolean hasEquivalentProperty( Property prop ) { return hasPropertyValue( getProfile().EQUIVALENT_PROPERTY(), "EQUIVALENT_PROPERTY", prop ); } /** * <p>Remove the statement that this property and the given property are * equivalent. If this statement * is not true of the current model, nothing happens.</p> * @param prop A property that may be declared to be equivalent to this property * @exception ProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile. */ @Override public void removeEquivalentProperty( Property prop ) { removePropertyValue( getProfile().EQUIVALENT_PROPERTY(), "EQUIVALENT_PROPERTY", prop ); } // inverseProperty /** * <p>Assert that the given property is the inverse of this property. Any existing * statements for <code>inverseOf</code> will be removed.</p> * @param prop The property that this property is a inverse to. * @exception ProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile. */ @Override public void setInverseOf( Property prop ) { setPropertyValue( getProfile().INVERSE_OF(), "INVERSE_OF", prop ); } /** * <p>Add a property that is the inverse of this property.</p> * @param prop A property that is the inverse of this property. * @exception ProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile. */ @Override public void addInverseOf( Property prop ) { addPropertyValue( getProfile().INVERSE_OF(), "INVERSE_OF", prop ); } /** * <p>Answer a property that is an inverse of this property. If there is * more than one such property, an arbitrary selection is made.</p> * @return A property inverse to this property * @exception ProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile. */ @Override public OntProperty getInverseOf() { return objectAsProperty( getProfile().INVERSE_OF(), "INVERSE_OF" ); } /** * <p>Answer an iterator over all of the properties that are declared to be inverse properties of * this property. Each element of the iterator will be an {@link OntProperty}.</p> * @return An iterator over the properties inverse to this property. * @exception ProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile. */ @Override public ExtendedIterator<? extends OntProperty> listInverseOf() { return listAs( getProfile().INVERSE_OF(), "INVERSE_OF", OntProperty.class ); } /** * <p>Answer true if this property is the inverse of the given property.</p> * @param prop A property to test for * @return True if the this property is the inverse of the the given property. */ @Override public boolean isInverseOf( Property prop ) { return hasPropertyValue( getProfile().INVERSE_OF(), "INVERSE_OF", prop ); } /** * <p>Remove the statement that this property is the inverse of the given property. If this statement * is not true of the current model, nothing happens.</p> * @param prop A property that may be declared to be inverse to this property * @exception ProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile. */ @Override public void removeInverseProperty( Property prop ) { removePropertyValue( getProfile().INVERSE_OF(), "INVERSE_OF", prop ); } /** * <p>Answer a view of this property as a functional property</p> * @return This property, but viewed as a FunctionalProperty node * @exception ConversionException if the resource cannot be converted to a functional property * given the language profile and the current state of the underlying model. */ @Override public FunctionalProperty asFunctionalProperty() { return as( FunctionalProperty.class ); } /** * <p>Answer a view of this property as a datatype property</p> * @return This property, but viewed as a DatatypeProperty node * @exception ConversionException if the resource cannot be converted to a datatype property * given the language profile and the current state of the underlying model. */ @Override public DatatypeProperty asDatatypeProperty() { return as( DatatypeProperty.class ); } /** * <p>Answer a view of this property as an object property</p> * @return This property, but viewed as an ObjectProperty node * @exception ConversionException if the resource cannot be converted to an object property * given the language profile and the current state of the underlying model. */ @Override public ObjectProperty asObjectProperty() { return as( ObjectProperty.class ); } /** * <p>Answer a view of this property as a transitive property</p> * @return This property, but viewed as a TransitiveProperty node * @exception ConversionException if the resource cannot be converted to a transitive property * given the language profile and the current state of the underlying model. */ @Override public TransitiveProperty asTransitiveProperty() { return as( TransitiveProperty.class ); } /** * <p>Answer a view of this property as an inverse functional property</p> * @return This property, but viewed as an InverseFunctionalProperty node * @exception ConversionException if the resource cannot be converted to an inverse functional property * given the language profile and the current state of the underlying model. */ @Override public InverseFunctionalProperty asInverseFunctionalProperty() { return as( InverseFunctionalProperty.class ); } /** * <p>Answer a view of this property as a symmetric property</p> * @return This property, but viewed as a SymmetricProperty node * @exception ConversionException if the resource cannot be converted to a symmetric property * given the language profile and the current state of the underlying model. */ @Override public SymmetricProperty asSymmetricProperty() { return as( SymmetricProperty.class ); } // conversion functions /** * <p>Answer a facet of this property as a functional property, adding additional information to the model if necessary.</p> * @return This property, but converted to a FunctionalProperty facet */ @Override public FunctionalProperty convertToFunctionalProperty() { return convertToType( getProfile().FUNCTIONAL_PROPERTY(), "FUNCTIONAL_PROPERTY", FunctionalProperty.class ); } /** * <p>Answer a facet of this property as a datatype property, adding additional information to the model if necessary.</p> * @return This property, but converted to a DatatypeProperty facet */ @Override public DatatypeProperty convertToDatatypeProperty() { return convertToType( getProfile().DATATYPE_PROPERTY(), "DATATYPE_PROPERTY", DatatypeProperty.class ); } /** * <p>Answer a facet of this property as an object property, adding additional information to the model if necessary.</p> * @return This property, but converted to an ObjectProperty facet */ @Override public ObjectProperty convertToObjectProperty() { return convertToType( getProfile().OBJECT_PROPERTY(), "OBJECT_PROPERTY", ObjectProperty.class ); } /** * <p>Answer a facet of this property as a transitive property, adding additional information to the model if necessary.</p> * @return This property, but converted to a TransitiveProperty facet */ @Override public TransitiveProperty convertToTransitiveProperty() { return convertToType( getProfile().TRANSITIVE_PROPERTY(), "TRANSITIVE_PROPERTY", TransitiveProperty.class ); } /** * <p>Answer a facet of this property as an inverse functional property, adding additional information to the model if necessary.</p> * @return This property, but converted to an InverseFunctionalProperty facet */ @Override public InverseFunctionalProperty convertToInverseFunctionalProperty() { return convertToType( getProfile().INVERSE_FUNCTIONAL_PROPERTY(), "INVERSE_FUNCTIONAL_PROPERTY", InverseFunctionalProperty.class ); } /** * <p>Answer a facet of this property as a symmetric property, adding additional information to the model if necessary.</p> * @return This property, but converted to a SymmetricProperty facet */ @Override public SymmetricProperty convertToSymmetricProperty() { return convertToType( getProfile().SYMMETRIC_PROPERTY(), "SYMMETRIC_PROPERTY", SymmetricProperty.class ); } // tests on property sub-types /** * <p>Answer true if this property is a functional property</p> * @return True if this this property has an <code>rdf:type</code> that defines it as a functional property. */ @Override public boolean isFunctionalProperty() { return hasRDFType( getProfile().FUNCTIONAL_PROPERTY(), "FUNCTIONAL_PROPERTY", false ); } /** * <p>Answer true if this property is a datatype property</p> * @return True if this this property has an <code>rdf:type</code> that defines it as a datatype property. */ @Override public boolean isDatatypeProperty() { return hasRDFType( getProfile().DATATYPE_PROPERTY(), "DATATYPE_PROPERTY", false ); } /** * <p>Answer true if this property is an object property</p> * @return True if this this property has an <code>rdf:type</code> that defines it as an object property. */ @Override public boolean isObjectProperty() { return hasRDFType( getProfile().OBJECT_PROPERTY(), "OBJECT_PROPERTY", false ); } /** * <p>Answer true if this property is a transitive property</p> * @return True if this this property has an <code>rdf:type</code> that defines it as a transitive property. */ @Override public boolean isTransitiveProperty() { return hasRDFType( getProfile().TRANSITIVE_PROPERTY(), "TRANSITIVE_PROPERTY", false ); } /** * <p>Answer true if this property is an inverse functional property</p> * @return True if this this property has an <code>rdf:type</code> that defines it as an inverse functional property. */ @Override public boolean isInverseFunctionalProperty() { return hasRDFType( getProfile().INVERSE_FUNCTIONAL_PROPERTY(), "INVERSE_FUNCTIONAL_PROPERTY", false ); } /** * <p>Answer true if this property is a symmetric property</p> * @return True if this this property has an <code>rdf:type</code> that defines it as a symmetric property. */ @Override public boolean isSymmetricProperty() { return hasRDFType( getProfile().SYMMETRIC_PROPERTY(), "SYMMETRIC_PROPERTY", false ); } /** * <p>Answer the property that is the inverse of this property. If no such property is defined, * return null. If more than one inverse is defined, return an abritrary selection.</p> * @return The property that is the inverse of this property, or null. */ @Override public OntProperty getInverse() { ExtendedIterator<OntProperty> i = listInverse(); OntProperty p = i.hasNext() ? i.next() : null; i.close(); return p; } /** * <p>Answer an iterator over the properties that are defined to be inverses of this property.</p> * @return An iterator over the properties that declare themselves the <code>inverseOf</code> this property. */ @Override public ExtendedIterator<OntProperty> listInverse() { return getModel().listStatements( null, getProfile().INVERSE_OF(), this ).mapWith( s -> s.getSubject().as( OntProperty.class ) ); } /** * <p>Answer true if there is at least one inverse property for this property.</p> * @return True if property has an inverse. */ @Override public boolean hasInverse() { ExtendedIterator<OntProperty> i = listInverse(); boolean hasInv = i.hasNext(); i.close(); return hasInv; } /** * <p>Answer an iterator of all of the classes in this ontology, such * that each returned class has this property as one of its * properties in {@link OntClass#listDeclaredProperties()}. This * simulates a frame-like view of properties and classes; for more * details see the <a href="../../../../../../how-to/rdf-frames.html"> * RDF frames howto</a>.</p> * @return An iterator of the classes having this property as one * of their declared properties */ @Override public ExtendedIterator<OntClass> listDeclaringClasses() { return listDeclaringClasses( false ); } /** * <p>Answer an iterator of all of the classes in this ontology, such * that each returned class has this property as one of its * properties in {@link OntClass#listDeclaredProperties(boolean)}. This * simulates a frame-like view of properties and classes; for more * details see the <a href="../../../../../../how-to/rdf-frames.html"> * RDF frames howto</a>.</p> * @param direct If true, use only </em>direct</em> associations between classes * and properties * @return An iterator of the classes having this property as one * of their declared properties */ @Override public ExtendedIterator<OntClass> listDeclaringClasses( boolean direct ) { // first list the candidate classes, which will also help us // work out whether this is a "global" property or not Set<OntClass> cands = new HashSet<>(); for (Iterator<OntClass> i = listDomain(); i.hasNext(); ) { // the candidates include this class and it sub-classes List<OntClass> q = new ArrayList<>(); q.add( i.next() ); while (!q.isEmpty()) { OntClass c = q.remove( 0 ); if (!c.isOntLanguageTerm() && !cands.contains( c )) { // a new value that is not just a term from OWL or RDFS cands.add( c ); for (Iterator<OntClass> j = c.listSubClasses(); j.hasNext(); ) { q.add( j.next() ); } } } } if (cands.isEmpty()) { // no declared non-global domain, so this is a global prop if (!direct) { // in the non-direct case, global properties appear in the ldp // of all classes, but we ignore the built-in classes return ((OntModel) getModel()).listClasses() .filterDrop( OntClass::isOntLanguageTerm ); } else { // in the direct case, global properties only attach to the // local hierarchy roots return ((OntModel) getModel()).listHierarchyRootClasses(); } } else { // not a global property // pick out classes from the domain for which this is a declared prop return WrappedIterator.create( cands.iterator() ) .filterKeep( new FilterDeclaringClass( this, direct )); } } /** * <p>Answer an iterator over any restrictions that mention this property as * the property that the restriction is adding some constraint to. For example:</p> * <code><pre><owl:Restriction> * <owl:onProperty rdf:resource="#childOf" /> * <owl:hasValue rdf:resource="#ian" /> * </owl:Restriction></pre></code> * <p><strong>Note</strong> that any such restrictions do not affect the global * semantics of this property itself. Restrictions define new class expressions, * and the property constraints are local to that class expression. This method * is provided as a convenience to assist callers to navigate the relationships * in the model.</p> * @return An iterator whose values are the restrictions from the local * model that reference this property. */ @Override public ExtendedIterator<Restriction> listReferringRestrictions() { return getModel().listStatements( null, getProfile().ON_PROPERTY(), this ) .mapWith( s -> s.getSubject().as( Restriction.class ) ); } // Internal implementation methods ////////////////////////////////// /** * <p>Answer a property that is attached to the given model, which will either * be this property or a new property object with the same URI in the given * model. If the given model is an ontology model, make the new property object * an ontproperty.</p> * @param m A model * @return A property equal to this property that is attached to m. */ @Override public Property inModel( Model m ) { return (getModel() == m) ? this : m.createProperty( getURI() ); } //============================================================================== // Inner class definitions //============================================================================== /** * <p>Filter that accepts classes which have the given property as one of * their declared properties.</p> */ private class FilterDeclaringClass implements Predicate<OntClass> { private boolean m_direct; private Property m_prop; private FilterDeclaringClass( Property prop, boolean direct ) { m_prop = prop; m_direct = direct; } @Override public boolean test( OntClass o ) { return o.hasDeclaredProperty( m_prop, m_direct ); } } }