001: /*****************************************************************************
002: * Source code information
003: * -----------------------
004: * Original author Ian Dickinson, HP Labs Bristol
005: * Author email Ian.Dickinson@hp.com
006: * Package Jena 2
007: * Web http://sourceforge.net/projects/jena/
008: * Created 31-Mar-2003
009: * Filename $RCSfile: OntPropertyImpl.java,v $
010: * Revision $Revision: 1.26 $
011: * Release status $State: Exp $
012: *
013: * Last modified on $Date: 2008/01/02 12:08:02 $
014: * by $Author: andy_seaborne $
015: *
016: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
017: * (see footer for full conditions)
018: *****************************************************************************/package com.hp.hpl.jena.ontology.impl;
019:
020: // Imports
021: ///////////////
022: import java.util.*;
023:
024: import com.hp.hpl.jena.enhanced.*;
025: import com.hp.hpl.jena.graph.*;
026: import com.hp.hpl.jena.ontology.*;
027: import com.hp.hpl.jena.rdf.model.*;
028: import com.hp.hpl.jena.util.iterator.*;
029: import com.hp.hpl.jena.util.iterator.ExtendedIterator;
030: import com.hp.hpl.jena.util.iterator.Filter;
031:
032: /**
033: * <p>
034: * Implementation of the abstraction representing a general ontology property.
035: * </p>
036: *
037: * @author Ian Dickinson, HP Labs
038: * (<a href="mailto:Ian.Dickinson@hp.com" >email</a>)
039: * @version CVS $Id: OntPropertyImpl.java,v 1.26 2008/01/02 12:08:02 andy_seaborne Exp $
040: */
041: public class OntPropertyImpl extends OntResourceImpl implements
042: OntProperty {
043: // Constants
044: //////////////////////////////////
045:
046: // Static variables
047: //////////////////////////////////
048:
049: /**
050: * A factory for generating OntProperty facets from nodes in enhanced graphs.
051: * Note: should not be invoked directly by user code: use
052: * {@link com.hp.hpl.jena.rdf.model.RDFNode#as as()} instead.
053: */
054: public static Implementation factory = new Implementation() {
055: public EnhNode wrap(Node n, EnhGraph eg) {
056: if (canWrap(n, eg)) {
057: return new OntPropertyImpl(n, eg);
058: } else {
059: throw new ConversionException("Cannot convert node "
060: + n + " to OntProperty");
061: }
062: }
063:
064: public boolean canWrap(Node node, EnhGraph eg) {
065: // node will support being an OntProperty facet if it has rdf:type owl:Property or equivalent
066: Profile profile = (eg instanceof OntModel) ? ((OntModel) eg)
067: .getProfile()
068: : null;
069: return (profile != null)
070: && profile.isSupported(node, eg, OntProperty.class);
071: }
072: };
073:
074: // Instance variables
075: //////////////////////////////////
076:
077: // Constructors
078: //////////////////////////////////
079:
080: /**
081: * <p>
082: * Construct an ontology property represented by the given node in the given graph.
083: * </p>
084: *
085: * @param n The node that represents the resource
086: * @param g The enh graph that contains n
087: */
088: public OntPropertyImpl(Node n, EnhGraph g) {
089: super (n, g);
090: }
091:
092: // External signature methods
093: //////////////////////////////////
094:
095: /**
096: * <p>
097: * Answer true to indicate that this resource is an RDF property.
098: * </p>
099: *
100: * @return True.
101: */
102: public boolean isProperty() {
103: return true;
104: }
105:
106: /**
107: * @see Property#getOrdinal()
108: */
109: public int getOrdinal() {
110: return ((Property) as(Property.class)).getOrdinal();
111: }
112:
113: // subPropertyOf
114:
115: /**
116: * <p>Assert that this property is sub-property of the given property. Any existing
117: * statements for <code>subPropertyOf</code> will be removed.</p>
118: * @param prop The property that this property is a sub-property of
119: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
120: */
121: public void setSuperProperty(Property prop) {
122: setPropertyValue(getProfile().SUB_PROPERTY_OF(),
123: "SUB_PROPERTY_OF", prop);
124: }
125:
126: /**
127: * <p>Add a super-property of this property.</p>
128: * @param prop A property that is a super-property of this property.
129: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
130: */
131: public void addSuperProperty(Property prop) {
132: addPropertyValue(getProfile().SUB_PROPERTY_OF(),
133: "SUB_PROPERTY_OF", prop);
134: }
135:
136: /**
137: * <p>Answer a property that is the super-property of this property. If there is
138: * more than one such property, an arbitrary selection is made.</p>
139: * @return A super-property of this property
140: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
141: */
142: public OntProperty getSuperProperty() {
143: return objectAsProperty(getProfile().SUB_PROPERTY_OF(),
144: "SUB_PROPERTY_OF");
145: }
146:
147: /**
148: * <p>Answer an iterator over all of the properties that are declared to be super-properties of
149: * this property. Each element of the iterator will be an {@link OntProperty}.</p>
150: * @return An iterator over the super-properties of this property.
151: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
152: */
153: public ExtendedIterator listSuperProperties() {
154: return listSuperProperties(false);
155: }
156:
157: /**
158: * <p>Answer an iterator over all of the properties that are declared to be super-properties of
159: * this property. Each element of the iterator will be an {@link OntProperty}.</p>
160: * @param direct If true, only answer the direcly adjacent properties in the
161: * property hierarchy: i.e. eliminate any property for which there is a longer route
162: * to reach that child under the super-property relation.
163: * @return An iterator over the super-properties of this property.
164: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
165: */
166: public ExtendedIterator listSuperProperties(boolean direct) {
167: return listDirectPropertyValues(getProfile().SUB_PROPERTY_OF(),
168: "SUB_PROPERTY_OF", OntProperty.class, getProfile()
169: .SUB_PROPERTY_OF(), direct, false);
170: }
171:
172: /**
173: * <p>Answer true if the given property is a super-property of this property.</p>
174: * @param prop A property to test.
175: * @param direct If true, only consider the direcly adjacent properties in the
176: * property hierarchy
177: * @return True if the given property is a super-property of this property.
178: */
179: public boolean hasSuperProperty(Property prop, boolean direct) {
180: return hasPropertyValue(getProfile().SUB_PROPERTY_OF(),
181: "SUB_PROPERTY_OF", prop);
182: }
183:
184: /**
185: * <p>Remove the given property from the super-properties of this property. If this statement
186: * is not true of the current model, nothing happens.</p>
187: * @param prop A property to be removed from the super-properties of this property
188: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
189: */
190: public void removeSuperProperty(Property prop) {
191: removePropertyValue(getProfile().SUB_PROPERTY_OF(),
192: "SUB_PROPERTY_OF", prop);
193: }
194:
195: /**
196: * <p>Assert that this property is super-property of the given property. Any existing
197: * statements for <code>subPropertyOf</code> on <code>prop</code> will be removed.</p>
198: * @param prop The property that is a sub-property of this property
199: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
200: */
201: public void setSubProperty(Property prop) {
202: // first we have to remove all of the inverse sub-prop links
203: checkProfile(getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF");
204: for (StmtIterator i = getModel().listStatements(null,
205: getProfile().SUB_PROPERTY_OF(), this ); i.hasNext();) {
206: i.removeNext();
207: }
208:
209: ((OntProperty) prop.as(OntProperty.class))
210: .addSuperProperty(this );
211: }
212:
213: /**
214: * <p>Add a sub-property of this property.</p>
215: * @param prop A property that is a sub-property of this property.
216: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
217: */
218: public void addSubProperty(Property prop) {
219: ((OntProperty) prop.as(OntProperty.class))
220: .addSuperProperty(this );
221: }
222:
223: /**
224: * <p>Answer a property that is the sub-property of this property. If there is
225: * more than one such property, an arbitrary selection is made.</p>
226: * @return A sub-property of this property
227: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
228: */
229: public OntProperty getSubProperty() {
230: checkProfile(getProfile().SUB_PROPERTY_OF(), "SUB_PROPERTY_OF");
231: return (OntProperty) getModel().listStatements(null,
232: getProfile().SUB_PROPERTY_OF(), this ).nextStatement()
233: .getSubject().as(OntProperty.class);
234: }
235:
236: /**
237: * <p>Answer an iterator over all of the properties that are declared to be sub-properties of
238: * this property. Each element of the iterator will be an {@link OntProperty}.</p>
239: * @return An iterator over the sub-properties of this property.
240: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
241: */
242: public ExtendedIterator listSubProperties() {
243: return listSubProperties(false);
244: }
245:
246: /**
247: * <p>Answer an iterator over all of the properties that are declared to be sub-properties of
248: * this property. Each element of the iterator will be an {@link OntProperty}.</p>
249: * @param direct If true, only answer the direcly adjacent properties in the
250: * property hierarchy: i.e. eliminate any property for which there is a longer route
251: * to reach that child under the sub-property relation.
252: * @return An iterator over the sub-properties of this property.
253: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
254: */
255: public ExtendedIterator listSubProperties(boolean direct) {
256: return listDirectPropertyValues(getProfile().SUB_PROPERTY_OF(),
257: "SUB_PROPERTY_OF", OntProperty.class, getProfile()
258: .SUB_PROPERTY_OF(), direct, true);
259: }
260:
261: /**
262: * <p>Answer true if the given property is a sub-property of this property.</p>
263: * @param prop A property to test.
264: * @param direct If true, only consider the direcly adjacent properties in the
265: * property hierarchy
266: * @return True if the given property is a sub-property of this property.
267: */
268: public boolean hasSubProperty(Property prop, boolean direct) {
269: return ((OntProperty) prop.as(OntProperty.class))
270: .hasSuperProperty(this , direct);
271: }
272:
273: /**
274: * <p>Remove the given property from the sub-properties of this property. If this statement
275: * is not true of the current model, nothing happens.</p>
276: * @param prop A property to be removed from the sub-properties of this property
277: * @exception OntProfileException If the {@link Profile#SUB_PROPERTY_OF()} property is not supported in the current language profile.
278: */
279: public void removeSubProperty(Property prop) {
280: ((OntProperty) prop.as(OntProperty.class))
281: .removeSuperProperty(this );
282: }
283:
284: // domain
285:
286: /**
287: * <p>Assert that the given resource represents the class of individuals that form the
288: * domain of this property. Any existing <code>domain</code> statements for this property are removed.</p>
289: * @param res The resource that represents the domain class for this property.
290: * @exception OntProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile.
291: */
292: public void setDomain(Resource res) {
293: setPropertyValue(getProfile().DOMAIN(), "DOMAIN", res);
294: }
295:
296: /**
297: * <p>Add a resource representing the domain of this property.</p>
298: * @param res A resource that represents a domain class for this property.
299: * @exception OntProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile.
300: */
301: public void addDomain(Resource res) {
302: addPropertyValue(getProfile().DOMAIN(), "DOMAIN", res);
303: }
304:
305: /**
306: * <p>Answer a resource that represents the domain class of this property. If there is
307: * more than one such resource, an arbitrary selection is made.</p>
308: * @return An resource representing the class that forms the domain of this property
309: * @exception OntProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile.
310: */
311: public OntResource getDomain() {
312: return objectAsResource(getProfile().DOMAIN(), "DOMAIN");
313: }
314:
315: /**
316: * <p>Answer an iterator over all of the declared domain classes of this property.
317: * Each element of the iterator will be an {@link OntResource}.</p>
318: * @return An iterator over the classes that form the domain of this property.
319: * @exception OntProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile.
320: */
321: public ExtendedIterator listDomain() {
322: return listAs(getProfile().DOMAIN(), "DOMAIN", OntClass.class);
323: }
324:
325: /**
326: * <p>Answer true if the given resource a class specifying the domain of this property.</p>
327: * @param res A resource representing a class
328: * @return True if the given resource is one of the domain classes of this property.
329: */
330: public boolean hasDomain(Resource res) {
331: return hasPropertyValue(getProfile().DOMAIN(), "DOMAIN", res);
332: }
333:
334: /**
335: * <p>Remove the given class from the stated domain(s) of this property. If this statement
336: * is not true of the current model, nothing happens.</p>
337: * @param cls A class to be removed from the declared domain(s) of this property
338: * @exception OntProfileException If the {@link Profile#DOMAIN()} property is not supported in the current language profile.
339: */
340: public void removeDomain(Resource cls) {
341: removePropertyValue(getProfile().DOMAIN(), "DOMAIN", cls);
342: }
343:
344: // range
345:
346: /**
347: * <p>Assert that the given resource represents the class of individuals that form the
348: * range of this property. Any existing <code>range</code> statements for this property are removed.</p>
349: * @param res The resource that represents the range class for this property.
350: * @exception OntProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile.
351: */
352: public void setRange(Resource res) {
353: setPropertyValue(getProfile().RANGE(), "RANGE", res);
354: }
355:
356: /**
357: * <p>Add a resource representing the range of this property.</p>
358: * @param res A resource that represents a range class for this property.
359: * @exception OntProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile.
360: */
361: public void addRange(Resource res) {
362: addPropertyValue(getProfile().RANGE(), "RANGE", res);
363: }
364:
365: /**
366: * <p>Answer a resource that represents the range class of this property. If there is
367: * more than one such resource, an arbitrary selection is made.</p>
368: * @return An resource representing the class that forms the range of this property
369: * @exception OntProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile.
370: */
371: public OntResource getRange() {
372: return objectAsResource(getProfile().RANGE(), "RANGE");
373: }
374:
375: /**
376: * <p>Answer an iterator over all of the declared range classes of this property.
377: * Each element of the iterator will be an {@link OntResource}.</p>
378: * @return An iterator over the classes that form the range of this property.
379: * @exception OntProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile.
380: */
381: public ExtendedIterator listRange() {
382: return listAs(getProfile().RANGE(), "RANGE", OntClass.class);
383: }
384:
385: /**
386: * <p>Answer true if the given resource a class specifying the range of this property.</p>
387: * @param res A resource representing a class
388: * @return True if the given resource is one of the range classes of this property.
389: */
390: public boolean hasRange(Resource res) {
391: return hasPropertyValue(getProfile().RANGE(), "RANGE", res);
392: }
393:
394: /**
395: * <p>Remove the given class from the stated range(s) of this property. If this statement
396: * is not true of the current model, nothing happens.</p>
397: * @param cls A class to be removed from the declared range(s) of this property
398: * @exception OntProfileException If the {@link Profile#RANGE()} property is not supported in the current language profile.
399: */
400: public void removeRange(Resource cls) {
401: removePropertyValue(getProfile().RANGE(), "RANGE", cls);
402: }
403:
404: // relationships between properties
405:
406: // equivalentProperty
407:
408: /**
409: * <p>Assert that the given property is equivalent to this property. Any existing
410: * statements for <code>equivalentProperty</code> will be removed.</p>
411: * @param prop The property that this property is a equivalent to.
412: * @exception OntProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile.
413: */
414: public void setEquivalentProperty(Property prop) {
415: setPropertyValue(getProfile().EQUIVALENT_PROPERTY(),
416: "EQUIVALENT_PROPERTY", prop);
417: }
418:
419: /**
420: * <p>Add a property that is equivalent to this property.</p>
421: * @param prop A property that is equivalent to this property.
422: * @exception OntProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile.
423: */
424: public void addEquivalentProperty(Property prop) {
425: addPropertyValue(getProfile().EQUIVALENT_PROPERTY(),
426: "EQUIVALENT_PROPERTY", prop);
427: }
428:
429: /**
430: * <p>Answer a property that is equivalent to this property. If there is
431: * more than one such property, an arbitrary selection is made.</p>
432: * @return A property equivalent to this property
433: * @exception OntProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile.
434: */
435: public OntProperty getEquivalentProperty() {
436: return objectAsProperty(getProfile().EQUIVALENT_PROPERTY(),
437: "EQUIVALENT_PROPERTY");
438: }
439:
440: /**
441: * <p>Answer an iterator over all of the properties that are declared to be equivalent properties to
442: * this property. Each element of the iterator will be an {@link OntProperty}.</p>
443: * @return An iterator over the properties equivalent to this property.
444: * @exception OntProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile.
445: */
446: public ExtendedIterator listEquivalentProperties() {
447: return listAs(getProfile().EQUIVALENT_PROPERTY(),
448: "EQUIVALENT_PROPERTY", OntProperty.class);
449: }
450:
451: /**
452: * <p>Answer true if the given property is equivalent to this property.</p>
453: * @param prop A property to test for
454: * @return True if the given property is equivalent to this property.
455: */
456: public boolean hasEquivalentProperty(Property prop) {
457: return hasPropertyValue(getProfile().EQUIVALENT_PROPERTY(),
458: "EQUIVALENT_PROPERTY", prop);
459: }
460:
461: /**
462: * <p>Remove the statement that this property and the given property are
463: * equivalent. If this statement
464: * is not true of the current model, nothing happens.</p>
465: * @param prop A property that may be declared to be equivalent to this property
466: * @exception OntProfileException If the {@link Profile#EQUIVALENT_PROPERTY()} property is not supported in the current language profile.
467: */
468: public void removeEquivalentProperty(Property prop) {
469: removePropertyValue(getProfile().EQUIVALENT_PROPERTY(),
470: "EQUIVALENT_PROPERTY", prop);
471: }
472:
473: // inverseProperty
474:
475: /**
476: * <p>Assert that the given property is the inverse of this property. Any existing
477: * statements for <code>inverseOf</code> will be removed.</p>
478: * @param prop The property that this property is a inverse to.
479: * @exception OntProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile.
480: */
481: public void setInverseOf(Property prop) {
482: setPropertyValue(getProfile().INVERSE_OF(), "INVERSE_OF", prop);
483: }
484:
485: /**
486: * <p>Add a property that is the inverse of this property.</p>
487: * @param prop A property that is the inverse of this property.
488: * @exception OntProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile.
489: */
490: public void addInverseOf(Property prop) {
491: addPropertyValue(getProfile().INVERSE_OF(), "INVERSE_OF", prop);
492: }
493:
494: /**
495: * <p>Answer a property that is an inverse of this property. If there is
496: * more than one such property, an arbitrary selection is made.</p>
497: * @return A property inverse to this property
498: * @exception OntProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile.
499: */
500: public OntProperty getInverseOf() {
501: return objectAsProperty(getProfile().INVERSE_OF(), "INVERSE_OF");
502: }
503:
504: /**
505: * <p>Answer an iterator over all of the properties that are declared to be inverse properties of
506: * this property. Each element of the iterator will be an {@link OntProperty}.</p>
507: * @return An iterator over the properties inverse to this property.
508: * @exception OntProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile.
509: */
510: public ExtendedIterator listInverseOf() {
511: return listAs(getProfile().INVERSE_OF(), "INVERSE_OF",
512: OntProperty.class);
513: }
514:
515: /**
516: * <p>Answer true if this property is the inverse of the given property.</p>
517: * @param prop A property to test for
518: * @return True if the this property is the inverse of the the given property.
519: */
520: public boolean isInverseOf(Property prop) {
521: return hasPropertyValue(getProfile().INVERSE_OF(),
522: "INVERSE_OF", prop);
523: }
524:
525: /**
526: * <p>Remove the statement that this property is the inverse of the given property. If this statement
527: * is not true of the current model, nothing happens.</p>
528: * @param prop A property that may be declared to be inverse to this property
529: * @exception OntProfileException If the {@link Profile#INVERSE_OF()} property is not supported in the current language profile.
530: */
531: public void removeInverseProperty(Property prop) {
532: removePropertyValue(getProfile().INVERSE_OF(), "INVERSE_OF",
533: prop);
534: }
535:
536: /**
537: * <p>Answer a view of this property as a functional property</p>
538: * @return This property, but viewed as a FunctionalProperty node
539: * @exception ConversionException if the resource cannot be converted to a functional property
540: * given the language profile and the current state of the underlying model.
541: */
542: public FunctionalProperty asFunctionalProperty() {
543: return (FunctionalProperty) as(FunctionalProperty.class);
544: }
545:
546: /**
547: * <p>Answer a view of this property as a datatype property</p>
548: * @return This property, but viewed as a DatatypeProperty node
549: * @exception ConversionException if the resource cannot be converted to a datatype property
550: * given the language profile and the current state of the underlying model.
551: */
552: public DatatypeProperty asDatatypeProperty() {
553: return (DatatypeProperty) as(DatatypeProperty.class);
554: }
555:
556: /**
557: * <p>Answer a view of this property as an object property</p>
558: * @return This property, but viewed as an ObjectProperty node
559: * @exception ConversionException if the resource cannot be converted to an object property
560: * given the language profile and the current state of the underlying model.
561: */
562: public ObjectProperty asObjectProperty() {
563: return (ObjectProperty) as(ObjectProperty.class);
564: }
565:
566: /**
567: * <p>Answer a view of this property as a transitive property</p>
568: * @return This property, but viewed as a TransitiveProperty node
569: * @exception ConversionException if the resource cannot be converted to a transitive property
570: * given the language profile and the current state of the underlying model.
571: */
572: public TransitiveProperty asTransitiveProperty() {
573: return (TransitiveProperty) as(TransitiveProperty.class);
574: }
575:
576: /**
577: * <p>Answer a view of this property as an inverse functional property</p>
578: * @return This property, but viewed as an InverseFunctionalProperty node
579: * @exception ConversionException if the resource cannot be converted to an inverse functional property
580: * given the language profile and the current state of the underlying model.
581: */
582: public InverseFunctionalProperty asInverseFunctionalProperty() {
583: return (InverseFunctionalProperty) as(InverseFunctionalProperty.class);
584: }
585:
586: /**
587: * <p>Answer a view of this property as a symmetric property</p>
588: * @return This property, but viewed as a SymmetricProperty node
589: * @exception ConversionException if the resource cannot be converted to a symmetric property
590: * given the language profile and the current state of the underlying model.
591: */
592: public SymmetricProperty asSymmetricProperty() {
593: return (SymmetricProperty) as(SymmetricProperty.class);
594: }
595:
596: // conversion functions
597:
598: /**
599: * <p>Answer a facet of this property as a functional property, adding additional information to the model if necessary.</p>
600: * @return This property, but converted to a FunctionalProperty facet
601: */
602: public FunctionalProperty convertToFunctionalProperty() {
603: return (FunctionalProperty) convertToType(getProfile()
604: .FUNCTIONAL_PROPERTY(), "FUNCTIONAL_PROPERTY",
605: FunctionalProperty.class);
606: }
607:
608: /**
609: * <p>Answer a facet of this property as a datatype property, adding additional information to the model if necessary.</p>
610: * @return This property, but converted to a DatatypeProperty facet
611: */
612: public DatatypeProperty convertToDatatypeProperty() {
613: return (DatatypeProperty) convertToType(getProfile()
614: .DATATYPE_PROPERTY(), "DATATYPE_PROPERTY",
615: DatatypeProperty.class);
616: }
617:
618: /**
619: * <p>Answer a facet of this property as an object property, adding additional information to the model if necessary.</p>
620: * @return This property, but converted to an ObjectProperty facet
621: */
622: public ObjectProperty convertToObjectProperty() {
623: return (ObjectProperty) convertToType(getProfile()
624: .OBJECT_PROPERTY(), "OBJECT_PROPERTY",
625: ObjectProperty.class);
626: }
627:
628: /**
629: * <p>Answer a facet of this property as a transitive property, adding additional information to the model if necessary.</p>
630: * @return This property, but converted to a TransitiveProperty facet
631: */
632: public TransitiveProperty convertToTransitiveProperty() {
633: return (TransitiveProperty) convertToType(getProfile()
634: .TRANSITIVE_PROPERTY(), "TRANSITIVE_PROPERTY",
635: TransitiveProperty.class);
636: }
637:
638: /**
639: * <p>Answer a facet of this property as an inverse functional property, adding additional information to the model if necessary.</p>
640: * @return This property, but converted to an InverseFunctionalProperty facet
641: */
642: public InverseFunctionalProperty convertToInverseFunctionalProperty() {
643: return (InverseFunctionalProperty) convertToType(getProfile()
644: .INVERSE_FUNCTIONAL_PROPERTY(),
645: "INVERSE_FUNCTIONAL_PROPERTY",
646: InverseFunctionalProperty.class);
647: }
648:
649: /**
650: * <p>Answer a facet of this property as a symmetric property, adding additional information to the model if necessary.</p>
651: * @return This property, but converted to a SymmetricProperty facet
652: */
653: public SymmetricProperty convertToSymmetricProperty() {
654: return (SymmetricProperty) convertToType(getProfile()
655: .SYMMETRIC_PROPERTY(), "SYMMETRIC_PROPERTY",
656: SymmetricProperty.class);
657: }
658:
659: // tests on property sub-types
660:
661: /**
662: * <p>Answer true if this property is a functional property</p>
663: * @return True if this this property has an <code>rdf:type</code> that defines it as a functional property.
664: */
665: public boolean isFunctionalProperty() {
666: return hasRDFType(getProfile().FUNCTIONAL_PROPERTY(),
667: "FUNCTIONAL_PROPERTY", false);
668: }
669:
670: /**
671: * <p>Answer true if this property is a datatype property</p>
672: * @return True if this this property has an <code>rdf:type</code> that defines it as a datatype property.
673: */
674: public boolean isDatatypeProperty() {
675: return hasRDFType(getProfile().DATATYPE_PROPERTY(),
676: "DATATYPE_PROPERTY", false);
677: }
678:
679: /**
680: * <p>Answer true if this property is an object property</p>
681: * @return True if this this property has an <code>rdf:type</code> that defines it as an object property.
682: */
683: public boolean isObjectProperty() {
684: return hasRDFType(getProfile().OBJECT_PROPERTY(),
685: "OBJECT_PROPERTY", false);
686: }
687:
688: /**
689: * <p>Answer true if this property is a transitive property</p>
690: * @return True if this this property has an <code>rdf:type</code> that defines it as a transitive property.
691: */
692: public boolean isTransitiveProperty() {
693: return hasRDFType(getProfile().TRANSITIVE_PROPERTY(),
694: "TRANSITIVE_PROPERTY", false);
695: }
696:
697: /**
698: * <p>Answer true if this property is an inverse functional property</p>
699: * @return True if this this property has an <code>rdf:type</code> that defines it as an inverse functional property.
700: */
701: public boolean isInverseFunctionalProperty() {
702: return hasRDFType(getProfile().INVERSE_FUNCTIONAL_PROPERTY(),
703: "INVERSE_FUNCTIONAL_PROPERTY", false);
704: }
705:
706: /**
707: * <p>Answer true if this property is a symmetric property</p>
708: * @return True if this this property has an <code>rdf:type</code> that defines it as a symmetric property.
709: */
710: public boolean isSymmetricProperty() {
711: return hasRDFType(getProfile().SYMMETRIC_PROPERTY(),
712: "SYMMETRIC_PROPERTY", false);
713: }
714:
715: /**
716: * <p>Answer the property that is the inverse of this property. If no such property is defined,
717: * return null. If more than one inverse is defined, return an abritrary selection.</p>
718: * @return The property that is the inverse of this property, or null.
719: */
720: public OntProperty getInverse() {
721: ExtendedIterator i = listInverse();
722: OntProperty p = i.hasNext() ? ((OntProperty) i.next()) : null;
723: i.close();
724:
725: return p;
726: }
727:
728: /**
729: * <p>Answer an iterator over the properties that are defined to be inverses of this property.</p>
730: * @return An iterator over the properties that declare themselves the <code>inverseOf</code> this property.
731: */
732: public ExtendedIterator listInverse() {
733: return getModel().listStatements(null,
734: getProfile().INVERSE_OF(), this ).mapWith(
735: new SubjectAsMapper(OntProperty.class));
736: }
737:
738: /**
739: * <p>Answer true if there is at least one inverse property for this property.</p>
740: * @return True if property has an inverse.
741: */
742: public boolean hasInverse() {
743: ExtendedIterator i = listInverse();
744: boolean hasInv = i.hasNext();
745: i.close();
746:
747: return hasInv;
748: }
749:
750: /**
751: * <p>Answer an iterator of all of the classes in this ontology, such
752: * that each returned class has this property as one of its
753: * properties in {@link OntClass#listDeclaredProperties()}. This
754: * simulates a frame-like view of properties and classes; for more
755: * details see the <a href="../../../../../../how-to/rdf-frames.html">
756: * RDF frames howto</a>.</p>
757: * @return An iterator of the classes having this property as one
758: * of their declared properties
759: */
760: public ExtendedIterator listDeclaringClasses() {
761: return listDeclaringClasses(false);
762: }
763:
764: /**
765: * <p>Answer an iterator of all of the classes in this ontology, such
766: * that each returned class has this property as one of its
767: * properties in {@link OntClass#listDeclaredProperties(boolean)}. This
768: * simulates a frame-like view of properties and classes; for more
769: * details see the <a href="../../../../../../how-to/rdf-frames.html">
770: * RDF frames howto</a>.</p>
771: * @param direct If true, use only </em>direct</em> associations between classes
772: * and properties
773: * @return An iterator of the classes having this property as one
774: * of their declared properties
775: */
776: public ExtendedIterator listDeclaringClasses(boolean direct) {
777: // first list the candidate classes, which will also help us
778: // work out whether this is a "global" property or not
779: Set cands = new HashSet();
780: for (Iterator i = listDomain(); i.hasNext();) {
781: // the candidates include this class and it sub-classes
782: List q = new ArrayList();
783: q.add(i.next());
784:
785: while (!q.isEmpty()) {
786: OntClass c = (OntClass) q.remove(0);
787:
788: if (!c.isOntLanguageTerm() && !cands.contains(c)) {
789: // a new value that is not just a term from OWL or RDFS
790: cands.add(c);
791: for (Iterator j = c.listSubClasses(); j.hasNext();) {
792: q.add(j.next());
793: }
794: }
795: }
796: }
797:
798: if (cands.isEmpty()) {
799: // no declared non-global domain, so this is a global prop
800: if (!direct) {
801: // in the non-direct case, global properties appear in the ldp
802: // of all classes, but we ignore the built-in classes
803: return ((OntModel) getModel()).listClasses()
804: .filterDrop(new Filter() {
805: public boolean accept(Object o) {
806: return ((OntClass) o)
807: .isOntLanguageTerm();
808: }
809: });
810: } else {
811: // in the direct case, global properties only attach to the
812: // local hierarchy roots
813: return ((OntModel) getModel())
814: .listHierarchyRootClasses();
815: }
816: } else {
817: // not a global property
818: // pick out classes from the domain for which this is a declared prop
819: return WrappedIterator.create(cands.iterator()).filterKeep(
820: new FilterDeclaringClass(this , direct));
821: }
822: }
823:
824: /**
825: * <p>Answer an iterator over any restrictions that mention this property as
826: * the property that the restriction is adding some constraint to. For example:</p>
827: * <code><pre><owl:Restriction>
828: * <owl:onProperty rdf:resource="#childOf" />
829: * <owl:hasValue rdf:resource="#ian" />
830: * </owl:Restriction></pre></code>
831: * <p><strong>Note</strong> that any such restrictions do not affect the global
832: * semantics of this property itself. Restrictions define new class expressions,
833: * and the property constraints are local to that class expression. This method
834: * is provided as a convenience to assist callers to navigate the relationships
835: * in the model.</p>
836: * @return An iterator whose values are the restrictions from the local
837: * model that reference this property.
838: */
839: public ExtendedIterator listReferringRestrictions() {
840: return getModel().listStatements(null,
841: getProfile().ON_PROPERTY(), this ).mapWith(
842: new SubjectAsMapper(Restriction.class));
843: }
844:
845: // Internal implementation methods
846: //////////////////////////////////
847:
848: /**
849: * <p>Answer a property that is attached to the given model, which will either
850: * be this property or a new property object with the same URI in the given
851: * model. If the given model is an ontology model, make the new property object
852: * an ontproperty.</p>
853: * @param m A model
854: * @return A property equal to this property that is attached to m.
855: */
856: public RDFNode inModel(Model m) {
857: return (getModel() == m) ? this : m.createProperty(getURI());
858: }
859:
860: //==============================================================================
861: // Inner class definitions
862: //==============================================================================
863:
864: /**
865: * <p>Filter that accepts classes which have the given property as one of
866: * their declared properties.</p>
867: */
868: private class FilterDeclaringClass extends Filter {
869: private boolean m_direct;
870: private Property m_prop;
871:
872: private FilterDeclaringClass(Property prop, boolean direct) {
873: m_prop = prop;
874: m_direct = direct;
875: }
876:
877: public boolean accept(Object o) {
878: return ((OntClass) o).hasDeclaredProperty(m_prop, m_direct);
879: }
880:
881: }
882: }
883:
884: /*
885: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
886: All rights reserved.
887:
888: Redistribution and use in source and binary forms, with or without
889: modification, are permitted provided that the following conditions
890: are met:
891:
892: 1. Redistributions of source code must retain the above copyright
893: notice, this list of conditions and the following disclaimer.
894:
895: 2. Redistributions in binary form must reproduce the above copyright
896: notice, this list of conditions and the following disclaimer in the
897: documentation and/or other materials provided with the distribution.
898:
899: 3. The name of the author may not be used to endorse or promote products
900: derived from this software without specific prior written permission.
901:
902: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
903: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
904: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
905: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
906: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
907: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
908: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
909: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
910: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
911: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
912: */
|