📄 propertyiterator.java
字号:
/*****************************************************************************
* Source code information
* -----------------------
* Original author Ian Dickinson, HP Labs Bristol
* Author email Ian.Dickinson@hp.com
* Package Jena
* Created 11 Sept 2001
* Filename $RCSfile: PropertyIterator.java,v $
* Revision $Revision: 1.17 $
* Release status Preview-release $State: Exp $
*
* Last modified on $Date: 2007/01/08 14:40:52 $
* by $Author: ian_dickinson $
*
* (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007 Hewlett-Packard Development Company, LP
* (see footer for full conditions)
*****************************************************************************/
// Package
///////////////
package com.hp.hpl.jena.ontology.daml;
// Imports
///////////////
import java.util.*;
import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.util.iterator.*;
import com.hp.hpl.jena.vocabulary.DAML_OIL;
/**
* <p>
* Provides a means of traversing the relationships in a DAML model, respecting
* some of the extended semantics of DAML+OIL over RDF. In particular, the
* PropertyIterator knows about class, property and instance equivalence,
* transitive properties, inverse properties, the class hierarchy and the
* property hierarchy.
* </p>
* <p>
* Given a property P, and a resource x, iterates over all the y such that
* <code>x P y</code>, respecting the fact that P may be transitive (so
* <code>x P y</code> and <code>y P z</code> implies <code>x P z</code>), and
* symmetric (so <code>x P y</code> implies <code>y P x</code>). The iterator
* is lazily evaluated, so changes to the model while iterating could generate
* unpredictable results. The iterator does do loop detection, so should always
* terminate (assuming the model is finite!). Deletion is not supported.
* </p>
* <p>
* This iterator also supports the setting of a default value. The default value
* is an object that will be returned as the last value of the iteration, unless
* it has already been returned earlier.
* </p>
*
* @author Ian Dickinson, HP Labs (<a href="mailto:Ian.Dickinson@hp.com">email</a>)
* @version CVS info: $Id: PropertyIterator.java,v 1.17 2007/01/08 14:40:52 ian_dickinson Exp $
* @since Jena 1.3.0 (was previously in package com.hp.hpl.jena.ontology.daml.impl).
* @deprecated The DAML API is scheduled to be removed from Jena 2.6 onwards. Please use the DAML profile in the main ontology API
*/
public class PropertyIterator
implements Iterator
{
// Constants
//////////////////////////////////
// Static variables
//////////////////////////////////
// Instance variables
//////////////////////////////////
/** The queue of nodes to be evaluated */
protected LinkedList m_nodeQueue = new LinkedList();
/** The property we're evaluating */
protected Property m_pred = null;
/** The inverse of pred, or null */
protected Property m_inverse = null;
/** Collection of properties equivalent to m_pred */
protected HashSet m_predEquivs = new HashSet();
/** Collection of properties equivalent to m_inverse */
protected HashSet m_inverseEquivs = new HashSet();
/** Flag to say if pred is transitive */
protected boolean m_transitive = false;
/** Set of nodes we've seen on this trip */
protected WeakHashMap m_seen = new WeakHashMap();
/** The resource we started from (if only one) */
protected Resource m_root = null;
/** The resources we started from (if many) */
protected List m_roots = null;
/** The default value for the iterator, or null if no default */
protected Object m_defaultValue = null;
/** A flag to show that the default value has been returned */
protected boolean m_defaultValueSeen = false;
/** A flag to control whether we use equivalent values during the iteration */
protected boolean m_useEquivalence = true;
/** The model we are operating on */
protected Model m_model = null;
// Constructors
//////////////////////////////////
/**
* Construct a property iterator for the given property, starting from the
* given resource. The property may be defined to be symmetric by supplying
* its inverse (which could be itself), and/or transitive. The property may also
* be defined to be reflexive, in which case root itself will be returned as
* a member of the iteration.
*
* @param root The root resource from whence to start iterating over the closure of pred
* @param pred The property to iterate over
* @param inverse The inverse of pred, or null if pred has no inverse. The inverse is used
* to include resource y in the iteration if P' = inverse(P) and y P' x.
* @param isTransitive If true, the property is transitive
* @param isReflexive If true, the property is reflexive (so, the root resource will be included
* in the iteration).
*/
public PropertyIterator( Resource root, Property pred, Property inverse, boolean isTransitive, boolean isReflexive ) {
this( root, pred, inverse, isTransitive, isReflexive, true );
}
/**
* Construct a property iterator for the given property, starting from the
* given resource. The property may be defined to be symmetric by supplying
* its inverse (which could be itself), and/or transitive. The property may also
* be defined to be reflexive, in which case root itself will be returned as
* a member of the iteration.
*
* @param root The root resource from whence to start iterating over the closure of pred
* @param pred The property to iterate over
* @param inverse The inverse of pred, or null if pred has no inverse. The inverse is used
* to include resource y in the iteration if P' = inverse(P) and y P' x.
* @param isTransitive If true, the property is transitive
* @param isReflexive If true, the property is reflexive (so, the root resource will be included
* in the iteration).
* @param useEquivalence If true, equivalence between DAML values will be included in the
* iteration (unless the model containing the DAML values
* has equivalence switched off via {@link DAMLModel#setUseEquivalence}).
*/
public PropertyIterator( Resource root, Property pred, Property inverse, boolean isTransitive,
boolean isReflexive, boolean useEquivalence ) {
m_root = root;
m_pred = pred;
m_inverse = inverse;
m_transitive = isTransitive;
m_useEquivalence = useEquivalence;
setModel();
cachePropertyEquivs();
// the root only goes on the queue if the relation is reflexive
if (isReflexive) {
enqueue( root );
}
else {
// otherwise, we'll just start with the relations of the root
expandQueue( root );
}
}
/**
* Construct a property iterator for the given property, starting from the
* given set of resources. The property may be defined to be symmetric by supplying
* its inverse (which could be itself), and/or transitive. The property may also
* be defined to be reflexive, in which case all of the given root resources will
* be returned as members of the iteration.
*
* @param roots A set of root resources from whence to start iterating over the closure of pred,
* represented as an iterator
* @param pred The property to iterate over
* @param inverse The inverse of pred, or null if pred has no inverse. The inverse is used
* to include resource y in the iteration if P' = inverse(P) and y P' x.
* @param isTransitive If true, the property is transitive
* @param isReflexive If true, the property is reflexive (so, the root resources will be included
* in the iteration).
*/
public PropertyIterator( Iterator roots, Property pred, Property inverse, boolean isTransitive, boolean isReflexive ) {
this( roots, pred, inverse, isTransitive, isReflexive, true );
}
/**
* Construct a property iterator for the given property, starting from the
* given set of resources. The property may be defined to be symmetric by supplying
* its inverse (which could be itself), and/or transitive. The property may also
* be defined to be reflexive, in which case all of the given root resources will
* be returned as members of the iteration.
*
* @param roots A set of root resources from whence to start iterating over the closure of pred,
* represented as an iterator
* @param pred The property to iterate over
* @param inverse The inverse of pred, or null if pred has no inverse. The inverse is used
* to include resource y in the iteration if P' = inverse(P) and y P' x.
* @param isTransitive If true, the property is transitive
* @param isReflexive If true, the property is reflexive (so, the root resources will be included
* in the iteration).
* @param useEquivalence If true, equivalence between DAML values will be included in the
* iteration (unless the model containing the DAML values has equivalence
* switched off via {@link DAMLModel#setUseEquivalence}.
*/
public PropertyIterator( Iterator roots, Property pred, Property inverse, boolean isTransitive,
boolean isReflexive, boolean useEquivalence ) {
// copy the roots of the traversal
m_roots = new ArrayList();
m_pred = pred;
m_inverse = inverse;
m_transitive = isTransitive;
m_useEquivalence = useEquivalence;
setModel();
cachePropertyEquivs();
// the root only goes on the queue if the relation is reflexive
if (isReflexive) {
// reflexive, so we queue each root to be expanded (and it will get returned by next())
while (roots.hasNext()) {
Resource next = (Resource) roots.next();
if (m_model == null && next.getModel() != null) {
// keep a reference to the model if we find one
m_model = next.getModel();
}
m_roots.add( next );
enqueue( next );
}
}
else {
// not reflexive, so we'll just start with the relations of the root on the queue
while (roots.hasNext()) {
Resource next = (Resource) roots.next();
if (m_model == null && next.getModel() != null) {
// keep a reference to the model if we find one
m_model = next.getModel();
}
m_roots.add( next );
expandQueue( next );
}
}
}
// External signature methods
//////////////////////////////////
/**
* Answer true if the iteration over the closure of the predicate will answer any values that have
* not yet been returned.
*
* @return True if there is at least one more element in the iteration
*/
public boolean hasNext() {
// is there at least one more node in the queue?
return !m_nodeQueue.isEmpty() || (hasDefaultValue() && !m_defaultValueSeen);
}
/**
* Answer the next RDFNode in the iteration over the given predicate. Note that each node in the
* closure of the predicate will be answered only once, to avoid endless loops.
*
* @return The next RDFNode in the iteration over the closure of the predicate.
* @exception java.util.NoSuchElementException if the iterator has no more elements
*/
public Object next() {
if (!m_nodeQueue.isEmpty()) {
// get the next node from the queue, this will be the one that we return
RDFNode next = (RDFNode) m_nodeQueue.removeFirst();
// is this the default value?
if (hasDefaultValue() && m_defaultValue.equals( next )) {
m_defaultValueSeen = true;
}
// now add the relations of the node to the end of the queue
if (next instanceof com.hp.hpl.jena.rdf.model.Resource) {
expandQueue( (Resource) next );
}
// answer the next node in the interation
return next;
}
else if (hasDefaultValue() && !m_defaultValueSeen) {
// return the default value for this iterator
m_defaultValueSeen = true;
return m_defaultValue;
}
else {
// no more nodes, so this is an error
throw new NoSuchElementException( "Tried to access next() element from empty property iterator" );
}
}
/**
* Unsupported operation in this iterator.
*
* @exception java.lang.UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException( "Cannot remove elements from a property iterator" );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -