0001: /*****************************************************************************
0002: * Source code information
0003: * -----------------------
0004: * Original author Ian Dickinson, HP Labs Bristol
0005: * Author email Ian.Dickinson@hp.com
0006: * Package Jena 2
0007: * Web http://sourceforge.net/projects/jena/
0008: * Created 22 Feb 2003
0009: * Filename $RCSfile: OntModelImpl.java,v $
0010: * Revision $Revision: 1.106 $
0011: * Release status $State: Exp $
0012: *
0013: * Last modified on $Date: 2008/01/28 15:51:48 $
0014: * by $Author: chris-dollin $
0015: *
0016: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
0017: * (see footer for full conditions)
0018: *****************************************************************************/package com.hp.hpl.jena.ontology.impl;
0019:
0020: // Imports
0021: ///////////////
0022: import com.hp.hpl.jena.rdf.listeners.StatementListener;
0023: import com.hp.hpl.jena.rdf.model.*;
0024: import com.hp.hpl.jena.rdf.model.impl.*;
0025: import com.hp.hpl.jena.reasoner.*;
0026: import com.hp.hpl.jena.util.iterator.*;
0027: import com.hp.hpl.jena.vocabulary.*;
0028: import com.hp.hpl.jena.ontology.*;
0029: import com.hp.hpl.jena.ontology.event.*;
0030: import com.hp.hpl.jena.graph.*;
0031: import com.hp.hpl.jena.graph.compose.MultiUnion;
0032: import com.hp.hpl.jena.graph.query.*;
0033: import com.hp.hpl.jena.enhanced.*;
0034: import com.hp.hpl.jena.shared.*;
0035:
0036: import java.io.*;
0037: import java.util.*;
0038:
0039: import org.apache.commons.logging.Log;
0040: import org.apache.commons.logging.LogFactory;
0041:
0042: /**
0043: * <p>
0044: * Implementation of a model that can process general ontologies in OWL,
0045: * DAML and similar languages.
0046: * </p>
0047: *
0048: * @author Ian Dickinson, HP Labs
0049: * (<a href="mailto:Ian.Dickinson@hp.com" >email</a>)
0050: * @version CVS $Id: OntModelImpl.java,v 1.106 2008/01/28 15:51:48 chris-dollin Exp $
0051: */
0052: public class OntModelImpl extends ModelCom implements OntModel {
0053: // Constants
0054: //////////////////////////////////
0055:
0056: /**
0057: * This variable is how the OntModel knows how to construct
0058: * a syntax checker. This part of the design may change.
0059: */
0060: static public String owlSyntaxCheckerClassName = "com.hp.hpl.jena.ontology.tidy.JenaChecker";
0061:
0062: // Static variables
0063: //////////////////////////////////
0064:
0065: static private Log s_log = LogFactory.getLog(OntModelImpl.class);
0066:
0067: /** Found from {@link owlSyntaxCheckerClassName}, must implement
0068: * {@link OWLSyntaxChecker}. */
0069: static private Class owlSyntaxCheckerClass;
0070:
0071: // Instance variables
0072: //////////////////////////////////
0073:
0074: /** The model specification this model is using to define its structure */
0075: protected OntModelSpec m_spec;
0076:
0077: /** List of URI strings of documents that have been imported into this one */
0078: protected Set m_imported = new HashSet();
0079:
0080: /** Mode switch for strict checking mode */
0081: protected boolean m_strictMode = true;
0082:
0083: /** The union graph that contains the imports closure - there is always one of these, which may also be _the_ graph for the model */
0084: protected MultiUnion m_union = new MultiUnion();
0085:
0086: /** The listener that detects dynamically added or removed imports statements */
0087: protected ImportsListener m_importsListener = null;
0088:
0089: /** The event manager for ontology events on this model */
0090: protected OntEventManager m_ontEventMgr = null;
0091:
0092: /** Cached deductions model */
0093: private Model m_deductionsModel = null;
0094:
0095: // Constructors
0096: //////////////////////////////////
0097:
0098: /**
0099: * <p>
0100: * Construct a new ontology model, using the given model as a base. The document manager
0101: * given in the specification object
0102: * will be used to build the imports closure of the model if its policy permits.
0103: * </p>
0104: *
0105: * @param model The base model that may contain existing statements for the ontology.
0106: * if it is null, a fresh model is created as the base.
0107: * @param spec A specification object that allows us to specify parameters and structure for the
0108: * ontology model to be constructed.
0109: */
0110: public OntModelImpl(OntModelSpec spec, Model model) {
0111: this (spec, makeBaseModel(spec, model), true);
0112: }
0113:
0114: /**
0115: * Construct a new ontology model from the given specification. The base model is
0116: * produced using the baseModelMaker.
0117: */
0118: public OntModelImpl(OntModelSpec spec) {
0119: this (spec, spec.createBaseModel(), true);
0120: }
0121:
0122: /**
0123: *
0124: * @param spec the specification for the OntModel
0125: * @param model the base model [must be non-null]
0126: * @param withImports If true, we load the imports as sub-models
0127: */
0128: private OntModelImpl(OntModelSpec spec, Model model,
0129: boolean withImports) {
0130: // we haven't built the full graph yet, so we pass a vestigial form up to the super constructor
0131: super (generateGraph(spec, model.getGraph()),
0132: BuiltinPersonalities.model);
0133: m_spec = spec;
0134:
0135: // extract the union graph from whatever generateGraph() created
0136: m_union = (getGraph() instanceof MultiUnion) ? ((MultiUnion) getGraph())
0137: : (MultiUnion) ((InfGraph) getGraph()).getRawGraph();
0138:
0139: // add the global prefixes, if required
0140: if (getDocumentManager().useDeclaredPrefixes()) {
0141: withDefaultMappings(getDocumentManager()
0142: .getDeclaredPrefixMapping());
0143: }
0144:
0145: if (withImports) {
0146: loadImports();
0147: }
0148:
0149: // force the inference engine, if we have one, to see the new graph data
0150: rebind();
0151: }
0152:
0153: // External signature methods
0154: //////////////////////////////////
0155:
0156: /**
0157: * <p>
0158: * Answer a reference to the document manager that this model is using to manage
0159: * ontology <-> mappings, and to load the imports closure. <strong>Note</strong>
0160: * the default ontology model {@linkplain OntModelSpec specifications} each have
0161: * a contained default document manager. Changing the document managers specified by
0162: * these default specification may (in fact, probably will)
0163: * affect other models built with the same specification
0164: * policy. This may or may not be as desired by the programmer!
0165: * </p>
0166: * @return A reference to this model's document manager, obtained from the specification object
0167: */
0168: public OntDocumentManager getDocumentManager() {
0169: return m_spec.getDocumentManager();
0170: }
0171:
0172: /**
0173: * <p>
0174: * Answer an iterator that ranges over the ontology resources in this model, i.e.
0175: * the resources with <code>rdf:type Ontology</code> or equivalent. These resources
0176: * typically contain metadata about the ontology document that contains them.
0177: * </p>
0178: * <p>
0179: * Specifically, the resources in this iterator will those whose type corresponds
0180: * to the value given in the ontology vocabulary associated with this model, see
0181: * {@link Profile#ONTOLOGY}.
0182: * </p>
0183: * <p>
0184: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0185: * the completeness of the deductive extension of the underlying graph. See class
0186: * overview for more details.
0187: * </p>
0188: *
0189: * @return An iterator over ontology resources.
0190: */
0191: public ExtendedIterator listOntologies() {
0192: checkProfileEntry(getProfile().ONTOLOGY(), "ONTOLOGY");
0193: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0194: .ONTOLOGY(), Ontology.class));
0195: }
0196:
0197: /**
0198: * <p>
0199: * Answer an iterator that ranges over the property resources in this model, i.e.
0200: * the resources with <code>rdf:type Property</code> or equivalent. An <code>OntProperty</code>
0201: * is equivalent to an <code>rdfs:Property</code> in a normal RDF graph; this type is
0202: * provided as a common super-type for the more specific {@link ObjectProperty} and
0203: * {@link DatatypeProperty} property types.
0204: * </p>
0205: * <p><strong>Note</strong> This method searches for nodes in the underlying model whose
0206: * <code>rdf:type</code> is <code>rdf:Property</code>. This type is <em>entailed</em> by
0207: * specific property sub-types, such as <code>owl:ObjectProperty</code>. An important
0208: * consequence of this is that in <em>models without an attached reasoner</em> (e.g. in the
0209: * <code>OWL_MEM</code> {@link OntModelSpec}), the entailed type will not be present
0210: * and this method will omit such properties from the returned iterator. <br />
0211: * <strong>Solution</strong> There are two
0212: * ways to address to this issue: either use a reasoning engine to ensure that type entailments
0213: * are taking place correctly, or call {@link #listAllOntProperties()}. Note
0214: * that <code>listAllOntProperties</code> is potentially less efficient than this method.</p>
0215: * <p>
0216: * The resources returned by this iterator will those whose type corresponds
0217: * to the value given in the ontology vocabulary associated with this model.
0218: * </p>
0219: *
0220: * @return An iterator over property resources.
0221: */
0222: public ExtendedIterator listOntProperties() {
0223: ExtendedIterator i = UniqueExtendedIterator
0224: .create(findByTypeAs(RDF.Property, OntProperty.class));
0225:
0226: // if we are in OWL_FULL, the properties should also include the annotation properties
0227: if (getReasoner() != null
0228: && getProfile().equals(
0229: ProfileRegistry.getInstance().getProfile(
0230: ProfileRegistry.OWL_LANG))) {
0231: // we are using a reasoner, and in OWL Full
0232: // so add the annotation properties too
0233: i = i.andThen(listAnnotationProperties());
0234: }
0235:
0236: return i;
0237: }
0238:
0239: /**
0240: * <p>Answer an iterator over all of the ontology properties in this model, including
0241: * object properties, datatype properties, annotation properties, etc. This method
0242: * takes a different approach to calculating the set of property resources to return,
0243: * and is robust against the absence of a reasoner attached to the model (see note
0244: * in {@link #listOntProperties()} for explanation). However, the calculation used by
0245: * this method is potentially less efficient than the alternative <code>listOntProperties()</code>.
0246: * Users whose models have an attached reasoner are recommended to use
0247: * {@link #listOntProperties()}.</p>
0248: * @return An iterator over all available properties in a model, irrespective of
0249: * whether a reasoner is available to perform <code>rdf:type</code> entailments.
0250: * Each property will appear exactly once in the iterator.
0251: */
0252: public ExtendedIterator listAllOntProperties() {
0253: ExtendedIterator i = findByTypeAs(RDF.Property,
0254: OntProperty.class).andThen(listObjectProperties())
0255: .andThen(listDatatypeProperties()).andThen(
0256: listAnnotationProperties()).andThen(
0257: listFunctionalProperties()).andThen(
0258: listTransitiveProperties()).andThen(
0259: listSymmetricProperties());
0260:
0261: // we must filter for uniqueness
0262: return UniqueExtendedIterator.create(i);
0263: }
0264:
0265: /**
0266: * <p>
0267: * Answer an iterator that ranges over the object property resources in this model, i.e.
0268: * the resources with <code>rdf:type ObjectProperty</code> or equivalent. An object
0269: * property is a property that is defined in the ontology language semantics as a
0270: * one whose range comprises individuals (rather than datatyped literals).
0271: * </p>
0272: * <p>
0273: * Specifically, the resources in this iterator will those whose type corresponds
0274: * to the value given in the ontology vocabulary associated with this model: see
0275: * {@link Profile#OBJECT_PROPERTY}.
0276: * </p>
0277: * <p>
0278: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0279: * the completeness of the deductive extension of the underlying graph. See class
0280: * overview for more details.
0281: * </p>
0282: *
0283: * @return An iterator over object property resources.
0284: */
0285: public ExtendedIterator listObjectProperties() {
0286: checkProfileEntry(getProfile().OBJECT_PROPERTY(),
0287: "OBJECT_PROPERTY");
0288: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0289: .OBJECT_PROPERTY(), ObjectProperty.class));
0290: }
0291:
0292: /**
0293: * <p>
0294: * Answer an iterator that ranges over the datatype property resources in this model, i.e.
0295: * the resources with <code>rdf:type DatatypeProperty</code> or equivalent. An datatype
0296: * property is a property that is defined in the ontology language semantics as a
0297: * one whose range comprises datatyped literals (rather than individuals).
0298: * </p>
0299: * <p>
0300: * Specifically, the resources in this iterator will those whose type corresponds
0301: * to the value given in the ontology vocabulary associated with this model: see
0302: * {@link Profile#DATATYPE_PROPERTY}.
0303: * </p>
0304: * <p>
0305: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0306: * the completeness of the deductive extension of the underlying graph. See class
0307: * overview for more details.
0308: * </p>
0309: *
0310: * @return An iterator over datatype property resources.
0311: */
0312: public ExtendedIterator listDatatypeProperties() {
0313: checkProfileEntry(getProfile().DATATYPE_PROPERTY(),
0314: "DATATYPE_PROPERTY");
0315: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0316: .DATATYPE_PROPERTY(), DatatypeProperty.class));
0317: }
0318:
0319: /**
0320: * <p>
0321: * Answer an iterator that ranges over the functional property resources in this model, i.e.
0322: * the resources with <code>rdf:type FunctionalProperty</code> or equivalent. A functional
0323: * property is a property that is defined in the ontology language semantics as having
0324: * a unique domain element for each instance of the relationship.
0325: * </p>
0326: * <p>
0327: * Specifically, the resources in this iterator will those whose type corresponds
0328: * to the value given in the ontology vocabulary associated with this model: see
0329: * {@link Profile#FUNCTIONAL_PROPERTY}.
0330: * </p>
0331: *
0332: * @return An iterator over functional property resources.
0333: */
0334: public ExtendedIterator listFunctionalProperties() {
0335: checkProfileEntry(getProfile().FUNCTIONAL_PROPERTY(),
0336: "FUNCTIONAL_PROPERTY");
0337: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0338: .FUNCTIONAL_PROPERTY(), FunctionalProperty.class));
0339: }
0340:
0341: /**
0342: * <p>
0343: * Answer an iterator that ranges over the transitive property resources in this model, i.e.
0344: * the resources with <code>rdf:type TransitiveProperty</code> or equivalent.
0345: * </p>
0346: * <p>
0347: * Specifically, the resources in this iterator will those whose type corresponds
0348: * to the value given in the ontology vocabulary associated with this model: see
0349: * {@link Profile#TRANSITIVE_PROPERTY}.
0350: * </p>
0351: *
0352: * @return An iterator over transitive property resources.
0353: */
0354: public ExtendedIterator listTransitiveProperties() {
0355: checkProfileEntry(getProfile().TRANSITIVE_PROPERTY(),
0356: "TRANSITIVE_PROPERTY");
0357: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0358: .TRANSITIVE_PROPERTY(), TransitiveProperty.class));
0359: }
0360:
0361: /**
0362: * <p>
0363: * Answer an iterator that ranges over the symmetric property resources in this model, i.e.
0364: * the resources with <code>rdf:type SymmetricProperty</code> or equivalent.
0365: * </p>
0366: * <p>
0367: * Specifically, the resources in this iterator will those whose type corresponds
0368: * to the value given in the ontology vocabulary associated with this model: see
0369: * {@link Profile#SYMMETRIC_PROPERTY}.
0370: * </p>
0371: *
0372: * @return An iterator over symmetric property resources.
0373: */
0374: public ExtendedIterator listSymmetricProperties() {
0375: checkProfileEntry(getProfile().SYMMETRIC_PROPERTY(),
0376: "SYMMETRIC_PROPERTY");
0377: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0378: .SYMMETRIC_PROPERTY(), SymmetricProperty.class));
0379: }
0380:
0381: /**
0382: * <p>
0383: * Answer an iterator that ranges over the inverse functional property resources in this model, i.e.
0384: * the resources with <code>rdf:type InverseFunctionalProperty</code> or equivalent.
0385: * </p>
0386: * <p>
0387: * Specifically, the resources in this iterator will those whose type corresponds
0388: * to the value given in the ontology vocabulary associated with this model: see
0389: * {@link Profile#INVERSE_FUNCTIONAL_PROPERTY}.
0390: * </p>
0391: *
0392: * @return An iterator over inverse functional property resources.
0393: */
0394: public ExtendedIterator listInverseFunctionalProperties() {
0395: checkProfileEntry(getProfile().INVERSE_FUNCTIONAL_PROPERTY(),
0396: "INVERSE_FUNCTIONAL_PROPERTY");
0397: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0398: .INVERSE_FUNCTIONAL_PROPERTY(),
0399: InverseFunctionalProperty.class));
0400: }
0401:
0402: /**
0403: * <p>
0404: * Answer an iterator that ranges over the individual resources in this model, i.e.
0405: * the resources with <code>rdf:type</code> corresponding to a class defined
0406: * in the ontology.
0407: * </p>
0408: * <p>
0409: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0410: * the completeness of the deductive extension of the underlying graph. See class
0411: * overview for more details.
0412: * </p>
0413: *
0414: * @return An iterator over Individuals.
0415: */
0416: public ExtendedIterator listIndividuals() {
0417: // since the reasoner implements some OWL full functionality for RDF compatability, we
0418: // have to decide which strategy to use for indentifying individuals depending on whether
0419: // or not a powerful reasoner (i.e. owl:Thing/daml:Thing aware) is being used with this model
0420: boolean supportsIndAsThing = false;
0421: if (getGraph() instanceof InfGraph) {
0422: supportsIndAsThing = ((InfGraph) getGraph()).getReasoner()
0423: .getReasonerCapabilities().contains(null,
0424: ReasonerVocabulary.supportsP,
0425: ReasonerVocabulary.individualAsThingP);
0426: }
0427: if (!supportsIndAsThing || (getProfile().THING() == null)
0428: || getProfile().CLASS().equals(RDFS.Class)) {
0429: // no inference, or we are in RDFS land, so we pick things that have rdf:type whose rdf:type is Class
0430:
0431: // we have to build the query plans dynamically - these were done once-only in pre-Jena-2.5,
0432: // but this can interfere with some opimisations
0433: ExtendedIterator indivI = queryFor(
0434: queryXTypeOfType(getProfile().CLASS()), null,
0435: Individual.class);
0436:
0437: if (getProfile().RESTRICTION() != null) {
0438: // and things whose rdf:type is Restriction
0439: indivI = indivI.andThen(queryFor(
0440: queryXTypeOfType(getProfile().RESTRICTION()),
0441: null, Individual.class));
0442: }
0443:
0444: // we also must pick resources that simply have rdf:type owl:Thing, since some individuals are asserted that way
0445: if (getProfile().THING() != null) {
0446: indivI = indivI.andThen(findByTypeAs(getProfile()
0447: .THING(), Individual.class));
0448: }
0449:
0450: return UniqueExtendedIterator.create(indivI);
0451: } else {
0452: // we have inference, so we pick the nodes that are of type Thing
0453: return UniqueExtendedIterator.create(findByTypeAs(
0454: getProfile().THING(), Individual.class));
0455: }
0456: }
0457:
0458: /**
0459: * <p>
0460: * Answer an iterator that ranges over the resources in this model that are
0461: * instances of the given class.
0462: * </p>
0463: *
0464: * @return An iterator over individual resources whose <code>rdf:type</code>
0465: * is <code>cls</code>.
0466: */
0467: public ExtendedIterator listIndividuals(Resource cls) {
0468: return UniqueExtendedIterator.create(findByTypeAs(cls,
0469: Individual.class));
0470: }
0471:
0472: /**
0473: * <p>
0474: * Answer an iterator that ranges over all of the various forms of class description resource
0475: * in this model. Class descriptions include {@link #listEnumeratedClasses enumerated}
0476: * classes, {@link #listUnionClasses union} classes, {@link #listComplementClasses complement}
0477: * classes, {@link #listIntersectionClasses intersection} classes, {@link #listClasses named}
0478: * classes and {@link #listRestrictions property restrictions}.
0479: * </p>
0480: * <p>
0481: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0482: * the completeness of the deductive extension of the underlying graph. See class
0483: * overview for more details.
0484: * </p>
0485: *
0486: * @return An iterator over class description resources.
0487: */
0488: public ExtendedIterator listClasses() {
0489: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0490: .getClassDescriptionTypes(), OntClass.class));
0491: }
0492:
0493: /**
0494: * <p>Answer an iterator over the classes in this ontology model that represent
0495: * the uppermost nodes of the class hierarchy. Depending on the underlying
0496: * reasoner configuration, if any, these will be calculated as the classes
0497: * that have Top (i.e. <code>owl:Thing</code> or <code>daml:Thing</code>)
0498: * as a direct super-class, or the classes which have no declared super-class.</p>
0499: * @return An iterator of the root classes in the local class hierarchy
0500: */
0501: public ExtendedIterator listHierarchyRootClasses() {
0502: // look for the shortcut of using direct subClass on :Thing
0503: if (getReasoner() != null) {
0504: Model conf = getReasoner().getReasonerCapabilities();
0505: if (conf != null
0506: && conf.contains(null,
0507: ReasonerVocabulary.supportsP,
0508: ReasonerVocabulary.directSubClassOf)
0509: && getProfile().THING() != null) {
0510: // we have have both direct sub-class of and a :Thing class to test against
0511: return listStatements(null,
0512: ReasonerVocabulary.directSubClassOf,
0513: getProfile().THING()).mapWith(
0514: new OntResourceImpl.SubjectAsMapper(
0515: OntClass.class));
0516: }
0517: }
0518:
0519: // no easy shortcut, so we use brute force
0520: return listClasses().filterDrop(new Filter() {
0521: public boolean accept(Object o) {
0522: return ((OntResource) o).isOntLanguageTerm();
0523: }
0524: }).filterKeep(new Filter() {
0525: public boolean accept(Object o) {
0526: return ((OntClass) o).isHierarchyRoot();
0527: }
0528: });
0529: }
0530:
0531: /**
0532: * <p>
0533: * Answer an iterator that ranges over the enumerated class class-descriptions
0534: * in this model, i.e. the class resources specified to have a property
0535: * <code>oneOf</code> (or equivalent) and a list of values.
0536: * </p>
0537: * <p>
0538: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0539: * the completeness of the deductive extension of the underlying graph. See class
0540: * overview for more details.
0541: * </p>
0542: *
0543: * @return An iterator over enumerated class resources.
0544: * @see Profile#ONE_OF
0545: */
0546: public ExtendedIterator listEnumeratedClasses() {
0547: checkProfileEntry(getProfile().ONE_OF(), "ONE_OF");
0548: return UniqueExtendedIterator.create(findByDefiningPropertyAs(
0549: getProfile().ONE_OF(), EnumeratedClass.class));
0550: }
0551:
0552: /**
0553: * <p>
0554: * Answer an iterator that ranges over the union class-descriptions
0555: * in this model, i.e. the class resources specified to have a property
0556: * <code>unionOf</code> (or equivalent) and a list of values.
0557: * </p>
0558: * <p>
0559: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0560: * the completeness of the deductive extension of the underlying graph. See class
0561: * overview for more details.
0562: * </p>
0563: *
0564: * @return An iterator over union class resources.
0565: * @see Profile#UNION_OF
0566: */
0567: public ExtendedIterator listUnionClasses() {
0568: checkProfileEntry(getProfile().UNION_OF(), "UNION_OF");
0569: return UniqueExtendedIterator.create(findByDefiningPropertyAs(
0570: getProfile().UNION_OF(), UnionClass.class));
0571: }
0572:
0573: /**
0574: * <p>
0575: * Answer an iterator that ranges over the complement class-descriptions
0576: * in this model, i.e. the class resources specified to have a property
0577: * <code>complementOf</code> (or equivalent) and a list of values.
0578: * </p>
0579: * <p>
0580: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0581: * the completeness of the deductive extension of the underlying graph. See class
0582: * overview for more details.
0583: * </p>
0584: *
0585: * @return An iterator over complement class resources.
0586: * @see Profile#COMPLEMENT_OF
0587: */
0588: public ExtendedIterator listComplementClasses() {
0589: checkProfileEntry(getProfile().COMPLEMENT_OF(), "COMPLEMENT_OF");
0590: return UniqueExtendedIterator.create(findByDefiningPropertyAs(
0591: getProfile().COMPLEMENT_OF(), ComplementClass.class));
0592: }
0593:
0594: /**
0595: * <p>
0596: * Answer an iterator that ranges over the intersection class-descriptions
0597: * in this model, i.e. the class resources specified to have a property
0598: * <code>intersectionOf</code> (or equivalent) and a list of values.
0599: * </p>
0600: * <p>
0601: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0602: * the completeness of the deductive extension of the underlying graph. See class
0603: * overview for more details.
0604: * </p>
0605: *
0606: * @return An iterator over complement class resources.
0607: * @see Profile#INTERSECTION_OF
0608: */
0609: public ExtendedIterator listIntersectionClasses() {
0610: checkProfileEntry(getProfile().INTERSECTION_OF(),
0611: "INTERSECTION_OF");
0612: return UniqueExtendedIterator
0613: .create(findByDefiningPropertyAs(getProfile()
0614: .INTERSECTION_OF(), IntersectionClass.class));
0615: }
0616:
0617: /**
0618: * <p>
0619: * Answer an iterator that ranges over the named class-descriptions
0620: * in this model, i.e. resources with <code>rdf:type
0621: * Class</code> (or equivalent) and a node URI.
0622: * </p>
0623: * <p>
0624: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0625: * the completeness of the deductive extension of the underlying graph. See class
0626: * overview for more details.
0627: * </p>
0628: *
0629: * @return An iterator over named class resources.
0630: */
0631: public ExtendedIterator listNamedClasses() {
0632: return listClasses().filterDrop(new Filter() {
0633: public boolean accept(Object x) {
0634: return ((Resource) x).isAnon();
0635: }
0636: });
0637: }
0638:
0639: /**
0640: * <p>
0641: * Answer an iterator that ranges over the property restriction class-descriptions
0642: * in this model, i.e. resources with <code>rdf:type
0643: * Restriction</code> (or equivalent).
0644: * </p>
0645: * <p>
0646: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0647: * the completeness of the deductive extension of the underlying graph. See class
0648: * overview for more details.
0649: * </p>
0650: *
0651: * @return An iterator over restriction class resources.
0652: * @see Profile#RESTRICTION
0653: */
0654: public ExtendedIterator listRestrictions() {
0655: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
0656: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0657: .RESTRICTION(), Restriction.class));
0658: }
0659:
0660: /**
0661: * <p>
0662: * Answer an iterator that ranges over the nodes that denote pair-wise disjointness between
0663: * sets of classes.
0664: * </p>
0665: * <p>
0666: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0667: * the completeness of the deductive extension of the underlying graph. See class
0668: * overview for more details.
0669: * </p>
0670: *
0671: * @return An iterator over AllDifferent nodes.
0672: */
0673: public ExtendedIterator listAllDifferent() {
0674: checkProfileEntry(getProfile().ALL_DIFFERENT(), "ALL_DIFFERENT");
0675: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0676: .ALL_DIFFERENT(), AllDifferent.class));
0677: }
0678:
0679: /**
0680: * <p>Answer an iterator over the DataRange objects in this ontology, if there
0681: * are any.</p>
0682: * @return An iterator, whose values are {@link DataRange} objects.
0683: */
0684: public ExtendedIterator listDataRanges() {
0685: checkProfileEntry(getProfile().DATARANGE(), "DATARANGE");
0686: return UniqueExtendedIterator.create(findByTypeAs(getProfile()
0687: .DATARANGE(), DataRange.class));
0688: }
0689:
0690: /**
0691: * <p>
0692: * Answer an iterator that ranges over the properties in this model that are declared
0693: * to be annotation properties. Not all supported languages define annotation properties
0694: * (the category of annotation properties is chiefly an OWL innovation).
0695: * </p>
0696: * <p>
0697: * <strong>Note:</strong> the number of nodes returned by this iterator will vary according to
0698: * the completeness of the deductive extension of the underlying graph. See class
0699: * overview for more details.
0700: * </p>
0701: *
0702: * @return An iterator over annotation properties.
0703: * @see Profile#getAnnotationProperties()
0704: */
0705: public ExtendedIterator listAnnotationProperties() {
0706: checkProfileEntry(getProfile().ANNOTATION_PROPERTY(),
0707: "ANNOTATION_PROPERTY");
0708: Resource r = getProfile().ANNOTATION_PROPERTY();
0709:
0710: if (r == null) {
0711: return NullIterator.instance;
0712: } else {
0713: return UniqueExtendedIterator.create(findByType(r).andThen(
0714: WrappedIterator.create(getProfile()
0715: .getAnnotationProperties())).mapWith(
0716: new SubjectNodeAs(AnnotationProperty.class)));
0717: }
0718: }
0719:
0720: /**
0721: * <p>
0722: * Answer a resource that represents an ontology description node in this model. If a resource
0723: * with the given uri exists in the model, and can be viewed as an Ontology, return the
0724: * Ontology facet, otherwise return null.
0725: * </p>
0726: *
0727: * @param uri The uri for the ontology node. Conventionally, this corresponds to the base URI
0728: * of the document itself.
0729: * @return An Ontology resource or null.
0730: */
0731: public Ontology getOntology(String uri) {
0732: return (Ontology) findByURIAs(uri, Ontology.class);
0733: }
0734:
0735: /**
0736: * <p>
0737: * Answer a resource that represents an Individual node in this model. If a resource
0738: * with the given uri exists in the model, and can be viewed as an Individual, return the
0739: * Individual facet, otherwise return null.
0740: * </p>
0741: *
0742: * @param uri The URI for the requried individual
0743: * @return An Individual resource or null.
0744: */
0745: public Individual getIndividual(String uri) {
0746: return (Individual) findByURIAs(uri, Individual.class);
0747: }
0748:
0749: /**
0750: * <p>
0751: * Answer a resource representing an generic property in this model. If a property
0752: * with the given uri exists in the model, return the
0753: * OntProperty facet, otherwise return null.
0754: * </p>
0755: *
0756: * @param uri The uri for the property.
0757: * @return An OntProperty resource or null.
0758: */
0759: public OntProperty getOntProperty(String uri) {
0760: return (OntProperty) findByURIAs(uri, OntProperty.class);
0761: }
0762:
0763: /**
0764: * <p>
0765: * Answer a resource representing an object property in this model. If a resource
0766: * with the given uri exists in the model, and can be viewed as an ObjectProperty, return the
0767: * ObjectProperty facet, otherwise return null.
0768: * </p>
0769: *
0770: * @param uri The uri for the object property. May not be null.
0771: * @return An ObjectProperty resource or null.
0772: */
0773: public ObjectProperty getObjectProperty(String uri) {
0774: return (ObjectProperty) findByURIAs(uri, ObjectProperty.class);
0775: }
0776:
0777: /**
0778: * <p>Answer a resource representing a transitive property. If a resource
0779: * with the given uri exists in the model, and can be viewed as a TransitiveProperty, return the
0780: * TransitiveProperty facet, otherwise return null. </p>
0781: * @param uri The uri for the property. May not be null.
0782: * @return A TransitiveProperty resource or null
0783: */
0784: public TransitiveProperty getTransitiveProperty(String uri) {
0785: return (TransitiveProperty) findByURIAs(uri,
0786: TransitiveProperty.class);
0787: }
0788:
0789: /**
0790: * <p>Answer a resource representing a symmetric property. If a resource
0791: * with the given uri exists in the model, and can be viewed as a SymmetricProperty, return the
0792: * SymmetricProperty facet, otherwise return null. </p>
0793: * @param uri The uri for the property. May not be null.
0794: * @return A SymmetricProperty resource or null
0795: */
0796: public SymmetricProperty getSymmetricProperty(String uri) {
0797: return (SymmetricProperty) findByURIAs(uri,
0798: SymmetricProperty.class);
0799: }
0800:
0801: /**
0802: * <p>Answer a resource representing an inverse functional property. If a resource
0803: * with the given uri exists in the model, and can be viewed as a InverseFunctionalProperty, return the
0804: * InverseFunctionalProperty facet, otherwise return null. </p>
0805: * @param uri The uri for the property. May not be null.
0806: * @return An InverseFunctionalProperty resource or null
0807: */
0808: public InverseFunctionalProperty getInverseFunctionalProperty(
0809: String uri) {
0810: return (InverseFunctionalProperty) findByURIAs(uri,
0811: InverseFunctionalProperty.class);
0812: }
0813:
0814: /**
0815: * <p>
0816: * Answer a resource that represents datatype property in this model. . If a resource
0817: * with the given uri exists in the model, and can be viewed as a DatatypeProperty, return the
0818: * DatatypeProperty facet, otherwise return null.
0819: * </p>
0820: *
0821: * @param uri The uri for the datatype property. May not be null.
0822: * @return A DatatypeProperty resource or null
0823: */
0824: public DatatypeProperty getDatatypeProperty(String uri) {
0825: return (DatatypeProperty) findByURIAs(uri,
0826: DatatypeProperty.class);
0827: }
0828:
0829: /**
0830: * <p>
0831: * Answer a resource that represents an annotation property in this model. If a resource
0832: * with the given uri exists in the model, and can be viewed as an AnnotationProperty, return the
0833: * AnnotationProperty facet, otherwise return null.
0834: * </p>
0835: *
0836: * @param uri The uri for the annotation property. May not be null.
0837: * @return An AnnotationProperty resource or null
0838: */
0839: public AnnotationProperty getAnnotationProperty(String uri) {
0840: return (AnnotationProperty) findByURIAs(uri,
0841: AnnotationProperty.class);
0842: }
0843:
0844: /**
0845: * <p>
0846: * Answer a resource that represents a class description node in this model. If a resource
0847: * with the given uri exists in the model, and can be viewed as an OntClass, return the
0848: * OntClass facet, otherwise return null.
0849: * </p>
0850: *
0851: * @param uri The uri for the class node, or null for an anonymous class.
0852: * @return An OntClass resource or null.
0853: */
0854: public OntClass getOntClass(String uri) {
0855: OntClass c = (OntClass) findByURIAs(uri, OntClass.class);
0856:
0857: // special case for nothing and thing
0858: if (c == null) {
0859: Resource thing = getProfile().THING();
0860: if (thing != null && thing.getURI().equals(uri)) {
0861: c = (OntClass) thing.inModel(this ).as(OntClass.class);
0862: }
0863:
0864: Resource nothing = getProfile().NOTHING();
0865: if (nothing != null && nothing.getURI().equals(uri)) {
0866: c = (OntClass) nothing.inModel(this ).as(OntClass.class);
0867: }
0868: }
0869:
0870: return c;
0871: }
0872:
0873: /**
0874: * <p>Answer a resource representing the class that is the complement of another class. If a resource
0875: * with the given uri exists in the model, and can be viewed as a ComplementClass, return the
0876: * ComplementClass facet, otherwise return null. </p>
0877: * @param uri The URI of the new complement class.
0878: * @return A complement class or null
0879: */
0880: public ComplementClass getComplementClass(String uri) {
0881: return (ComplementClass) findByURIAs(uri, ComplementClass.class);
0882: }
0883:
0884: /**
0885: * <p>Answer a resource representing the class that is the enumeration of a list of individuals. If a resource
0886: * with the given uri exists in the model, and can be viewed as an EnumeratedClass, return the
0887: * EnumeratedClass facet, otherwise return null. </p>
0888: * @param uri The URI of the new enumeration class.
0889: * @return An enumeration class or null
0890: */
0891: public EnumeratedClass getEnumeratedClass(String uri) {
0892: return (EnumeratedClass) findByURIAs(uri, EnumeratedClass.class);
0893: }
0894:
0895: /**
0896: * <p>Answer a resource representing the class that is the union of a list of class desctiptions. If a resource
0897: * with the given uri exists in the model, and can be viewed as a UnionClass, return the
0898: * UnionClass facet, otherwise return null. </p>
0899: * @param uri The URI of the new union class.
0900: * @return A union class description or null
0901: */
0902: public UnionClass getUnionClass(String uri) {
0903: return (UnionClass) findByURIAs(uri, UnionClass.class);
0904: }
0905:
0906: /**
0907: * <p>Answer a resource representing the class that is the intersection of a list of class descriptions. If a resource
0908: * with the given uri exists in the model, and can be viewed as a IntersectionClass, return the
0909: * IntersectionClass facet, otherwise return null. </p>
0910: * @param uri The URI of the new intersection class.
0911: * @return An intersection class description or null
0912: */
0913: public IntersectionClass getIntersectionClass(String uri) {
0914: return (IntersectionClass) findByURIAs(uri,
0915: IntersectionClass.class);
0916: }
0917:
0918: /**
0919: * <p>
0920: * Answer a resource that represents a property restriction in this model. If a resource
0921: * with the given uri exists in the model, and can be viewed as a Restriction, return the
0922: * Restriction facet, otherwise return null.
0923: * </p>
0924: *
0925: * @param uri The uri for the restriction node.
0926: * @return A Restriction resource or null
0927: */
0928: public Restriction getRestriction(String uri) {
0929: return (Restriction) findByURIAs(uri, Restriction.class);
0930: }
0931:
0932: /**
0933: * <p>Answer a class description defined as the class of those individuals that have the given
0934: * resource as the value of the given property. If a resource
0935: * with the given uri exists in the model, and can be viewed as a HasValueRestriction, return the
0936: * HasValueRestriction facet, otherwise return null. </p>
0937: *
0938: * @param uri The URI for the restriction
0939: * @return A resource representing a has-value restriction or null
0940: */
0941: public HasValueRestriction getHasValueRestriction(String uri) {
0942: return (HasValueRestriction) findByURIAs(uri,
0943: HasValueRestriction.class);
0944: }
0945:
0946: /**
0947: * <p>Answer a class description defined as the class of those individuals that have at least
0948: * one property with a value belonging to the given class. If a resource
0949: * with the given uri exists in the model, and can be viewed as a SomeValuesFromRestriction, return the
0950: * SomeValuesFromRestriction facet, otherwise return null. </p>
0951: *
0952: * @param uri The URI for the restriction
0953: * @return A resource representing a some-values-from restriction, or null
0954: */
0955: public SomeValuesFromRestriction getSomeValuesFromRestriction(
0956: String uri) {
0957: return (SomeValuesFromRestriction) findByURIAs(uri,
0958: SomeValuesFromRestriction.class);
0959: }
0960:
0961: /**
0962: * <p>Answer a class description defined as the class of those individuals for which all values
0963: * of the given property belong to the given class. If a resource
0964: * with the given uri exists in the model, and can be viewed as an AllValuesFromResriction, return the
0965: * AllValuesFromRestriction facet, otherwise return null. </p>
0966: *
0967: * @param uri The URI for the restriction
0968: * @return A resource representing an all-values-from restriction or null
0969: */
0970: public AllValuesFromRestriction getAllValuesFromRestriction(
0971: String uri) {
0972: return (AllValuesFromRestriction) findByURIAs(uri,
0973: AllValuesFromRestriction.class);
0974: }
0975:
0976: /**
0977: * <p>Answer a class description defined as the class of those individuals that have exactly
0978: * the given number of values for the given property. If a resource
0979: * with the given uri exists in the model, and can be viewed as a CardinalityRestriction, return the
0980: * CardinalityRestriction facet, otherwise return null. </p>
0981: *
0982: * @param uri The URI for the restriction
0983: * @return A resource representing a has-value restriction, or null
0984: */
0985: public CardinalityRestriction getCardinalityRestriction(String uri) {
0986: return (CardinalityRestriction) findByURIAs(uri,
0987: CardinalityRestriction.class);
0988: }
0989:
0990: /**
0991: * <p>Answer a class description defined as the class of those individuals that have at least
0992: * the given number of values for the given property. If a resource
0993: * with the given uri exists in the model, and can be viewed as a MinCardinalityRestriction, return the
0994: * MinCardinalityRestriction facet, otherwise return null. </p>
0995: *
0996: * @param uri The URI for the restriction
0997: * @return A resource representing a min-cardinality restriction, or null
0998: */
0999: public MinCardinalityRestriction getMinCardinalityRestriction(
1000: String uri) {
1001: return (MinCardinalityRestriction) findByURIAs(uri,
1002: MinCardinalityRestriction.class);
1003: }
1004:
1005: /**
1006: * <p>Answer a class description defined as the class of those individuals that have at most
1007: * the given number of values for the given property. If a resource
1008: * with the given uri exists in the model, and can be viewed as a MaxCardinalityRestriction, return the
1009: * MaxCardinalityRestriction facet, otherwise return null.</p>
1010: *
1011: * @param uri The URI for the restriction
1012: * @return A resource representing a mas-cardinality restriction, or null
1013: */
1014: public MaxCardinalityRestriction getMaxCardinalityRestriction(
1015: String uri) {
1016: return (MaxCardinalityRestriction) findByURIAs(uri,
1017: MaxCardinalityRestriction.class);
1018: }
1019:
1020: /**
1021: * <p>Answer a class description defined as the class of those individuals that have a property
1022: * p, all values of which are members of a given class. Typically used with a cardinality constraint.
1023: * If a resource
1024: * with the given uri exists in the model, and can be viewed as a QualifiedRestriction, return the
1025: * QualifiedRestriction facet, otherwise return null.</p>
1026: *
1027: * @param uri The URI for the restriction
1028: * @return A resource representing a qualified restriction, or null
1029: */
1030: public QualifiedRestriction getQualifiedRestriction(String uri) {
1031: return (QualifiedRestriction) findByURIAs(uri,
1032: QualifiedRestriction.class);
1033: }
1034:
1035: /**
1036: * <p>Answer a class description defined as the class of those individuals that have a property
1037: * p, with cardinality N, all values of which are members of a given class.
1038: * If a resource
1039: * with the given uri exists in the model, and can be viewed as a CardinalityQRestriction, return the
1040: * CardinalityQRestriction facet, otherwise return null.</p>
1041: *
1042: * @param uri The URI for the restriction
1043: * @return A resource representing a qualified cardinality restriction, or null
1044: */
1045: public CardinalityQRestriction getCardinalityQRestriction(String uri) {
1046: return (CardinalityQRestriction) findByURIAs(uri,
1047: CardinalityQRestriction.class);
1048: }
1049:
1050: /**
1051: * <p>Answer a class description defined as the class of those individuals that have a property
1052: * p, with min cardinality N, all values of which are members of a given class.
1053: * If a resource
1054: * with the given uri exists in the model, and can be viewed as a MinCardinalityQRestriction, return the
1055: * MinCardinalityQRestriction facet, otherwise return null.</p>
1056: *
1057: * @param uri The URI for the restriction
1058: * @return A resource representing a qualified min cardinality restriction, or null
1059: */
1060: public MinCardinalityQRestriction getMinCardinalityQRestriction(
1061: String uri) {
1062: return (MinCardinalityQRestriction) findByURIAs(uri,
1063: MinCardinalityQRestriction.class);
1064: }
1065:
1066: /**
1067: * <p>Answer a class description defined as the class of those individuals that have a property
1068: * p, with max cardinality N, all values of which are members of a given class.
1069: * If a resource
1070: * with the given uri exists in the model, and can be viewed as a MaxCardinalityQRestriction, return the
1071: * MaxCardinalityQRestriction facet, otherwise return null.</p>
1072: *
1073: * @param uri The URI for the restriction
1074: * @return A resource representing a qualified max cardinality restriction, or null
1075: */
1076: public MaxCardinalityQRestriction getMaxCardinalityQRestriction(
1077: String uri) {
1078: return (MaxCardinalityQRestriction) findByURIAs(uri,
1079: MaxCardinalityQRestriction.class);
1080: }
1081:
1082: /**
1083: * <p>
1084: * Answer a resource that represents an ontology description node in this model. If a resource
1085: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1086: * the updateable sub-graph of the ontology model.
1087: * </p>
1088: *
1089: * @param uri The uri for the ontology node. Conventionally, this corresponds to the base URI
1090: * of the document itself.
1091: * @return An Ontology resource.
1092: */
1093: public Ontology createOntology(String uri) {
1094: checkProfileEntry(getProfile().ONTOLOGY(), "ONTOLOGY");
1095: return (Ontology) createOntResource(Ontology.class,
1096: getProfile().ONTOLOGY(), uri);
1097: }
1098:
1099: /**
1100: * <p>
1101: * Answer a resource that represents an Indvidual node in this model. A new anonymous resource
1102: * will be created in the updateable sub-graph of the ontology model.
1103: * </p>
1104: *
1105: * @param cls Resource representing the ontology class to which the individual belongs
1106: * @return A new anoymous Individual of the given class.
1107: */
1108: public Individual createIndividual(Resource cls) {
1109: return (Individual) createOntResource(Individual.class, cls,
1110: null);
1111: }
1112:
1113: /**
1114: * <p>
1115: * Answer a resource that represents an Individual node in this model. If a resource
1116: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1117: * the updateable sub-graph of the ontology model.
1118: * </p>
1119: *
1120: * @param cls Resource representing the ontology class to which the individual belongs
1121: * @param uri The uri for the individual, or null for an anonymous individual.
1122: * @return An Individual resource.
1123: */
1124: public Individual createIndividual(String uri, Resource cls) {
1125: return (Individual) createOntResource(Individual.class, cls,
1126: uri);
1127: }
1128:
1129: /**
1130: * <p>
1131: * Answer a resource representing an generic property in this model. Effectively
1132: * this method is an alias for {@link #createProperty( String )}, except that
1133: * the return type is {@link OntProperty}, which allow more convenient access to
1134: * a property's position in the property hierarchy, domain, range, etc.
1135: * </p>
1136: *
1137: * @param uri The uri for the property. May not be null.
1138: * @return An OntProperty resource.
1139: */
1140: public OntProperty createOntProperty(String uri) {
1141: Property p = createProperty(uri);
1142: p.addProperty(RDF.type, getProfile().PROPERTY());
1143: return (OntProperty) p.as(OntProperty.class);
1144: }
1145:
1146: /**
1147: * <p>
1148: * Answer a resource representing an object property in this model,
1149: * and that is not a functional property.
1150: * </p>
1151: *
1152: * @param uri The uri for the object property. May not be null.
1153: * @return An ObjectProperty resource.
1154: * @see #createObjectProperty( String, boolean )
1155: */
1156: public ObjectProperty createObjectProperty(String uri) {
1157: return createObjectProperty(uri, false);
1158: }
1159:
1160: /**
1161: * <p>
1162: * Answer a resource that represents an object property in this model. An object property
1163: * is defined to have a range of individuals, rather than datatypes.
1164: * If a resource
1165: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1166: * the updateable sub-graph of the ontology model.
1167: * </p>
1168: *
1169: * @param uri The uri for the object property. May not be null.
1170: * @param functional If true, the resource will also be typed as a {@link FunctionalProperty},
1171: * that is, a property that has a unique range value for any given domain value.
1172: * @return An ObjectProperty resource, optionally also functional.
1173: */
1174: public ObjectProperty createObjectProperty(String uri,
1175: boolean functional) {
1176: checkProfileEntry(getProfile().OBJECT_PROPERTY(),
1177: "OBJECT_PROPERTY");
1178: ObjectProperty p = (ObjectProperty) createOntResource(
1179: ObjectProperty.class, getProfile().OBJECT_PROPERTY(),
1180: uri);
1181:
1182: if (functional) {
1183: checkProfileEntry(getProfile().FUNCTIONAL_PROPERTY(),
1184: "FUNCTIONAL_PROPERTY");
1185: p.addProperty(RDF.type, getProfile().FUNCTIONAL_PROPERTY());
1186: }
1187:
1188: return p;
1189: }
1190:
1191: /**
1192: * <p>Answer a resource representing a transitive property</p>
1193: * @param uri The uri for the property. May not be null.
1194: * @return An TransitiveProperty resource
1195: * @see #createTransitiveProperty( String, boolean )
1196: */
1197: public TransitiveProperty createTransitiveProperty(String uri) {
1198: return createTransitiveProperty(uri, false);
1199: }
1200:
1201: /**
1202: * <p>Answer a resource representing a transitive property, which is optionally
1203: * also functional. <strong>Note:</strong> although it is permitted in OWL full
1204: * to have functional transitive properties, it makes the language undecideable.
1205: * Functional transitive properties are not permitted in OWL Lite or OWL DL.</p>
1206: * @param uri The uri for the property. May not be null.
1207: * @param functional If true, the property is also functional
1208: * @return An TransitiveProperty resource, optionally also functional.
1209: */
1210: public TransitiveProperty createTransitiveProperty(String uri,
1211: boolean functional) {
1212: checkProfileEntry(getProfile().TRANSITIVE_PROPERTY(),
1213: "TRANSITIVE_PROPERTY");
1214: TransitiveProperty p = (TransitiveProperty) createOntResource(
1215: TransitiveProperty.class, getProfile()
1216: .TRANSITIVE_PROPERTY(), uri);
1217:
1218: if (functional) {
1219: checkProfileEntry(getProfile().FUNCTIONAL_PROPERTY(),
1220: "FUNCTIONAL_PROPERTY");
1221: p.addProperty(RDF.type, getProfile().FUNCTIONAL_PROPERTY());
1222: }
1223:
1224: return p;
1225: }
1226:
1227: /**
1228: * <p>Answer a resource representing a symmetric property</p>
1229: * @param uri The uri for the property. May not be null.
1230: * @return An SymmetricProperty resource
1231: * @see #createSymmetricProperty( String, boolean )
1232: */
1233: public SymmetricProperty createSymmetricProperty(String uri) {
1234: return createSymmetricProperty(uri, false);
1235: }
1236:
1237: /**
1238: * <p>Answer a resource representing a symmetric property, which is optionally
1239: * also functional.</p>
1240: * @param uri The uri for the property. May not be null.
1241: * @param functional If true, the property is also functional
1242: * @return An SymmetricProperty resource, optionally also functional.
1243: */
1244: public SymmetricProperty createSymmetricProperty(String uri,
1245: boolean functional) {
1246: checkProfileEntry(getProfile().SYMMETRIC_PROPERTY(),
1247: "SYMMETRIC_PROPERTY");
1248: SymmetricProperty p = (SymmetricProperty) createOntResource(
1249: SymmetricProperty.class, getProfile()
1250: .SYMMETRIC_PROPERTY(), uri);
1251:
1252: if (functional) {
1253: checkProfileEntry(getProfile().FUNCTIONAL_PROPERTY(),
1254: "FUNCTIONAL_PROPERTY");
1255: p.addProperty(RDF.type, getProfile().FUNCTIONAL_PROPERTY());
1256: }
1257:
1258: return p;
1259: }
1260:
1261: /**
1262: * <p>Answer a resource representing an inverse functional property</p>
1263: * @param uri The uri for the property. May not be null.
1264: * @return An InverseFunctionalProperty resource
1265: * @see #createInverseFunctionalProperty( String, boolean )
1266: */
1267: public InverseFunctionalProperty createInverseFunctionalProperty(
1268: String uri) {
1269: return createInverseFunctionalProperty(uri, false);
1270: }
1271:
1272: /**
1273: * <p>Answer a resource representing an inverse functional property, which is optionally
1274: * also functional.</p>
1275: * @param uri The uri for the property. May not be null.
1276: * @param functional If true, the property is also functional
1277: * @return An InverseFunctionalProperty resource, optionally also functional.
1278: */
1279: public InverseFunctionalProperty createInverseFunctionalProperty(
1280: String uri, boolean functional) {
1281: checkProfileEntry(getProfile().INVERSE_FUNCTIONAL_PROPERTY(),
1282: "INVERSE_FUNCTIONAL_PROPERTY");
1283: InverseFunctionalProperty p = (InverseFunctionalProperty) createOntResource(
1284: InverseFunctionalProperty.class, getProfile()
1285: .INVERSE_FUNCTIONAL_PROPERTY(), uri);
1286:
1287: if (functional) {
1288: checkProfileEntry(getProfile().FUNCTIONAL_PROPERTY(),
1289: "FUNCTIONAL_PROPERTY");
1290: p.addProperty(RDF.type, getProfile().FUNCTIONAL_PROPERTY());
1291: }
1292:
1293: return p;
1294: }
1295:
1296: /**
1297: * <p>
1298: * Answer a resource that represents datatype property in this model, and that is
1299: * not a functional property.
1300: * </p>
1301: *
1302: * @param uri The uri for the datatype property. May not be null.
1303: * @return A DatatypeProperty resource.
1304: * @see #createDatatypeProperty( String, boolean )
1305: */
1306: public DatatypeProperty createDatatypeProperty(String uri) {
1307: return createDatatypeProperty(uri, false);
1308: }
1309:
1310: /**
1311: * <p>
1312: * Answer a resource that represents datatype property in this model. A datatype property
1313: * is defined to have a range that is a concrete datatype, rather than an individual.
1314: * If a resource
1315: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1316: * the updateable sub-graph of the ontology model.
1317: * </p>
1318: *
1319: * @param uri The uri for the datatype property. May not be null.
1320: * @param functional If true, the resource will also be typed as a {@link FunctionalProperty},
1321: * that is, a property that has a unique range value for any given domain value.
1322: * @return A DatatypeProperty resource.
1323: */
1324: public DatatypeProperty createDatatypeProperty(String uri,
1325: boolean functional) {
1326: checkProfileEntry(getProfile().DATATYPE_PROPERTY(),
1327: "DATATYPE_PROPERTY");
1328: DatatypeProperty p = (DatatypeProperty) createOntResource(
1329: DatatypeProperty.class, getProfile()
1330: .DATATYPE_PROPERTY(), uri);
1331:
1332: if (functional) {
1333: checkProfileEntry(getProfile().FUNCTIONAL_PROPERTY(),
1334: "FUNCTIONAL_PROPERTY");
1335: p.addProperty(RDF.type, getProfile().FUNCTIONAL_PROPERTY());
1336: }
1337:
1338: return p;
1339: }
1340:
1341: /**
1342: * <p>
1343: * Answer a resource that represents an annotation property in this model. If a resource
1344: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1345: * the updateable sub-graph of the ontology model.
1346: * </p>
1347: *
1348: * @param uri The uri for the annotation property.
1349: * @return An AnnotationProperty resource.
1350: */
1351: public AnnotationProperty createAnnotationProperty(String uri) {
1352: checkProfileEntry(getProfile().ANNOTATION_PROPERTY(),
1353: "ANNOTATION_PROPERTY");
1354: return (AnnotationProperty) createOntResource(
1355: AnnotationProperty.class, getProfile()
1356: .ANNOTATION_PROPERTY(), uri);
1357: }
1358:
1359: /**
1360: * <p>
1361: * Answer a resource that represents an anonymous class description in this model. A new
1362: * anonymous resource of <code>rdf:type C</code>, where C is the class type from the
1363: * language profile.
1364: * </p>
1365: *
1366: * @return An anonymous Class resource.
1367: */
1368: public OntClass createClass() {
1369: checkProfileEntry(getProfile().CLASS(), "CLASS");
1370: return (OntClass) createOntResource(OntClass.class,
1371: getProfile().CLASS(), null);
1372: }
1373:
1374: /**
1375: * <p>
1376: * Answer a resource that represents a class description node in this model. If a resource
1377: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1378: * the updateable sub-graph of the ontology model.
1379: * </p>
1380: *
1381: * @param uri The uri for the class node, or null for an anonymous class.
1382: * @return A Class resource.
1383: */
1384: public OntClass createClass(String uri) {
1385: checkProfileEntry(getProfile().CLASS(), "CLASS");
1386: return (OntClass) createOntResource(OntClass.class,
1387: getProfile().CLASS(), uri);
1388: }
1389:
1390: /**
1391: * <p>Answer a resource representing the class that is the complement of the given argument class</p>
1392: * @param uri The URI of the new complement class, or null for an anonymous class description.
1393: * @param cls Resource denoting the class that the new class is a complement of
1394: * @return A complement class
1395: */
1396: public ComplementClass createComplementClass(String uri,
1397: Resource cls) {
1398: checkProfileEntry(getProfile().CLASS(), "CLASS");
1399: OntClass c = (OntClass) createOntResource(OntClass.class,
1400: getProfile().CLASS(), uri);
1401:
1402: checkProfileEntry(getProfile().COMPLEMENT_OF(), "COMPLEMENT_OF");
1403: // if the class that this class is a complement of is not specified, use owl:nothing or daml:nothing
1404: c.addProperty(getProfile().COMPLEMENT_OF(),
1405: (cls == null) ? getProfile().NOTHING() : cls);
1406:
1407: return (ComplementClass) c.as(ComplementClass.class);
1408: }
1409:
1410: /**
1411: * <p>Answer a resource representing the class that is the enumeration of the given list of individuals</p>
1412: * @param uri The URI of the new enumeration class, or null for an anonymous class description.
1413: * @param members An optional list of resources denoting the individuals in the enumeration
1414: * @return An enumeration class
1415: */
1416: public EnumeratedClass createEnumeratedClass(String uri,
1417: RDFList members) {
1418: checkProfileEntry(getProfile().CLASS(), "CLASS");
1419: OntClass c = (OntClass) createOntResource(OntClass.class,
1420: getProfile().CLASS(), uri);
1421:
1422: checkProfileEntry(getProfile().ONE_OF(), "ONE_OF");
1423: c.addProperty(getProfile().ONE_OF(),
1424: (members == null) ? createList() : members);
1425:
1426: return (EnumeratedClass) c.as(EnumeratedClass.class);
1427: }
1428:
1429: /**
1430: * <p>Answer a resource representing the class that is the union of the given list of class desctiptions</p>
1431: * @param uri The URI of the new union class, or null for an anonymous class description.
1432: * @param members A list of resources denoting the classes that comprise the union
1433: * @return A union class description
1434: */
1435: public UnionClass createUnionClass(String uri, RDFList members) {
1436: checkProfileEntry(getProfile().CLASS(), "CLASS");
1437: OntClass c = (OntClass) createOntResource(OntClass.class,
1438: getProfile().CLASS(), uri);
1439:
1440: checkProfileEntry(getProfile().UNION_OF(), "UNION_OF");
1441: c.addProperty(getProfile().UNION_OF(),
1442: (members == null) ? createList() : members);
1443:
1444: return (UnionClass) c.as(UnionClass.class);
1445: }
1446:
1447: /**
1448: * <p>Answer a resource representing the class that is the intersection of the given list of class descriptions.</p>
1449: * @param uri The URI of the new intersection class, or null for an anonymous class description.
1450: * @param members A list of resources denoting the classes that comprise the intersection
1451: * @return An intersection class description
1452: */
1453: public IntersectionClass createIntersectionClass(String uri,
1454: RDFList members) {
1455: checkProfileEntry(getProfile().CLASS(), "CLASS");
1456: OntClass c = (OntClass) createOntResource(OntClass.class,
1457: getProfile().CLASS(), uri);
1458:
1459: checkProfileEntry(getProfile().INTERSECTION_OF(),
1460: "INTERSECTION_OF");
1461: c.addProperty(getProfile().INTERSECTION_OF(),
1462: (members == null) ? createList() : members);
1463:
1464: return (IntersectionClass) c.as(IntersectionClass.class);
1465: }
1466:
1467: /**
1468: * <p>
1469: * Answer a resource that represents an anonymous property restriction in this model. A new
1470: * anonymous resource of <code>rdf:type R</code>, where R is the restriction type from the
1471: * language profile.
1472: * </p>
1473: *
1474: * @param p The property that is restricted by this restriction
1475: * @return An anonymous Restriction resource.
1476: */
1477: public Restriction createRestriction(Property p) {
1478: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1479: Restriction r = (Restriction) createOntResource(
1480: Restriction.class, getProfile().RESTRICTION(), null);
1481: if (p != null) {
1482: r.setOnProperty(p);
1483: }
1484:
1485: return r;
1486: }
1487:
1488: /**
1489: * <p>
1490: * Answer a resource that represents a property restriction in this model. If a resource
1491: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1492: * the updateable sub-graph of the ontology model.
1493: * </p>
1494: *
1495: * @param uri The uri for the restriction node, or null for an anonymous restriction.
1496: * @param p The property that is restricted by this restriction
1497: * @return A Restriction resource.
1498: */
1499: public Restriction createRestriction(String uri, Property p) {
1500: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1501: Restriction r = (Restriction) createOntResource(
1502: Restriction.class, getProfile().RESTRICTION(), uri);
1503: if (p != null) {
1504: r.setOnProperty(p);
1505: }
1506:
1507: return r;
1508: }
1509:
1510: /**
1511: * <p>Answer a class description defined as the class of those individuals that have the given
1512: * resource as the value of the given property</p>
1513: *
1514: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1515: * should be the normal case)
1516: * @param prop The property the restriction applies to
1517: * @param value The value of the property, as a resource or RDF literal
1518: * @return A new resource representing a has-value restriction
1519: */
1520: public HasValueRestriction createHasValueRestriction(String uri,
1521: Property prop, RDFNode value) {
1522: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1523: Restriction r = (Restriction) createOntResource(
1524: Restriction.class, getProfile().RESTRICTION(), uri);
1525:
1526: if (prop == null || value == null) {
1527: throw new IllegalArgumentException(
1528: "Cannot create hasValueRestriction with a null property or value");
1529: }
1530:
1531: checkProfileEntry(getProfile().HAS_VALUE(), "HAS_VALUE");
1532: r.addProperty(getProfile().ON_PROPERTY(), prop);
1533: r.addProperty(getProfile().HAS_VALUE(), value);
1534:
1535: return (HasValueRestriction) r.as(HasValueRestriction.class);
1536: }
1537:
1538: /**
1539: * <p>Answer a class description defined as the class of those individuals that have at least
1540: * one property with a value belonging to the given class</p>
1541: *
1542: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1543: * should be the normal case)
1544: * @param prop The property the restriction applies to
1545: * @param cls The class to which at least one value of the property belongs
1546: * @return A new resource representing a some-values-from restriction
1547: */
1548: public SomeValuesFromRestriction createSomeValuesFromRestriction(
1549: String uri, Property prop, Resource cls) {
1550: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1551: Restriction r = (Restriction) createOntResource(
1552: Restriction.class, getProfile().RESTRICTION(), uri);
1553:
1554: if (prop == null || cls == null) {
1555: throw new IllegalArgumentException(
1556: "Cannot create someValuesFromRestriction with a null property or class");
1557: }
1558:
1559: checkProfileEntry(getProfile().SOME_VALUES_FROM(),
1560: "SOME_VALUES_FROM");
1561: r.addProperty(getProfile().ON_PROPERTY(), prop);
1562: r.addProperty(getProfile().SOME_VALUES_FROM(), cls);
1563:
1564: return (SomeValuesFromRestriction) r
1565: .as(SomeValuesFromRestriction.class);
1566: }
1567:
1568: /**
1569: * <p>Answer a class description defined as the class of those individuals for which all values
1570: * of the given property belong to the given class</p>
1571: *
1572: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1573: * should be the normal case)
1574: * @param prop The property the restriction applies to
1575: * @param cls The class to which any value of the property belongs
1576: * @return A new resource representing an all-values-from restriction
1577: */
1578: public AllValuesFromRestriction createAllValuesFromRestriction(
1579: String uri, Property prop, Resource cls) {
1580: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1581: Restriction r = (Restriction) createOntResource(
1582: Restriction.class, getProfile().RESTRICTION(), uri);
1583:
1584: if (prop == null || cls == null) {
1585: throw new IllegalArgumentException(
1586: "Cannot create allValuesFromRestriction with a null property or class");
1587: }
1588:
1589: checkProfileEntry(getProfile().ALL_VALUES_FROM(),
1590: "ALL_VALUES_FROM");
1591: r.addProperty(getProfile().ON_PROPERTY(), prop);
1592: r.addProperty(getProfile().ALL_VALUES_FROM(), cls);
1593:
1594: return (AllValuesFromRestriction) r
1595: .as(AllValuesFromRestriction.class);
1596: }
1597:
1598: /**
1599: * <p>Answer a class description defined as the class of those individuals that have exactly
1600: * the given number of values for the given property.</p>
1601: *
1602: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1603: * should be the normal case)
1604: * @param prop The property the restriction applies to
1605: * @param cardinality The exact cardinality of the property
1606: * @return A new resource representing a has-value restriction
1607: */
1608: public CardinalityRestriction createCardinalityRestriction(
1609: String uri, Property prop, int cardinality) {
1610: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1611: Restriction r = (Restriction) createOntResource(
1612: Restriction.class, getProfile().RESTRICTION(), uri);
1613:
1614: if (prop == null) {
1615: throw new IllegalArgumentException(
1616: "Cannot create cardinalityRestriction with a null property");
1617: }
1618:
1619: checkProfileEntry(getProfile().CARDINALITY(), "CARDINALITY");
1620: r.addProperty(getProfile().ON_PROPERTY(), prop);
1621: r.addProperty(getProfile().CARDINALITY(),
1622: createTypedLiteral(cardinality));
1623:
1624: return (CardinalityRestriction) r
1625: .as(CardinalityRestriction.class);
1626: }
1627:
1628: /**
1629: * <p>Answer a class description defined as the class of those individuals that have at least
1630: * the given number of values for the given property.</p>
1631: *
1632: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1633: * should be the normal case)
1634: * @param prop The property the restriction applies to
1635: * @param cardinality The minimum cardinality of the property
1636: * @return A new resource representing a min-cardinality restriction
1637: */
1638: public MinCardinalityRestriction createMinCardinalityRestriction(
1639: String uri, Property prop, int cardinality) {
1640: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1641: Restriction r = (Restriction) createOntResource(
1642: Restriction.class, getProfile().RESTRICTION(), uri);
1643:
1644: if (prop == null) {
1645: throw new IllegalArgumentException(
1646: "Cannot create minCardinalityRestriction with a null property");
1647: }
1648:
1649: checkProfileEntry(getProfile().MIN_CARDINALITY(),
1650: "MIN_CARDINALITY");
1651: r.addProperty(getProfile().ON_PROPERTY(), prop);
1652: r.addProperty(getProfile().MIN_CARDINALITY(),
1653: createTypedLiteral(cardinality));
1654:
1655: return (MinCardinalityRestriction) r
1656: .as(MinCardinalityRestriction.class);
1657: }
1658:
1659: /**
1660: * <p>Answer a class description defined as the class of those individuals that have at most
1661: * the given number of values for the given property.</p>
1662: *
1663: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1664: * should be the normal case)
1665: * @param prop The property the restriction applies to
1666: * @param cardinality The maximum cardinality of the property
1667: * @return A new resource representing a mas-cardinality restriction
1668: */
1669: public MaxCardinalityRestriction createMaxCardinalityRestriction(
1670: String uri, Property prop, int cardinality) {
1671: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1672: Restriction r = (Restriction) createOntResource(
1673: Restriction.class, getProfile().RESTRICTION(), uri);
1674:
1675: if (prop == null) {
1676: throw new IllegalArgumentException(
1677: "Cannot create maxCardinalityRestriction with a null property");
1678: }
1679:
1680: checkProfileEntry(getProfile().MAX_CARDINALITY(),
1681: "MAX_CARDINALITY");
1682: r.addProperty(getProfile().ON_PROPERTY(), prop);
1683: r.addProperty(getProfile().MAX_CARDINALITY(),
1684: createTypedLiteral(cardinality));
1685:
1686: return (MaxCardinalityRestriction) r
1687: .as(MaxCardinalityRestriction.class);
1688: }
1689:
1690: /**
1691: * <p>Answer a class description defined as the class of those individuals that have at most
1692: * the given number of values for the given property, all values of which belong to the given
1693: * class.</p>
1694: *
1695: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1696: * should be the normal case)
1697: * @param prop The property the restriction applies to
1698: * @param cardinality The maximum cardinality of the property
1699: * @param cls The class to which all values of the restricted property should belong
1700: * @return A new resource representing a mas-cardinality restriction
1701: */
1702: public MaxCardinalityQRestriction createMaxCardinalityQRestriction(
1703: String uri, Property prop, int cardinality, OntClass cls) {
1704: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1705: checkProfileEntry(getProfile().ON_PROPERTY(), "ON_PROPERTY");
1706: checkProfileEntry(getProfile().MAX_CARDINALITY_Q(),
1707: "MAX_CARDINALITY_Q");
1708: checkProfileEntry(getProfile().HAS_CLASS_Q(), "HAS_CLASS_Q");
1709:
1710: if (prop == null) {
1711: throw new IllegalArgumentException(
1712: "Cannot create MaxCardinalityQRestriction with a null property");
1713: }
1714: if (cls == null) {
1715: throw new IllegalArgumentException(
1716: "Cannot create MaxCardinalityQRestriction with a null class");
1717: }
1718:
1719: Restriction r = (Restriction) createOntResource(
1720: Restriction.class, getProfile().RESTRICTION(), uri);
1721:
1722: r.addProperty(getProfile().ON_PROPERTY(), prop);
1723: r.addProperty(getProfile().MAX_CARDINALITY_Q(),
1724: createTypedLiteral(cardinality));
1725: r.addProperty(getProfile().HAS_CLASS_Q(), cls);
1726:
1727: return (MaxCardinalityQRestriction) r
1728: .as(MaxCardinalityQRestriction.class);
1729: }
1730:
1731: /**
1732: * <p>Answer a class description defined as the class of those individuals that have at least
1733: * the given number of values for the given property, all values of which belong to the given
1734: * class.</p>
1735: *
1736: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1737: * should be the normal case)
1738: * @param prop The property the restriction applies to
1739: * @param cardinality The minimun cardinality of the property
1740: * @param cls The class to which all values of the restricted property should belong
1741: * @return A new resource representing a mas-cardinality restriction
1742: */
1743: public MinCardinalityQRestriction createMinCardinalityQRestriction(
1744: String uri, Property prop, int cardinality, OntClass cls) {
1745: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1746: checkProfileEntry(getProfile().ON_PROPERTY(), "ON_PROPERTY");
1747: checkProfileEntry(getProfile().MIN_CARDINALITY_Q(),
1748: "MIN_CARDINALITY_Q");
1749: checkProfileEntry(getProfile().HAS_CLASS_Q(), "HAS_CLASS_Q");
1750:
1751: if (prop == null) {
1752: throw new IllegalArgumentException(
1753: "Cannot create MinCardinalityQRestriction with a null property");
1754: }
1755: if (cls == null) {
1756: throw new IllegalArgumentException(
1757: "Cannot create MinCardinalityQRestriction with a null class");
1758: }
1759:
1760: Restriction r = (Restriction) createOntResource(
1761: Restriction.class, getProfile().RESTRICTION(), uri);
1762:
1763: r.addProperty(getProfile().ON_PROPERTY(), prop);
1764: r.addProperty(getProfile().MIN_CARDINALITY_Q(),
1765: createTypedLiteral(cardinality));
1766: r.addProperty(getProfile().HAS_CLASS_Q(), cls);
1767:
1768: return (MinCardinalityQRestriction) r
1769: .as(MinCardinalityQRestriction.class);
1770: }
1771:
1772: /**
1773: * <p>Answer a class description defined as the class of those individuals that have exactly
1774: * the given number of values for the given property, all values of which belong to the given
1775: * class.</p>
1776: *
1777: * @param uri The optional URI for the restriction, or null for an anonymous restriction (which
1778: * should be the normal case)
1779: * @param prop The property the restriction applies to
1780: * @param cardinality The cardinality of the property
1781: * @param cls The class to which all values of the restricted property should belong
1782: * @return A new resource representing a mas-cardinality restriction
1783: */
1784: public CardinalityQRestriction createCardinalityQRestriction(
1785: String uri, Property prop, int cardinality, OntClass cls) {
1786: checkProfileEntry(getProfile().RESTRICTION(), "RESTRICTION");
1787: checkProfileEntry(getProfile().ON_PROPERTY(), "ON_PROPERTY");
1788: checkProfileEntry(getProfile().CARDINALITY_Q(), "CARDINALITY_Q");
1789: checkProfileEntry(getProfile().HAS_CLASS_Q(), "HAS_CLASS_Q");
1790:
1791: if (prop == null) {
1792: throw new IllegalArgumentException(
1793: "Cannot create CardinalityQRestriction with a null property");
1794: }
1795: if (cls == null) {
1796: throw new IllegalArgumentException(
1797: "Cannot create CardinalityQRestriction with a null class");
1798: }
1799:
1800: Restriction r = (Restriction) createOntResource(
1801: Restriction.class, getProfile().RESTRICTION(), uri);
1802:
1803: r.addProperty(getProfile().ON_PROPERTY(), prop);
1804: r.addProperty(getProfile().CARDINALITY_Q(),
1805: createTypedLiteral(cardinality));
1806: r.addProperty(getProfile().HAS_CLASS_Q(), cls);
1807:
1808: return (CardinalityQRestriction) r
1809: .as(CardinalityQRestriction.class);
1810: }
1811:
1812: /**
1813: * <p>Answer a data range defined as the given set of concrete data values. DataRange resources
1814: * are necessarily bNodes.</p>
1815: *
1816: * @param literals An iterator over a set of literals that will be the members of the data range,
1817: * or null to define an empty data range
1818: * @return A new data range containing the given literals as permissible values
1819: */
1820: public DataRange createDataRange(RDFList literals) {
1821: checkProfileEntry(getProfile().DATARANGE(), "DATARANGE");
1822: DataRange d = (DataRange) createOntResource(DataRange.class,
1823: getProfile().DATARANGE(), null);
1824:
1825: checkProfileEntry(getProfile().ONE_OF(), "ONE_OF");
1826: d.addProperty(getProfile().ONE_OF(),
1827: (literals == null) ? createList() : literals);
1828:
1829: return d;
1830: }
1831:
1832: /**
1833: * <p>
1834: * Answer a new, anonymous node representing the fact that a given set of classes are all
1835: * pair-wise distinct. <code>AllDifferent</code> is a feature of OWL only, and is something
1836: * of an anomoly in that it exists only to give a place to anchor the <code>distinctMembers</code>
1837: * property, which is the actual expression of the fact.
1838: * </p>
1839: *
1840: * @return A new AllDifferent resource
1841: */
1842: public AllDifferent createAllDifferent() {
1843: return createAllDifferent(null);
1844: }
1845:
1846: /**
1847: * <p>
1848: * Answer a new, anonymous node representing the fact that a given set of classes are all
1849: * pair-wise distinct. <code>AllDifferent</code> is a feature of OWL only, and is something
1850: * of an anomoly in that it exists only to give a place to anchor the <code>distinctMembers</code>
1851: * property, which is the actual expression of the fact.
1852: * </p>
1853: * @param differentMembers A list of the class expressions that denote a set of mutually disjoint classes
1854: * @return A new AllDifferent resource
1855: */
1856: public AllDifferent createAllDifferent(RDFList differentMembers) {
1857: checkProfileEntry(getProfile().ALL_DIFFERENT(), "ALL_DIFFERENT");
1858: AllDifferent ad = (AllDifferent) createOntResource(
1859: AllDifferent.class, getProfile().ALL_DIFFERENT(), null);
1860:
1861: ad.setDistinctMembers((differentMembers == null) ? createList()
1862: : differentMembers);
1863:
1864: return ad;
1865: }
1866:
1867: /**
1868: * <p>
1869: * Answer a resource that represents a generic ontology node in this model. If a resource
1870: * with the given uri exists in the model, it will be re-used. If not, a new one is created in
1871: * the updateable sub-graph of the ontology model.
1872: * </p>
1873: * <p>
1874: * This is a generic method for creating any known ontology value. The selector that determines
1875: * which resource to create is the same as as the argument to the {@link RDFNode#as as()}
1876: * method: the Java class object of the desired abstraction. For example, to create an
1877: * ontology class via this mechanism, use:
1878: * <code><pre>
1879: * OntClass c = (OntClass) myModel.createOntResource( OntClass.class, null,
1880: * "http://example.org/ex#Parrot" );
1881: * </pre></code>
1882: * </p>
1883: *
1884: * @param javaClass The Java class object that represents the ontology abstraction to create
1885: * @param rdfType Optional resource denoting the ontology class to which an individual or
1886: * axiom belongs, if that is the type of resource being created.
1887: * @param uri The uri for the ontology resource, or null for an anonymous resource.
1888: * @return An ontology resource, of the type specified by the <code>javaClass</code>
1889: */
1890: public OntResource createOntResource(Class javaClass,
1891: Resource rdfType, String uri) {
1892: return (OntResource) getResourceWithType(uri, rdfType).as(
1893: javaClass);
1894: }
1895:
1896: /**
1897: * <p>Answer a resource presenting the {@link OntResource} facet, which has the
1898: * given URI.</p>
1899: * @param uri The URI of the resource, or null for an anonymous resource (aka bNode)
1900: * @return An OntResource with the given URI
1901: */
1902: public OntResource createOntResource(String uri) {
1903: return (OntResource) getResource(uri).as(OntResource.class);
1904: }
1905:
1906: /**
1907: * <p>Answer a new empty list. This method overrides the list create method in ModelCom,
1908: * to allow both DAML and RDFS lists to be created.</p>
1909: * @return An RDF-encoded list of no elements, using the current language profile
1910: */
1911: public RDFList createList() {
1912: Resource list = getResource(getProfile().NIL().getURI());
1913:
1914: return (RDFList) list.as(RDFList.class);
1915: }
1916:
1917: /**
1918: * <p>
1919: * Answer the language profile (for example, OWL or DAML+OIL) that this model is
1920: * working to.
1921: * </p>
1922: *
1923: * @return A language profile
1924: */
1925: public Profile getProfile() {
1926: return m_spec.getProfile();
1927: }
1928:
1929: /**
1930: * <p>Determine which models this model imports (by looking for, for example,
1931: * <code>owl:imports</code> statements, and load each of those models as an
1932: * import. A check is made to determine if a model has already been imported,
1933: * if so, the import is ignored. Thus this method is safe against circular
1934: * sets of import statements. Note that actual implementation is delegated to
1935: * the associated {@link OntDocumentManager}.
1936: */
1937: public void loadImports() {
1938: // load the imports closure, according to the policies in my document manager
1939: getDocumentManager().loadImports(this );
1940: }
1941:
1942: /**
1943: * <p>
1944: * Answer true if this model has had the given URI document imported into it. This is
1945: * important to know since an import only occurs once, and we also want to be able to
1946: * detect cycles of imports.
1947: * </p>
1948: *
1949: * @param uri An ontology URI
1950: * @return True if the document corresponding to the URI has been successfully loaded
1951: * into this model
1952: */
1953: public boolean hasLoadedImport(String uri) {
1954: return m_imported.contains(uri);
1955: }
1956:
1957: /**
1958: * <p>
1959: * Record that this model has now imported the document with the given
1960: * URI, so that it will not be re-imported in the future.
1961: * </p>
1962: *
1963: * @param uri A document URI that has now been imported into the model.
1964: */
1965: public void addLoadedImport(String uri) {
1966: m_imported.add(uri);
1967: }
1968:
1969: /**
1970: * <p>
1971: * Record that this model no longer imports the document with the given
1972: * URI.
1973: * </p>
1974: *
1975: * @param uri A document URI that is no longer imported into the model.
1976: */
1977: public void removeLoadedImport(String uri) {
1978: m_imported.remove(uri);
1979: }
1980:
1981: /**
1982: * <p>
1983: * Answer a list of the imported URI's in this ontology model. Detection of <code>imports</code>
1984: * statments will be according to the local language profile
1985: * </p>
1986: *
1987: * @return The imported ontology URI's as a set. Note that since the underlying graph is
1988: * not ordered, the order of values in the list in successive calls to this method is
1989: * not guaranteed to be preserved.
1990: */
1991: public Set listImportedOntologyURIs() {
1992: return listImportedOntologyURIs(false);
1993: }
1994:
1995: /**
1996: * <p>
1997: * Answer a list of the imported URI's in this ontology model, and optionally in the closure
1998: * of this model's imports. Detection of <code>imports</code>
1999: * statments will be according to the local language profile. Note that, in order to allow this
2000: * method to be called during the imports closure process, we <b>only query the base model</b>,
2001: * thus side-stepping the any attached reasoner.
2002: * </p>
2003: * @param closure If true, the set of uri's returned will include not only those directly
2004: * imported by this model, but those imported by the model's imports transitively.
2005: * @return The imported ontology URI's as a list. Note that since the underlying graph is
2006: * not ordered, the order of values in the list in successive calls to this method is
2007: * not guaranteed to be preserved.
2008: */
2009: public Set listImportedOntologyURIs(boolean closure) {
2010: Set results = new HashSet();
2011: List queue = new ArrayList();
2012: queue.add(getBaseModel());
2013:
2014: while (!queue.isEmpty()) {
2015: Model m = (Model) queue.remove(0);
2016:
2017: // list the ontology nodes
2018: if (getProfile().ONTOLOGY() != null
2019: && getProfile().IMPORTS() != null) {
2020: StmtIterator i = m.listStatements(null, getProfile()
2021: .IMPORTS(), (RDFNode) null);
2022: while (i.hasNext()) {
2023: Statement s = i.nextStatement();
2024: String uri = s.getResource().getURI();
2025:
2026: if (!results.contains(uri)) {
2027: // this is a new uri, so we add it
2028: results.add(uri);
2029:
2030: // and push the model on the stack if we know it
2031: Model mi = getDocumentManager().getModel(uri);
2032: if (closure && mi != null
2033: && !queue.contains(mi)) {
2034: queue.add(mi);
2035: }
2036: }
2037: }
2038: }
2039: }
2040:
2041: return results;
2042: }
2043:
2044: /**
2045: * <p>
2046: * Answer the model maker associated with this model (used for constructing the
2047: * constituent models of the imports closure).
2048: * </p>
2049: *
2050: * @return The local graph factory
2051: */
2052: public ModelMaker getImportModelMaker() {
2053: return m_spec.getImportModelMaker();
2054: }
2055:
2056: /**
2057: @deprecated use getImportModelMaker instead.
2058: */
2059: public ModelMaker getModelMaker() {
2060: return getImportModelMaker();
2061: }
2062:
2063: /**
2064: * <p>If this OntModel is presenting an OWL model, answer the minimum OWL language
2065: * level that the constructs
2066: * used in this model lie entirely within. The three possible return values are
2067: * {@link OWL#FULL_LANG} for OWL-full,
2068: * {@link OWL#DL_LANG} for OWL-DL or
2069: * {@link OWL#LITE_LANG} for OWL-lite.
2070: * Note that these URI's are <strong>not</strong> officially sanctioned by the WebOnt
2071: * working group. For unknown reasons, the working group chose not to assign official
2072: * URI's to represent the different OWL language levels. There is a slim chance that this
2073: * may change in future, in which case these return values will change apropriately.
2074: * In addition, the given <code>problems</problems> list, if non-null, will be filled with the syntax
2075: * problems detected by the syntax checker (<code> com.hp.hpl.jena.ontology.tidy.Checker</code>).
2076: * </p>
2077: * <p>
2078: * The Jena OWL syntax checker will normally list as problems those constructs used in
2079: * this model that are in OWL Full but not permitted in OWL DL. The exception to this
2080: * is if the {@linkplain #getProfile() language profile} for this model is
2081: * {@linkplain OWLLiteProfile OWL Lite}, then the syntax checker will
2082: * test for constructs that lie in OWL-DL or OWL-Full and hence outside in OWL-Lite.
2083: * </p>
2084: *
2085: * @param problems A list that, if non-null, will have the various problems discovered by the OWL syntax
2086: * checker added to it.
2087: * @return A resource denoting the minimum OWL language level for this model
2088: * @exception OntologyException if this model is not an OWL model
2089: */
2090: public Resource getOWLLanguageLevel(List problems) {
2091: initSyntaxCheckerClass();
2092: try {
2093: return ((OWLSyntaxChecker) owlSyntaxCheckerClass
2094: .newInstance()).getOWLLanguageLevel(this , problems);
2095: } catch (InstantiationException e) {
2096: throw new BrokenException("Syntax Checker misconfigured: ",
2097: e);
2098: } catch (IllegalAccessException e) {
2099: throw new BrokenException("Syntax Checker misconfigured: ",
2100: e);
2101: }
2102: }
2103:
2104: /**
2105: * <p>Read statements into the model from the given source, and then load
2106: * imported ontologies (according to the document manager policy).</p>
2107: * @param uri URI to read from, may be mapped to a local source by the document manager
2108: */
2109: public Model read(String uri) {
2110: return read(uri, null);
2111: }
2112:
2113: /**
2114: * <p>Read statements into the model from the given source, and then load
2115: * imported ontologies (according to the document manager policy).</p>
2116: * @param reader An input reader
2117: * @param base The base URI
2118: */
2119: public Model read(Reader reader, String base) {
2120: super .read(reader, base);
2121:
2122: loadImports();
2123: rebind();
2124: return this ;
2125: }
2126:
2127: /**
2128: * <p>Read statements into the model from the given source, and then load
2129: * imported ontologies (according to the document manager policy).</p>
2130: * @param reader An input stream
2131: * @param base The base URI
2132: */
2133: public Model read(InputStream reader, String base) {
2134: super .read(reader, base);
2135:
2136: loadImports();
2137: rebind();
2138: return this ;
2139: }
2140:
2141: /**
2142: * <p>Read statements into the model from the given source, and then load
2143: * imported ontologies (according to the document manager policy).</p>
2144: * @param uri URI to read from, may be mapped to a local source by the document manager
2145: * @param syntax The source syntax
2146: * @return This model, to allow chaining calls
2147: */
2148: public Model read(String uri, String syntax) {
2149: return read(uri, uri, syntax);
2150: }
2151:
2152: /**
2153: * <p>Read statements into the model from the given source, and then load
2154: * imported ontologies (according to the document manager policy).</p>
2155: * @param uri URI to read from, may be mapped to a local source by the document manager
2156: * @param base The base URI for this model
2157: * @param syntax The source syntax
2158: * @return This model, to allow chaining calls
2159: */
2160: public Model read(String uri, String base, String syntax) {
2161: // we don't want to load this document again if imported by one of the imports
2162: if (s_log.isDebugEnabled()) {
2163: s_log.debug("Noting already loaded import URI " + uri);
2164: }
2165: addLoadedImport(uri);
2166:
2167: OntDocumentManager odm = getDocumentManager();
2168:
2169: String sourceURL = odm.doAltURLMapping(uri);
2170:
2171: // invoke the read hook from the ODM
2172: String source = odm.getReadHook().beforeRead(this , sourceURL,
2173: odm);
2174: if (source == null) {
2175: s_log
2176: .warn("ReadHook returned null, so skipping assuming previous value: "
2177: + sourceURL);
2178: source = sourceURL;
2179: } else {
2180: // now we can actually do the read
2181: super .read(source, base, syntax);
2182: }
2183:
2184: // the post read hook
2185: odm.getReadHook().afterRead(this , source, odm);
2186:
2187: // cache this model against the public uri (if caching enabled)
2188: getDocumentManager().addModel(uri, this );
2189:
2190: loadImports();
2191: rebind();
2192: return this ;
2193: }
2194:
2195: /**
2196: * <p>Read statements into the model from the given source, and then load
2197: * imported ontologies (according to the document manager policy).</p>
2198: * @param reader An input reader
2199: * @param base The base URI
2200: * @param syntax The source syntax
2201: * @return This model, to allow chaining calls
2202: */
2203: public Model read(Reader reader, String base, String syntax) {
2204: super .read(reader, base, syntax);
2205:
2206: loadImports();
2207: rebind();
2208: return this ;
2209: }
2210:
2211: /**
2212: * <p>Read statements into the model from the given source, and then load
2213: * imported ontologies (according to the document manager policy).</p>
2214: * @param reader An input stream
2215: * @param base The base URI
2216: * @param syntax The source syntax
2217: * @return This model, to allow chaining calls
2218: */
2219: public Model read(InputStream reader, String base, String syntax) {
2220: super .read(reader, base, syntax);
2221:
2222: loadImports();
2223: rebind();
2224: return this ;
2225: }
2226:
2227: /**
2228: * <p>
2229: * Answer the sub-graphs of this model. A sub-graph is defined as a graph that
2230: * is used to contain the triples from an imported document.
2231: * </p>
2232: *
2233: * @return A list of sub graphs for this ontology model
2234: */
2235: public List getSubGraphs() {
2236: return getUnionGraph().getSubGraphs();
2237: }
2238:
2239: /**
2240: * <p>Answer an iterator over the ontologies that this ontology imports,
2241: * each of which will have been wrapped as an ontology model using the same
2242: * {@link OntModelSpec} as this model. If this model has no imports,
2243: * the iterator will be non-null but will not have any values.</p>
2244: * @return An iterator, each value of which will be an <code>OntModel</code>
2245: * representing an imported ontology.
2246: * @deprecated This method has been re-named to <code>listSubModels</code>,
2247: * but note that to obtain the same behaviour as <code>listImportedModels</code>
2248: * from Jena 2.4 and earlier, callers should invoke {@link #listSubModels(boolean)}
2249: * with parameter <code>true</code>.
2250: * @see #listSubModels()
2251: * @see #listSubModels(boolean)
2252: */
2253: public ExtendedIterator listImportedModels() {
2254: return listSubModels(true);
2255: }
2256:
2257: /**
2258: * <p>Answer an iterator over the ontology models that are sub-models of
2259: * this model. Sub-models are used, for example, to represent composite
2260: * documents such as the imports of a model. So if ontology A imports
2261: * ontologies B and C, each of B and C will be available as one of
2262: * the sub-models of the model containing A. This method replaces the
2263: * older {@link #listImportedModels}. Note that to fully replicate
2264: * the behaviour of <code>listImportedModels</code>, the
2265: * <code>withImports</code> flag must be set to true. Each model
2266: * returned by this method will have been wrapped as an ontology model using the same
2267: * {@link OntModelSpec} as this model. If this model has no sub-models,
2268: * the returned iterator will be non-null but will not have any values.</p>
2269: *
2270: * @param withImports If true, each sub-model returned by this method
2271: * will also include its import models. So if model A imports D, and D
2272: * imports D, when called with <code>withImports</code> set to true, the
2273: * return value for <code>modelA.listSubModels(true)</code> will be an
2274: * iterator, whose only value is a model for D, and that model will contain
2275: * a sub-model representing the import of E. If <code>withImports</code>
2276: * is false, E will not be included as a sub-model of D.
2277: * @return An iterator, each value of which will be an <code>OntModel</code>
2278: * representing a sub-model of this ontology.
2279: */
2280: public ExtendedIterator listSubModels(final boolean withImports) {
2281: ExtendedIterator i = WrappedIterator.create(getSubGraphs()
2282: .iterator());
2283:
2284: return i.mapWith(new Map1() {
2285: public Object map1(Object o) {
2286: Model base = ModelFactory
2287: .createModelForGraph((Graph) o);
2288: OntModel om = new OntModelImpl(m_spec, base,
2289: withImports);
2290: return om;
2291: }
2292: });
2293: }
2294:
2295: /**
2296: * <p>Answer an iterator over the ontology models that are sub-models of
2297: * this model. Sub-models are used, for example, to represent composite
2298: * documents such as the imports of a model. So if ontology A imports
2299: * ontologies B and C, each of B and C will be available as one of
2300: * the sub-models of the model containing A.
2301: * <strong>Important note on behaviour change:</strong> please see
2302: * the comment on {@link #listSubModels(boolean)} for explanation
2303: * of the <code>withImports</code> flag. This zero-argument form
2304: * of <code>listSubModels</code> sets <code>withImports</code> to
2305: * false, so the returned models will not themselves contain imports.
2306: * This behaviour differs from the zero-argument method
2307: * {@link #listImportedModels()} in Jena 2.4 an earlier.</p>
2308: * @return An iterator, each value of which will be an <code>OntModel</code>
2309: * representing a sub-model of this ontology.
2310: * @see #listSubModels(boolean)
2311: */
2312: public ExtendedIterator listSubModels() {
2313: return listSubModels(false);
2314: }
2315:
2316: /**
2317: * <p>Answer the number of sub-models of this model, not including the
2318: * base model.</p>
2319: * @return The number of sub-models, ≥ zero.
2320: */
2321: public int countSubModels() {
2322: int count = 0;
2323: for (Iterator i = getSubGraphs().iterator(); i.hasNext();) {
2324: count++;
2325: i.next();
2326: }
2327: return count;
2328: }
2329:
2330: /**
2331: * <p>Answer an <code>OntModel</code> representing the imported ontology
2332: * with the given URI. If an ontology with that URI has not been imported,
2333: * answer null.</p>
2334: * @param uri The URI of an ontology that may have been imported into the
2335: * ontology represented by this model
2336: * @return A model representing the imported ontology with the given URI, or
2337: * null.
2338: */
2339: public OntModel getImportedModel(String uri) {
2340: if (listImportedOntologyURIs(true).contains(uri)) {
2341: Model mi = getDocumentManager().getModel(uri);
2342:
2343: if (mi != null) {
2344: if (mi instanceof OntModel) {
2345: // already a suitable ont model
2346: return (OntModel) mi;
2347: } else {
2348: // not in ont-model clothing yet, so re-wrap
2349: return ModelFactory.createOntologyModel(m_spec, mi);
2350: }
2351: }
2352: }
2353:
2354: return null;
2355: }
2356:
2357: /**
2358: * <p>
2359: * Answer the base-graph of this model. The base-graph is the graph that
2360: * contains the triples read from the source document for this ontology.
2361: * </p>
2362: *
2363: * @return The base-graph for this ontology model
2364: */
2365: public Graph getBaseGraph() {
2366: return getUnionGraph().getBaseGraph();
2367: }
2368:
2369: /**
2370: * <p>
2371: * Answer the base model of this model. The base model is the model wrapping
2372: * the graph that contains the triples read from the source document for this
2373: * ontology. It is therefore the model that will be updated if statements are
2374: * added to a model that is built from a union of documents (via the
2375: * <code>imports</code> statements in the source document).
2376: * </p>
2377: *
2378: * @return The base model for this ontology model
2379: */
2380: public Model getBaseModel() {
2381: return ModelFactory.createModelForGraph(getBaseGraph());
2382: }
2383:
2384: /**
2385: * <p>
2386: * Add the given model as one of the sub-models of the enclosed ontology union model.
2387: * <strong>Note</strong> that if <code>model</code> is a composite model (i.e. an
2388: * {@link OntModel} or {@link InfModel}), the model and all of its submodels will
2389: * be added to the union of sub-models of this model. If this is <strong>not</strong> required,
2390: * callers should explicitly add only the base model:
2391: * </p>
2392: * <pre>
2393: * parent.addSubModel( child.getBaseModel() );
2394: * </pre>
2395: *
2396: * @param model A sub-model to add
2397: */
2398: public void addSubModel(Model model) {
2399: addSubModel(model, true);
2400: }
2401:
2402: /**
2403: * <p>
2404: * Add the given model as one of the sub-models of the enclosed ontology union model.
2405: * <strong>Note</strong> that if <code>model</code> is a composite model (i.e. an
2406: * {@link OntModel} or {@link InfModel}), the model and all of its submodels will
2407: * be added to the union of sub-models of this model. If this is <strong>not</strong> required,
2408: * callers should explicitly add only the base model:
2409: * </p>
2410: * <pre>
2411: * parent.addSubModel( child.getBaseModel(), true );
2412: * </pre>
2413: *
2414: * @param model A sub-model to add
2415: * @param rebind If true, rebind any associated inferencing engine to the new data (which
2416: * may be an expensive operation)
2417: */
2418: public void addSubModel(Model model, boolean rebind) {
2419: getUnionGraph().addGraph(model.getGraph());
2420: if (rebind) {
2421: rebind();
2422: }
2423: }
2424:
2425: /**
2426: * <p>
2427: * Remove the given model as one of the sub-models of the enclosed ontology union model. Will
2428: * cause the associated infererence engine (if any) to update, so this may be
2429: * an expensive operation in some cases.
2430: * </p>
2431: *
2432: * @param model A sub-model to remove
2433: * @see #addSubModel( Model, boolean )
2434: */
2435: public void removeSubModel(Model model) {
2436: removeSubModel(model, true);
2437: }
2438:
2439: /**
2440: * <p>
2441: * Remove the given model as one of the sub-models of the enclosed ontology union model.
2442: * </p>
2443: *
2444: * @param model A sub-model to remove
2445: * @param rebind If true, rebind any associated inferencing engine to the new data (which
2446: * may be an expensive operation)
2447: */
2448: public void removeSubModel(Model model, boolean rebind) {
2449: Graph subG = model.getGraph();
2450: getUnionGraph().removeGraph(subG);
2451:
2452: // note that it may be the base graph of the given model that was added
2453: // originally
2454: if (subG instanceof MultiUnion) {
2455: // we need to get the base graph when removing a ontmodel
2456: getUnionGraph().removeGraph(
2457: ((MultiUnion) subG).getBaseGraph());
2458: }
2459:
2460: if (rebind) {
2461: rebind();
2462: }
2463: }
2464:
2465: /**
2466: * <p>Answer true if the given node is a member of the base model of this ontology model.
2467: * This is an important distiction, because only the base model receives updates when the
2468: * ontology model is updated. Thus, removing properties of a resource that is not in the base
2469: * model will not actually side-effect the overall model.</p>
2470: * @param node An RDF node (Resource, Property or Literal) to test
2471: * @return True if the given node is from the base model
2472: */
2473: public boolean isInBaseModel(RDFNode node) {
2474: Node n = node.asNode();
2475: Graph b = getBaseGraph();
2476: return b.contains(n, Node.ANY, Node.ANY)
2477: || b.contains(Node.ANY, n, Node.ANY)
2478: || b.contains(Node.ANY, Node.ANY, n);
2479: }
2480:
2481: /**
2482: * <p>Answer true if the given statement is defined in the base model of this ontology model.
2483: * This is an important distiction, because only the base model receives updates when the
2484: * ontology model is updated. Thus, removing a statement that is not in the base
2485: * model will not actually side-effect the overall model.</p>
2486: * @param stmt A statement to test
2487: * @return True if the given statement is from the base model
2488: */
2489: public boolean isInBaseModel(Statement stmt) {
2490: Node s = stmt.getSubject().asNode();
2491: Node p = stmt.getPredicate().asNode();
2492: Node o = stmt.getObject().asNode();
2493: Graph b = getBaseGraph();
2494: return b.contains(s, p, o);
2495: }
2496:
2497: /**
2498: * <p>
2499: * Answer true if this model is currently in <i>strict checking mode</i>. Strict
2500: * mode means
2501: * that converting a common resource to a particular language element, such as
2502: * an ontology class, will be subject to some simple syntactic-level checks for
2503: * appropriateness.
2504: * </p>
2505: *
2506: * @return True if in strict checking mode
2507: */
2508: public boolean strictMode() {
2509: return m_strictMode;
2510: }
2511:
2512: /**
2513: * <p>
2514: * Set the checking mode to strict or non-strict.
2515: * </p>
2516: *
2517: * @param strict
2518: * @see #strictMode()
2519: */
2520: public void setStrictMode(boolean strict) {
2521: m_strictMode = strict;
2522: }
2523:
2524: /**
2525: * <p>Set the flag that controls whether adding or removing <i>imports</i>
2526: * statements into the
2527: * model will result in the imports closure changing dynamically.</p>
2528: * @param dynamic If true, adding or removing an imports statement to the
2529: * model will result in a change in the imports closure. If false, changes
2530: * to the imports are not monitored dynamically. Default false.
2531: */
2532: public void setDynamicImports(boolean dynamic) {
2533: if (dynamic) {
2534: if (m_importsListener == null) {
2535: // turn on dynamic processing
2536: m_importsListener = new ImportsListener();
2537: register(m_importsListener);
2538: }
2539: } else {
2540: if (m_importsListener != null) {
2541: // turn off dynamic processing
2542: unregister(m_importsListener);
2543: m_importsListener = null;
2544: }
2545: }
2546: }
2547:
2548: /**
2549: * <p>Answer true if the imports closure of the model will be dynamically
2550: * updated as imports statements are added and removed.</p>
2551: * @return True if the imports closure is updated dynamically.
2552: */
2553: public boolean getDynamicImports() {
2554: return m_importsListener != null;
2555: }
2556:
2557: /**
2558: * <p>Answer the ontology model specification that was used to construct this model</p>
2559: * @return An ont model spec instance.
2560: */
2561: public OntModelSpec getSpecification() {
2562: return m_spec;
2563: }
2564:
2565: /**
2566: * <p>Answer the ontology event manager attached to this model. If there is no event
2567: * manager currently attached, a new one will be created.</p>
2568: * @return The current, or a new, ontology event mananger
2569: */
2570: public OntEventManager getEventManager() {
2571: if (m_ontEventMgr == null) {
2572: m_ontEventMgr = new OntEventManager(this );
2573: }
2574:
2575: return m_ontEventMgr;
2576: }
2577:
2578: /**
2579: * <p>
2580: * Answer the iterator over the resources from the graph that satisfy the given
2581: * query, followed by the answers to the alternative queries (if specified). A
2582: * typical scenario is that the main query gets resources of a given class (say,
2583: * <code>rdfs:Class</code>), while the altQueries query for aliases for that
2584: * type (such as <code>daml:Class</code>).
2585: * </p>
2586: *
2587: * @param query A query to run against the model
2588: * @param altQueries An optional list of subsidiary queries to chain on to the first
2589: * @return ExtendedIterator An iterator over the (assumed single) results of
2590: * executing the queries.
2591: */
2592: public ExtendedIterator queryFor(BindingQueryPlan query,
2593: List altQueries, Class asKey) {
2594: GetBinding firstBinding = new GetBinding(0);
2595:
2596: // get the results from the main query
2597: ExtendedIterator mainQuery = query.executeBindings().mapWith(
2598: firstBinding);
2599:
2600: // now add the alternate queries, if defined
2601: if (altQueries != null) {
2602: for (Iterator i = altQueries.iterator(); i.hasNext();) {
2603: ExtendedIterator altQuery = ((BindingQueryPlan) i
2604: .next()).executeBindings()
2605: .mapWith(firstBinding);
2606: mainQuery = mainQuery.andThen(altQuery);
2607: }
2608: }
2609:
2610: // map each answer value to the appropriate ehnanced node
2611: return mainQuery.filterKeep(new SubjectNodeCanAs(asKey))
2612: .mapWith(new SubjectNodeAs(asKey));
2613: }
2614:
2615: // output operations - delegate to base model
2616:
2617: public Model write(Writer writer) {
2618: return getBaseModel().write(writer);
2619: }
2620:
2621: public Model write(Writer writer, String lang) {
2622: return getBaseModel().write(writer, lang);
2623: }
2624:
2625: public Model write(Writer writer, String lang, String base) {
2626: return getBaseModel().write(writer, lang, base);
2627: }
2628:
2629: public Model write(OutputStream out) {
2630: return getBaseModel().write(out);
2631: }
2632:
2633: public Model write(OutputStream out, String lang) {
2634: return getBaseModel().write(out, lang);
2635: }
2636:
2637: public Model write(OutputStream out, String lang, String base) {
2638: return getBaseModel().write(out, lang, base);
2639: }
2640:
2641: public Model writeAll(Writer writer, String lang, String base) {
2642: return super .write(writer, lang, base);
2643: }
2644:
2645: public Model writeAll(OutputStream out, String lang, String base) {
2646: return super .write(out, lang, base);
2647: }
2648:
2649: // Implementation of inf model interface methods
2650:
2651: /**
2652: * Return the raw RDF model being processed (i.e. the argument
2653: * to the Reasonder.bind call that created this InfModel).
2654: */
2655: public Model getRawModel() {
2656: return getBaseModel();
2657: }
2658:
2659: /**
2660: * Return the Reasoner which is being used to answer queries to this graph.
2661: */
2662: public Reasoner getReasoner() {
2663: return (getGraph() instanceof InfGraph) ? ((InfGraph) getGraph())
2664: .getReasoner()
2665: : null;
2666: }
2667:
2668: /**
2669: * Cause the inference model to reconsult the underlying data to take
2670: * into account changes. Normally changes are made through the InfModel's add and
2671: * remove calls are will be handled appropriately. However, in some cases changes
2672: * are made "behind the InfModels's back" and this forces a full reconsult of
2673: * the changed data.
2674: */
2675: public void rebind() {
2676: if (getGraph() instanceof InfGraph) {
2677: ((InfGraph) getGraph()).rebind();
2678: }
2679: }
2680:
2681: /**
2682: * Perform any initial processing and caching. This call is optional. Most
2683: * engines either have negligable set up work or will perform an implicit
2684: * "prepare" if necessary. The call is provided for those occasions where
2685: * substantial preparation work is possible (e.g. running a forward chaining
2686: * rule system) and where an application might wish greater control over when
2687: * this prepration is done rather than just leaving to be done at first query time.
2688: */
2689: public void prepare() {
2690: if (getGraph() instanceof InfGraph) {
2691: ((InfGraph) getGraph()).prepare();
2692: }
2693: }
2694:
2695: /**
2696: * Reset any internal caches. Some systems, such as the tabled backchainer,
2697: * retain information after each query. A reset will wipe this information preventing
2698: * unbounded memory use at the expense of more expensive future queries. A reset
2699: * does not cause the raw data to be reconsulted and so is less expensive than a rebind.
2700: */
2701: public void reset() {
2702: if (getGraph() instanceof InfGraph) {
2703: ((InfGraph) getGraph()).reset();
2704: }
2705: }
2706:
2707: /**
2708: * <p>Returns a derivations model. The rule reasoners typically create a
2709: * graph containing those triples added to the base graph due to rule firings.
2710: * In some applications it can useful to be able to access those deductions
2711: * directly, without seeing the raw data which triggered them. In particular,
2712: * this allows the forward rules to be used as if they were rewrite transformation
2713: * rules.</p>
2714: *
2715: * @return The derivations model, if one is defined, or else null
2716: */
2717: public Model getDeductionsModel() {
2718: if (m_deductionsModel == null) {
2719: InfGraph infGraph = getInfGraph();
2720: if (infGraph != null) {
2721: Graph deductionsGraph = infGraph.getDeductionsGraph();
2722: if (deductionsGraph != null) {
2723: m_deductionsModel = ModelFactory
2724: .createModelForGraph(deductionsGraph);
2725: }
2726: }
2727: } else {
2728: // ensure that the cached model sees the updated changes from the
2729: // underlying reasoner graph
2730: getInfGraph().prepare();
2731: }
2732:
2733: return m_deductionsModel;
2734: }
2735:
2736: /**
2737: * Test the consistency of the underlying data. This normally tests
2738: * the validity of the bound instance data against the bound
2739: * schema data.
2740: * @return a ValidityReport structure
2741: */
2742: public ValidityReport validate() {
2743: return (getGraph() instanceof InfGraph) ? ((InfGraph) getGraph())
2744: .validate()
2745: : null;
2746: }
2747:
2748: /** Find all the statements matching a pattern.
2749: * <p>Return an iterator over all the statements in a model
2750: * that match a pattern. The statements selected are those
2751: * whose subject matches the <code>subject</code> argument,
2752: * whose predicate matches the <code>predicate</code> argument
2753: * and whose object matchesthe <code>object</code> argument.
2754: * If an argument is <code>null</code> it matches anything.</p>
2755: * <p>
2756: * The s/p/o terms may refer to resources which are temporarily defined in the "posit" model.
2757: * This allows one, for example, to query what resources are of type CE where CE is a
2758: * class expression rather than a named class - put CE in the posit arg.</p>
2759: *
2760: * @return an iterator over the subjects
2761: * @param subject The subject sought
2762: * @param predicate The predicate sought
2763: * @param object The value sought
2764: */
2765: public StmtIterator listStatements(Resource subject,
2766: Property predicate, RDFNode object, Model posit) {
2767: if (getGraph() instanceof InfGraph) {
2768: Iterator iter = getInfGraph()
2769: .find(asNode(subject), asNode(predicate),
2770: asNode(object), posit.getGraph());
2771: return IteratorFactory.asStmtIterator(iter, this );
2772: } else {
2773: return null;
2774: }
2775: }
2776:
2777: /**
2778: * Switch on/off drivation logging. If this is switched on then every time an inference
2779: * is a made that fact is recorded and the resulting record can be access through a later
2780: * getDerivation call. This may consume a lot of space!
2781: */
2782: public void setDerivationLogging(boolean logOn) {
2783: if (getGraph() instanceof InfGraph) {
2784: ((InfGraph) getGraph()).setDerivationLogging(logOn);
2785: }
2786: }
2787:
2788: /**
2789: * Return the derivation of the given statement (which should be the result of
2790: * some previous list operation).
2791: * Not all reasoneers will support derivations.
2792: * @return an iterator over Derivation records or null if there is no derivation information
2793: * available for this triple.
2794: */
2795: public Iterator getDerivation(Statement statement) {
2796: return (getGraph() instanceof InfGraph) ? ((InfGraph) getGraph())
2797: .getDerivation(statement.asTriple())
2798: : null;
2799: }
2800:
2801: // Internal implementation methods
2802: //////////////////////////////////
2803:
2804: private static void initSyntaxCheckerClass() {
2805: if (owlSyntaxCheckerClass == null) {
2806: try {
2807: owlSyntaxCheckerClass = Class
2808: .forName(owlSyntaxCheckerClassName);
2809: owlSyntaxCheckerClass.newInstance();
2810: } catch (Exception e) {
2811: throw new ConfigException(
2812: "owlsyntax.jar must be on the classpath.", e);
2813: }
2814: }
2815: }
2816:
2817: /**
2818: * <p>Helper method to the constructor, which interprets the spec and generates an appropriate
2819: * graph for this model</p>
2820: * @param spec The model spec to interpret
2821: * @param base The base model, or null
2822: */
2823: private static Graph generateGraph(OntModelSpec spec, Graph base) {
2824: // create a empty union graph
2825: MultiUnion u = new MultiUnion();
2826: u.addGraph(base);
2827: u.setBaseGraph(base);
2828:
2829: Reasoner r = spec.getReasoner();
2830: // if we have a reasoner in the spec, bind to the union graph and return
2831: return r == null ? (Graph) u : r.bind(u);
2832: }
2833:
2834: /**
2835: * <p>Answer the union graph that contains the imports closure for this ontology</p>
2836: * @return The union graph
2837: */
2838: protected MultiUnion getUnionGraph() {
2839: return m_union;
2840: }
2841:
2842: /** Answer the resource with the given URI, if present, as the given facet */
2843: protected Resource findByURIAs(String uri, Class asKey) {
2844: if (uri == null) {
2845: throw new IllegalArgumentException(
2846: "Cannot get() ontology value with a null URI");
2847: }
2848:
2849: Node n = Node.createURI(uri);
2850:
2851: if (getGraph().contains(n, Node.ANY, Node.ANY)) {
2852: // this resource is a subject in the graph
2853: try {
2854: return (Resource) getNodeAs(n, asKey);
2855: } catch (ConversionException ignore) {/**/
2856: }
2857: }
2858:
2859: // not present, or cannot be as'ed to the desired facet
2860: return null;
2861: }
2862:
2863: /**
2864: * <p>
2865: * Answer an iterator over all of the resources that have
2866: * <code>rdf:type</code> type.
2867: * </p>
2868: *
2869: * @param type The resource that is the value of <code>rdf:type</code> we
2870: * want to match
2871: * @return An iterator over all triples <code>_x rdf:type type</code>
2872: */
2873: protected ExtendedIterator findByType(Resource type) {
2874: return getGraph().find(null, RDF.type.asNode(), type.asNode());
2875: }
2876:
2877: /**
2878: * <p>
2879: * Answer an iterator over all of the resources that have
2880: * <code>rdf:type type</code>, or optionally, one of the alternative types.
2881: * </p>
2882: *
2883: * @param type The resource that is the value of <code>rdf:type</code> we
2884: * want to match
2885: * @param alternates An iterator over alternative types to search for, or null
2886: * @return An iterator over all triples <code>_x rdf:type t</code> where t
2887: * is <code>type</code> or one of the values from <code>types</code>.
2888: */
2889: protected ExtendedIterator findByType(Resource type,
2890: Iterator alternates) {
2891: ExtendedIterator i = findByType(type);
2892:
2893: // compose onto i the find iterators for the alternate types
2894: if (alternates != null) {
2895: while (alternates.hasNext()) {
2896: i = i.andThen(findByType((Resource) alternates.next()));
2897: }
2898: }
2899:
2900: return UniqueExtendedIterator.create(i);
2901: }
2902:
2903: /**
2904: * <p>
2905: * Answer an iterator over all of the resources that have
2906: * <code>rdf:type type</code>, or optionally, one of the alternative types,
2907: * and present the results <code>as()</code> the given class.
2908: * </p>
2909: *
2910: * @param type The resource that is the value of <code>rdf:type</code> we
2911: * want to match
2912: * @param types An iterator over alternative types to search for, or null
2913: * @param asKey The value to use to present the polymorphic results
2914: * @return An iterator over all triples <code>_x rdf:type type</code>
2915: */
2916: protected ExtendedIterator findByTypeAs(Resource type,
2917: Iterator types, Class asKey) {
2918: return findByType(type, types)
2919: .mapWith(new SubjectNodeAs(asKey));
2920: }
2921:
2922: /**
2923: * <p>
2924: * Answer an iterator over all of the resources that has an
2925: * <code>rdf:type</code> from the types iterator,
2926: * and present the results <code>as()</code> the given class.
2927: * </p>
2928: *
2929: * @param types An iterator over types to search for. An exception will
2930: * be raised if this iterator does not have at least one next() element.
2931: * @param asKey The value to use to present the polymorphic results
2932: * @return An iterator over all triples <code>_x rdf:type type</code>
2933: */
2934: protected ExtendedIterator findByTypeAs(Iterator types, Class asKey) {
2935: return findByTypeAs((Resource) types.next(), types, asKey);
2936: }
2937:
2938: /**
2939: * <p>
2940: * Answer an iterator over resources with the given rdf:type; for each value
2941: * in the iterator, ensure that is is presented <code>as()</code> the
2942: * polymorphic object denoted by the given class key.
2943: * </p>
2944: *
2945: * @param type The rdf:type to search for
2946: * @param asKey The key to pass to as() on the subject nodes
2947: * @return An iterator over subjects with the given type, presenting as
2948: * the given polymorphic class.
2949: */
2950: protected ExtendedIterator findByTypeAs(Resource type, Class asKey) {
2951: return findByType(type).mapWith(new SubjectNodeAs(asKey));
2952: }
2953:
2954: /**
2955: * <p>
2956: * Answer a binding query that will search for 'an X that has an
2957: * rdf:type whose rdf:type is C' for some given resource C.
2958: * </p>
2959: *
2960: * @param type The type of the type of the resources we're searching for
2961: * @return BindingQueryPlan A binding query for the X resources.
2962: */
2963: protected BindingQueryPlan queryXTypeOfType(Resource type) {
2964: if (type != null) {
2965: Query q = new Query();
2966: // kers: this non-intuitive order should improve search performance
2967: q.addMatch(Query.Y, RDF.type.asNode(), type.asNode());
2968: q.addMatch(Query.X, RDF.type.asNode(), Query.Y);
2969:
2970: return queryHandler().prepareBindings(q,
2971: new Node[] { Query.X });
2972: } else {
2973: return null;
2974: }
2975: }
2976:
2977: /**
2978: * <p>
2979: * Answer an iterator over nodes that have p as a subject
2980: * </p>
2981: *
2982: * @param p A property
2983: * @return ExtendedIterator over subjects of p.
2984: */
2985: protected ExtendedIterator findByDefiningProperty(Property p) {
2986: return getGraph().find(null, p.asNode(), null);
2987: }
2988:
2989: /**
2990: * <p>
2991: * Answer an iterator over nodes that have p as a subject, presented as
2992: * polymorphic enh resources of the given facet.
2993: * </p>
2994: *
2995: * @param p A property
2996: * @param asKey A facet type
2997: * @return ExtendedIterator over subjects of p, presented as the facet.
2998: */
2999: protected ExtendedIterator findByDefiningPropertyAs(Property p,
3000: Class asKey) {
3001: return findByDefiningProperty(p).mapWith(
3002: new SubjectNodeAs(asKey));
3003: }
3004:
3005: /**
3006: * <p>
3007: * Answer the resource with the given uri and that optionally has the given <code>rdf:type</code>,
3008: * creating the resource if necessary.
3009: * </p>
3010: *
3011: * @param uri The uri to use, or null for an anonymous resource
3012: * @param rdfType The resource to assert as the <code>rdf:type</code>, or null to leave untyped
3013: * @return A new or existing Resource
3014: */
3015: protected Resource getResourceWithType(String uri, Resource rdfType) {
3016: Resource r = getResource(uri);
3017: if (rdfType != null) {
3018: r.addProperty(RDF.type, rdfType);
3019: }
3020: return r;
3021: }
3022:
3023: /**
3024: * <p>Answer a resource presenting the {@link OntResource} facet, which has the given
3025: * URI. If no such resource is currently present in the model, return null.</p>
3026: * @param uri The URI of a resource
3027: * @return An OntResource with the given URI, or null
3028: */
3029: public OntResource getOntResource(String uri) {
3030: Resource r = getResource(uri);
3031: if (containsResource(r)) {
3032: return (OntResource) r.as(OntResource.class);
3033: }
3034: return null;
3035: }
3036:
3037: /**
3038: * <p>Answer a resource presenting the {@link OntResource} facet, which
3039: * corresponds to the given resource but attached to this model.</p>
3040: * @param res An existing resource
3041: * @return An {@link OntResource} attached to this model that has the same URI
3042: * or anonID as the given resource
3043: */
3044: public OntResource getOntResource(Resource res) {
3045: return (OntResource) res.inModel(this ).as(OntResource.class);
3046: }
3047:
3048: /**
3049: * <p>Throw an OntologyException if the term is not in language profile</p>
3050: *
3051: * @param profileTerm The entry from the profile
3052: * @param desc A label for the profile term
3053: * @exception OntologyException if profileTerm is null.
3054: */
3055: protected void checkProfileEntry(Object profileTerm, String desc) {
3056: if (profileTerm == null) {
3057: // not in the profile
3058: throw new ProfileException(desc, getProfile());
3059: }
3060: }
3061:
3062: /**
3063: * <p>Check that every member of the given list has the given rdf:type, and throw an exception if not.</p>
3064: * @param list The list to be checked
3065: * @param rdfType The rdf:type value to check for
3066: * @exception LanguageConsistencyException if any member of the list does not have <code>rdf:type <i>rdfType</i></code>
3067: */
3068: protected void checkListMembersRdfType(RDFList list,
3069: Resource rdfType) {
3070: if (strictMode()
3071: && !((Boolean) list.reduce(new RdfTypeTestFn(rdfType),
3072: Boolean.TRUE)).booleanValue()) {
3073: // not all of the members of the list are of the given type
3074: throw new LanguageConsistencyException(
3075: "The members of the given list are expected to be of rdf:type "
3076: + rdfType.toString());
3077: }
3078: }
3079:
3080: /**
3081: Answer the supplied model, unless it's null, in which case answer a new model
3082: constructed as per spec.
3083: */
3084: private static Model makeBaseModel(OntModelSpec spec, Model model) {
3085: return model == null ? spec.createBaseModel() : model;
3086: }
3087:
3088: /**
3089: * <p>Answer the InfGraph that this model is wrapping, or null if this ontology
3090: * model is not wrapping an inf graph.</p>
3091: * @return The model's graph as an InfGraph, or null
3092: */
3093: private InfGraph getInfGraph() {
3094: return (getGraph() instanceof InfGraph) ? ((InfGraph) getGraph())
3095: : null;
3096: }
3097:
3098: //==============================================================================
3099: // Inner class definitions
3100: //==============================================================================
3101:
3102: /** Map triple subjects or single nodes to subject enh nodes, presented as() the given class */
3103: protected class SubjectNodeAs implements Map1 {
3104: protected Class m_asKey;
3105:
3106: protected SubjectNodeAs(Class asKey) {
3107: m_asKey = asKey;
3108: }
3109:
3110: public Object map1(Object x) {
3111: Node n = (x instanceof Triple) ? ((Triple) x).getSubject()
3112: : ((x instanceof EnhNode) ? ((EnhNode) x).asNode()
3113: : (Node) x);
3114: return getNodeAs(n, m_asKey);
3115: }
3116:
3117: }
3118:
3119: /** Filter that accepts nodes that can be mapped to the given facet */
3120: protected class SubjectNodeCanAs extends Filter {
3121: protected Class m_asKey;
3122:
3123: protected SubjectNodeCanAs(Class asKey) {
3124: m_asKey = asKey;
3125: }
3126:
3127: public boolean accept(Object x) {
3128: Node n = (x instanceof Triple) ? ((Triple) x).getSubject()
3129: : ((x instanceof EnhNode) ? ((EnhNode) x).asNode()
3130: : (Node) x);
3131: try {
3132: getNodeAs(n, m_asKey);
3133: } catch (Exception ignore) {
3134: return false;
3135: }
3136:
3137: return true;
3138: }
3139:
3140: }
3141:
3142: /** Project out the first element of a list of bindings */
3143: protected class GetBinding implements Map1 {
3144: protected int m_index;
3145:
3146: protected GetBinding(int index) {
3147: m_index = index;
3148: }
3149:
3150: public Object map1(Object x) {
3151: return ((List) x).get(m_index);
3152: }
3153: }
3154:
3155: /** Function to test the rdf type of a list */
3156: protected class RdfTypeTestFn implements RDFList.ReduceFn {
3157: protected Resource m_type;
3158:
3159: protected RdfTypeTestFn(Resource type) {
3160: m_type = type;
3161: }
3162:
3163: public Object reduce(RDFNode node, Object accumulator) {
3164: Boolean acc = (Boolean) accumulator;
3165: if (acc.booleanValue()) {
3166: // true so far
3167: Resource r = (Resource) node;
3168: return new Boolean(r.hasProperty(RDF.type, m_type));
3169: } else {
3170: return acc;
3171: }
3172: }
3173: }
3174:
3175: /** Listener for model changes that indicate a change in the imports to the model */
3176: protected class ImportsListener extends StatementListener {
3177: public void addedStatement(Statement added) {
3178: if (added.getPredicate().equals(getProfile().IMPORTS())) {
3179: getDocumentManager().loadImport(OntModelImpl.this ,
3180: added.getResource().getURI());
3181: }
3182: }
3183:
3184: public void removedStatement(Statement removed) {
3185: if (removed.getPredicate().equals(getProfile().IMPORTS())) {
3186: getDocumentManager().unloadImport(OntModelImpl.this ,
3187: removed.getResource().getURI());
3188: }
3189: }
3190: }
3191: }
3192:
3193: /*
3194: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
3195: All rights reserved.
3196:
3197: Redistribution and use in source and binary forms, with or without
3198: modification, are permitted provided that the following conditions
3199: are met:
3200:
3201: 1. Redistributions of source code must retain the above copyright
3202: notice, this list of conditions and the following disclaimer.
3203:
3204: 2. Redistributions in binary form must reproduce the above copyright
3205: notice, this list of conditions and the following disclaimer in the
3206: documentation and/or other materials provided with the distribution.
3207:
3208: 3. The name of the author may not be used to endorse or promote products
3209: derived from this software without specific prior written permission.
3210:
3211: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3212: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3213: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3214: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3215: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3216: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3217: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3218: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3219: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3220: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3221: */
|