FileDocCategorySizeDatePackage
NodeSetDTM.javaAPI DocJava SE 5 API35333Fri Aug 26 14:56:06 BST 2005com.sun.org.apache.xpath.internal

NodeSetDTM

public class NodeSetDTM extends NodeVector implements Cloneable, DTMIterator

The NodeSetDTM class can act as either a NodeVector, NodeList, or NodeIterator. However, in order for it to act as a NodeVector or NodeList, it's required that setShouldCacheNodes(true) be called before the first nextNode() is called, in order that nodes can be added as they are fetched. Derived classes that implement iterators must override runTo(int index), in order that they may run the iteration to the given index.

Note that we directly implement the DOM's NodeIterator interface. We do not emulate all the behavior of the standard NodeIterator. In particular, we do not guarantee to present a "live view" of the document ... but in XSLT, the source document should never be mutated, so this should never be an issue.

Thought: Should NodeSetDTM really implement NodeList and NodeIterator, or should there be specific subclasses of it which do so? The advantage of doing it all here is that all NodeSetDTMs will respond to the same calls; the disadvantage is that some of them may return less-than-enlightening results when you do so.

xsl.usage
advanced

Fields Summary
DTMManager
m_manager
protected transient int
m_next
If this node is being used as an iterator, the next index that nextNode() will return.
protected transient boolean
m_mutable
True if this list can be mutated.
protected transient boolean
m_cacheNodes
True if this list is cached.
protected int
m_root
The root of the iteration, if available.
private transient int
m_last
Constructors Summary
public NodeSetDTM(DTMManager dtmManager)
Create an empty nodelist.

    super();
    m_manager = dtmManager;
  
public NodeSetDTM(int blocksize, int dummy, DTMManager dtmManager)
Create an empty, using the given block size.

param
blocksize Size of blocks to allocate
param
dummy pass zero for right now...

    super(blocksize);
    m_manager = dtmManager;
  
public NodeSetDTM(NodeSetDTM nodelist)
Create a NodeSetDTM, and copy the members of the given NodeSetDTM into it.

param
nodelist Set of Nodes to be made members of the new set.


    super();
    m_manager = nodelist.getDTMManager();
    m_root = nodelist.getRoot();

    addNodes((DTMIterator) nodelist);
  
public NodeSetDTM(DTMIterator ni)
Create a NodeSetDTM, and copy the members of the given DTMIterator into it.

param
ni Iterator which yields Nodes to be made members of the new set.


    super();

    m_manager = ni.getDTMManager();
    m_root = ni.getRoot();
    addNodes(ni);
  
public NodeSetDTM(NodeIterator iterator, XPathContext xctxt)
Create a NodeSetDTM, and copy the members of the given DTMIterator into it.

param
ni Iterator which yields Nodes to be made members of the new set.


    super();

    Node node;
    m_manager = xctxt.getDTMManager();

    while (null != (node = iterator.nextNode()))
    {
      int handle = xctxt.getDTMHandleFromNode(node);
      addNodeInDocOrder(handle, xctxt);
    }
  
public NodeSetDTM(NodeList nodeList, XPathContext xctxt)
Create a NodeSetDTM, and copy the members of the given DTMIterator into it.

param
ni Iterator which yields Nodes to be made members of the new set.


    super();

    m_manager = xctxt.getDTMManager();

    int n = nodeList.getLength();
    for (int i = 0; i < n; i++) 
    {
      Node node = nodeList.item(i);
      int handle = xctxt.getDTMHandleFromNode(node);
      // Do not reorder or strip duplicate nodes from the given DOM nodelist
      addNode(handle); // addNodeInDocOrder(handle, xctxt);  
    } 
  
public NodeSetDTM(int node, DTMManager dtmManager)
Create a NodeSetDTM which contains the given Node.

param
node Single node to be added to the new set.


    super();
    m_manager = dtmManager;

    addNode(node);
  
Methods Summary
public voidaddElement(int value)
Append a Node onto the vector.

param
value The node to be added.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.addElement(value);
  
public voidaddNode(int n)
Add a node to the NodeSetDTM. Not all types of NodeSetDTMs support this operation

param
n Node to be added
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    this.addElement(n);
  
public intaddNodeInDocOrder(int node, boolean test, com.sun.org.apache.xpath.internal.XPathContext support)
Add the node into a vector of nodes where it should occur in document order.

param
v Vector of nodes, presumably containing Nodes
param
obj Node object.
param
node The node to be added.
param
test true if we should test for doc order
param
support The XPath runtime context.
return
insertIndex.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    int insertIndex = -1;

    if (test)
    {

      // This needs to do a binary search, but a binary search 
      // is somewhat tough because the sequence test involves 
      // two nodes.
      int size = size(), i;

      for (i = size - 1; i >= 0; i--)
      {
        int child = elementAt(i);

        if (child == node)
        {
          i = -2;  // Duplicate, suppress insert

          break;
        }

        DTM dtm = support.getDTM(node);
        if (!dtm.isNodeAfter(node, child))
        {
          break;
        }
      }

      if (i != -2)
      {
        insertIndex = i + 1;

        insertElementAt(node, insertIndex);
      }
    }
    else
    {
      insertIndex = this.size();

      boolean foundit = false;

      for (int i = 0; i < insertIndex; i++)
      {
        if (i == node)
        {
          foundit = true;

          break;
        }
      }

      if (!foundit)
        addElement(node);
    }

    // checkDups();
    return insertIndex;
  
public intaddNodeInDocOrder(int node, com.sun.org.apache.xpath.internal.XPathContext support)
Add the node into a vector of nodes where it should occur in document order.

param
v Vector of nodes, presumably containing Nodes
param
obj Node object.
param
node The node to be added.
param
support The XPath runtime context.
return
The index where it was inserted.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    return addNodeInDocOrder(node, true, support);
  
public voidaddNodes(com.sun.org.apache.xml.internal.dtm.DTMIterator iterator)
Copy NodeList members into this nodelist, adding in document order. Null references are not added.

param
iterator DTMIterator which yields the nodes to be added.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    if (null != iterator)  // defensive to fix a bug that Sanjiva reported.
    {
      int obj;

      while (DTM.NULL != (obj = iterator.nextNode()))
      {
        addElement(obj);
      }
    }

    // checkDups();
  
public voidaddNodesInDocOrder(com.sun.org.apache.xml.internal.dtm.DTMIterator iterator, com.sun.org.apache.xpath.internal.XPathContext support)
Copy NodeList members into this nodelist, adding in document order. If a node is null, don't add it.

param
iterator DTMIterator which yields the nodes to be added.
param
support The XPath runtime context.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    int node;

    while (DTM.NULL != (node = iterator.nextNode()))
    {
      addNodeInDocOrder(node, support);
    }
  
public voidallowDetachToRelease(boolean allowRelease)
Specify if it's OK for detach to release the iterator for reuse.

param
allowRelease true if it is OK for detach to release this iterator for pooling.

    // no action for right now.
  
public voidappendNodes(com.sun.org.apache.xml.internal.utils.NodeVector nodes)
Append the nodes to the list.

param
nodes The nodes to be appended to this node set.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.appendNodes(nodes);
  
public java.lang.Objectclone()
Clone this NodeSetDTM. At this time, we only expect this to be used with LocPathIterators; it may not work with other kinds of NodeSetDTMs.

return
a new NodeSetDTM of the same type, having the same state... though unless overridden in the subclasses, it may not copy all the state information.
throws
CloneNotSupportedException if this subclass of NodeSetDTM does not support the clone() operation.


    NodeSetDTM clone = (NodeSetDTM) super.clone();

    return clone;
  
public com.sun.org.apache.xml.internal.dtm.DTMIteratorcloneWithReset()
Get a cloned Iterator, and reset its state to the beginning of the iteration.

return
a new NodeSetDTM of the same type, having the same state... except that the reset() operation has been called.
throws
CloneNotSupportedException if this subclass of NodeSetDTM does not support the clone() operation.


    NodeSetDTM clone = (NodeSetDTM) clone();

    clone.reset();

    return clone;
  
public booleancontains(int s)
Tell if the table contains the given node.

param
s Node to look for
return
True if the given node was found.


    runTo(-1);

    return super.contains(s);
  
public voiddetach()
Detaches the iterator from the set which it iterated over, releasing any computational resources and placing the iterator in the INVALID state. Afterdetach has been invoked, calls to nextNode orpreviousNode will raise the exception INVALID_STATE_ERR.

This operation is a no-op in NodeSetDTM, and will not cause INVALID_STATE_ERR to be raised by later operations.

public intelementAt(int i)
Get the nth element.

param
i The index of the requested node.
return
Node at specified index.


    runTo(i);

    return super.elementAt(i);
  
public intgetAxis()
Returns the axis being iterated, if it is known.

return
Axis.CHILD, etc., or -1 if the axis is not known or is of multiple types.

    return -1;
  
public intgetCurrentNode()
Return the last fetched node. Needed to support the UnionPathIterator.

return
the last fetched node.
throws
RuntimeException thrown if this NodeSetDTM is not of a cached type, and thus doesn't permit indexed access.


    if (!m_cacheNodes)
      throw new RuntimeException(
        "This NodeSetDTM can not do indexing or counting functions!");

    int saved = m_next;
    // because nextNode always increments
    // But watch out for copy29, where the root iterator didn't
    // have nextNode called on it.
    int current = (m_next > 0) ? m_next-1 : m_next; 
    int n = (current < m_firstFree) ? elementAt(current) : DTM.NULL;
    m_next = saved; // HACK: I think this is a bit of a hack.  -sb
    return n;
  
public intgetCurrentPos()
Get the current position, which is one less than the next nextNode() call will retrieve. i.e. if you call getCurrentPos() and the return is 0, the next fetch will take place at index 1.

return
The the current position index.


                                              
    
  
    return m_next;
  
public com.sun.org.apache.xml.internal.dtm.DTMgetDTM(int nodeHandle)
Get an instance of a DTM that "owns" a node handle. Since a node iterator may be passed without a DTMManager, this allows the caller to easily get the DTM using just the iterator.

param
nodeHandle the nodeHandle.
return
a non-null DTM reference.

    
    return m_manager.getDTM(nodeHandle);
  
public com.sun.org.apache.xml.internal.dtm.DTMManagergetDTMManager()
Get an instance of the DTMManager. Since a node iterator may be passed without a DTMManager, this allows the caller to easily get the DTMManager using just the iterator.

return
a non-null DTMManager reference.

    
    return m_manager;
  
public booleangetExpandEntityReferences()
The value of this flag determines whether the children of entity reference nodes are visible to the iterator. If false, they will be skipped over.
To produce a view of the document that has entity references expanded and does not expose the entity reference node itself, use the whatToShow flags to hide the entity reference node and set expandEntityReferences to true when creating the iterator. To produce a view of the document that has entity reference nodes but no entity expansion, use the whatToShow flags to show the entity reference node and set expandEntityReferences to false.

return
true for all iterators based on NodeSetDTM, meaning that the contents of EntityRefrence nodes may be returned (though whatToShow says that the EntityReferences themselves are not shown.)

    return true;
  
public com.sun.org.apache.xml.internal.dtm.DTMFiltergetFilter()
The filter object used to screen nodes. Filters are applied to further reduce (and restructure) the DTMIterator's view of the document. In our case, we will be using hardcoded filters built into our iterators... but getFilter() is part of the DOM's DTMIterator interface, so we have to support it.

return
null, which is slightly misleading. True, there is no user-written filter object, but in fact we are doing some very sophisticated custom filtering. A DOM purist might suggest returning a placeholder object just to indicate that this is not going to return all nodes selected by whatToShow.

    return null;
  
public intgetLast()

  
    
  
    return m_last;
  
public intgetLength()
The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive. Note that this operation requires finding all the matching nodes, which may defeat attempts to defer that work.

return
integer indicating how many nodes are represented by this list.


    runTo(-1);

    return this.size();
  
public intgetRoot()

return
The root node of the Iterator, as specified when it was created. For non-Iterator NodeSetDTMs, this will be null.

    if(DTM.NULL == m_root)
    {
      if(size() > 0)
        return item(0);
      else
        return DTM.NULL;
    }
    else
      return m_root;
  
public booleangetShouldCacheNodes()
Get whether or not this is a cached node set.

return
True if this list is cached.


                      
    
  
    return m_cacheNodes;
  
public intgetWhatToShow()
This attribute determines which node types are presented via the iterator. The available set of constants is defined in the DTMFilter interface. For NodeSetDTMs, the mask has been hardcoded to show all nodes except EntityReference nodes, which have no equivalent in the XPath data model.

return
integer used as a bit-array, containing flags defined in the DOM's DTMFilter class. The value will be SHOW_ALL & ~SHOW_ENTITY_REFERENCE, meaning that only entity references are suppressed.

    return DTMFilter.SHOW_ALL & ~DTMFilter.SHOW_ENTITY_REFERENCE;
  
public intindexOf(int elem, int index)
Searches for the first occurence of the given argument, beginning the search at index, and testing for equality using the equals method.

param
elem Node to look for
param
index Index of where to start the search
return
the index of the first occurrence of the object argument in this vector at position index or later in the vector; returns -1 if the object is not found.


    runTo(-1);

    return super.indexOf(elem, index);
  
public intindexOf(int elem)
Searches for the first occurence of the given argument, beginning the search at index, and testing for equality using the equals method.

param
elem Node to look for
return
the index of the first occurrence of the object argument in this vector at position index or later in the vector; returns -1 if the object is not found.


    runTo(-1);

    return super.indexOf(elem);
  
public voidinsertElementAt(int value, int at)
Inserts the specified node in this vector at the specified index. Each component in this vector with an index greater or equal to the specified index is shifted upward to have an index one greater than the value it had previously.

param
value The node to be inserted.
param
at The index where the insert should occur.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.insertElementAt(value, at);
  
public voidinsertNode(int n, int pos)
Insert a node at a given position.

param
n Node to be added
param
pos Offset at which the node is to be inserted, with 0 being the first position.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    insertElementAt(n, pos);
  
public booleanisDocOrdered()
Returns true if all the nodes in the iteration well be returned in document order.

return
true as a default.

    return true;
  
public booleanisFresh()
Tells if this NodeSetDTM is "fresh", in other words, if the first nextNode() that is called will return the first node in the set.

return
true if nextNode() would return the first node in the set, false if it would return a later one.

    return (m_next == 0);
  
public booleanisMutable()
Tells if this iterator can have nodes added to it or set via the setItem(int node, int index) method.

return
True if the nodelist can be mutated.

    return m_mutable;
  
public intitem(int index)
Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null. TODO: What happens if index is out of range?

param
index Index into the collection.
return
The node at the indexth position in the NodeList, or null if that is not a valid index.


    runTo(index);

    return this.elementAt(index);
  
public intnextNode()
Returns the next node in the set and advances the position of the iterator in the set. After a DTMIterator is created, the first call to nextNode() returns the first node in the set.

return
The next Node in the set being iterated over, or DTM.NULL if there are no more members in that set.
throws
DOMException INVALID_STATE_ERR: Raised if this method is called after the detach method was invoked.


    if ((m_next) < this.size())
    {
      int next = this.elementAt(m_next);

      m_next++;

      return next;
    }
    else
      return DTM.NULL;
  
public intpreviousNode()
Returns the previous node in the set and moves the position of the iterator backwards in the set.

return
The previous Node in the set being iterated over, orDTM.NULL if there are no more members in that set.
throws
DOMException INVALID_STATE_ERR: Raised if this method is called after the detach method was invoked.
throws
RuntimeException thrown if this NodeSetDTM is not of a cached type, and hence doesn't know what the previous node was.


    if (!m_cacheNodes)
      throw new RuntimeException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_CANNOT_ITERATE, null)); //"This NodeSetDTM can not iterate to a previous node!");

    if ((m_next - 1) > 0)
    {
      m_next--;

      return this.elementAt(m_next);
    }
    else
      return DTM.NULL;
  
public voidremoveAllElements()
Inserts the specified node in this vector at the specified index. Each component in this vector with an index greater or equal to the specified index is shifted upward to have an index one greater than the value it had previously.

throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.removeAllElements();
  
public booleanremoveElement(int s)
Removes the first occurrence of the argument from this vector. If the object is found in this vector, each component in the vector with an index greater or equal to the object's index is shifted downward to have an index one smaller than the value it had previously.

param
s The node to be removed.
return
True if the node was successfully removed
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    return super.removeElement(s);
  
public voidremoveElementAt(int i)
Deletes the component at the specified index. Each component in this vector with an index greater or equal to the specified index is shifted downward to have an index one smaller than the value it had previously.

param
i The index of the node to be removed.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.removeElementAt(i);
  
public voidremoveNode(int n)
Remove a node.

param
n Node to be added
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    this.removeElement(n);
  
public voidreset()
Reset the iterator. May have no effect on non-iterator Nodesets.

    m_next = 0;
  
public voidrunTo(int index)
If an index is requested, NodeSetDTM will call this method to run the iterator to the index. By default this sets m_next to the index. If the index argument is -1, this signals that the iterator should be run to the end.

param
index Position to advance (or retreat) to, with 0 requesting the reset ("fresh") position and -1 (or indeed any out-of-bounds value) requesting the final position.
throws
RuntimeException thrown if this NodeSetDTM is not one of the types which supports indexing/counting.


    if (!m_cacheNodes)
      throw new RuntimeException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_CANNOT_INDEX, null)); //"This NodeSetDTM can not do indexing or counting functions!");

    if ((index >= 0) && (m_next < m_firstFree))
      m_next = index;
    else
      m_next = m_firstFree - 1;
  
public voidsetCurrentPos(int i)
Set the current position in the node set.

param
i Must be a valid index.
throws
RuntimeException thrown if this NodeSetDTM is not of a cached type, and thus doesn't permit indexed access.


    if (!m_cacheNodes)
      throw new RuntimeException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_CANNOT_INDEX, null)); //"This NodeSetDTM can not do indexing or counting functions!");

    m_next = i;
  
public voidsetElementAt(int node, int index)
Sets the component at the specified index of this vector to be the specified object. The previous component at that position is discarded. The index must be a value greater than or equal to 0 and less than the current size of the vector.

param
node The node to be set.
param
index The index of the node to be replaced.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.setElementAt(node, index);
  
public voidsetEnvironment(java.lang.Object environment)
Set the environment in which this iterator operates, which should provide: a node (the context node... same value as "root" defined below) a pair of non-zero positive integers (the context position and the context size) a set of variable bindings a function library the set of namespace declarations in scope for the expression.

At this time the exact implementation of this environment is application dependent. Probably a proper interface will be created fairly soon.

param
environment The environment object.

    // no-op
  
public voidsetItem(int node, int index)
Same as setElementAt.

param
node The node to be set.
param
index The index of the node to be replaced.
throws
RuntimeException thrown if this NodeSetDTM is not of a mutable type.


    if (!m_mutable)
      throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); //"This NodeSetDTM is not mutable!");

    super.setElementAt(node, index);
  
public voidsetLast(int last)

    m_last = last;
  
public voidsetRoot(int context, java.lang.Object environment)
Initialize the context values for this expression after it is cloned.

param
execContext The XPath runtime context for this transformation.

    // no-op, I guess...  (-sb)
  
public voidsetShouldCacheNodes(boolean b)
If setShouldCacheNodes(true) is called, then nodes will be cached. They are not cached by default. This switch must be set before the first call to nextNode is made, to ensure that all nodes are cached.

param
b true if this node set should be cached.
throws
RuntimeException thrown if an attempt is made to request caching after we've already begun stepping through the nodes in this set.


    if (!isFresh())
      throw new RuntimeException(
        XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANNOT_CALL_SETSHOULDCACHENODE, null)); //"Can not call setShouldCacheNodes after nextNode has been called!");

    m_cacheNodes = b;
    m_mutable = true;
  
public intsize()
Get the length of the list.

return
The size of this node set.

    return super.size();