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

NodeSequence

public class NodeSequence extends XObject implements PathComponent, Cloneable, DTMIterator
This class is the dynamic wrapper for a Xalan DTMIterator instance, and provides random access capabilities.

Fields Summary
protected int
m_last
The index of the last node in the iteration.
protected int
m_next
The index of the next node to be fetched. Useful if this is a cached iterator, and is being used as random access NodeList.
protected DTMIterator
m_iter
The functional iterator that fetches nodes.
protected DTMManager
m_dtmMgr
The DTMManager to use if we're using a NodeVector only. We may well want to do away with this, and store it in the NodeVector.
Constructors Summary
public NodeSequence(DTMIterator iter, int context, XPathContext xctxt, boolean shouldCacheNodes)
Create a new NodeSequence from a (already cloned) iterator.

param
iter Cloned (not static) DTMIterator.
param
context The initial context node.
param
xctxt The execution context.
param
shouldCacheNodes True if this sequence can random access.

  	setIter(iter);
  	setRoot(context, xctxt);
  	setShouldCacheNodes(shouldCacheNodes);
  
public NodeSequence(Object nodeVector)
Create a new NodeSequence from a (already cloned) iterator.

param
iter Cloned (not static) DTMIterator.

  	super(nodeVector);
  	if(null != nodeVector)
  	{
  		assertion(nodeVector instanceof NodeVector, 
  			"Must have a NodeVector as the object for NodeSequence!");
  		if(nodeVector instanceof DTMIterator)
  		{
  			setIter((DTMIterator)nodeVector);
  			m_last = ((DTMIterator)nodeVector).getLength();
  		}
  		
  	}
  
public NodeSequence(DTMManager dtmMgr)
Construct an empty XNodeSet object. This is used to create a mutable nodeset to which random nodes may be added.

    super(new NodeVector());
    m_last = 0;
    m_dtmMgr = dtmMgr;
  
public NodeSequence()
Create a new NodeSequence in an invalid (null) state.

  
Methods Summary
protected voidSetVector(com.sun.org.apache.xml.internal.utils.NodeVector v)
Set the vector where nodes will be stored.

  	m_obj = v;
  
protected intaddNodeInDocOrder(int node)
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.

      assertion(hasCache(), "addNodeInDocOrder must be done on a mutable sequence!");

      int insertIndex = -1;
      
      NodeVector vec = getVector();

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

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

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

          break;
        }

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

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

        vec.insertElementAt(node, insertIndex);
      }

      // checkDups();
      return insertIndex;
    
public voidallowDetachToRelease(boolean allowRelease)
Calling this with a value of false will cause the nodeset to be cached.

see
DTMIterator#allowDetachToRelease(boolean)

  	if((false == allowRelease) && !hasCache())
  	{
  		setShouldCacheNodes(true);
  	}
  	
  	if(null != m_iter)
  		m_iter.allowDetachToRelease(allowRelease);
  	super.allowDetachToRelease(allowRelease);
  
public java.lang.Objectclone()
Get a clone of this iterator, but don't reset the iteration in the process, so that it may be used from the current position. Note: Not a deep clone.

return
A clone of this object.
throws
CloneNotSupportedException

  	return super.clone();
  
public com.sun.org.apache.xml.internal.dtm.DTMIteratorcloneWithReset()
Note: Not a deep clone.

see
DTMIterator#cloneWithReset()

  	NodeSequence seq = (NodeSequence)super.clone();
    seq.m_next = 0;
    return seq;
  
public voiddetach()

see
DTMIterator#detach()

  	if(null != m_iter)
  		m_iter.detach();
  	super.detach();
  
public voidfixupVariables(java.util.Vector vars, int globalsSize)

see
com.sun.org.apache.xpath.internal.Expression#fixupVariables(Vector, int)

  	super.fixupVariables(vars, globalsSize);
  
public intgetAnalysisBits()

see
PathComponent#getAnalysisBits()

  	if((null != m_iter) && (m_iter instanceof PathComponent))
    	return ((PathComponent)m_iter).getAnalysisBits();
    else
    	return 0;
  
public intgetAxis()

see
DTMIterator#getAxis()

  	if(null != m_iter)
    	return m_iter.getAxis();
    else
    {
    	assertion(false, "Can not getAxis from a non-iterated node sequence!");
    	return 0;
    }
  
public final com.sun.org.apache.xml.internal.dtm.DTMIteratorgetContainedIter()
Get the functional iterator that fetches nodes.

return
The contained iterator.

  	return m_iter;
  
public intgetCurrentNode()

see
DTMIterator#getCurrentNode()

  	if(hasCache())
  	{
  		int currentIndex = m_next-1;
  		NodeVector vec = getVector();
  		if((currentIndex >= 0) && (currentIndex < vec.size()))
  			return vec.elementAt(currentIndex);
  		else
  			return DTM.NULL;
  	}
  	
  	if(null != m_iter)
  	{
    	return m_iter.getCurrentNode();
  	}
  	else
  		return DTM.NULL;
  
public intgetCurrentPos()

see
DTMIterator#getCurrentPos()

    return m_next;
  
public com.sun.org.apache.xml.internal.dtm.DTMgetDTM(int nodeHandle)

see
DTMIterator#getDTM(int)

  	DTMManager mgr = getDTMManager();
  	if(null != mgr)
    	return getDTMManager().getDTM(nodeHandle);
    else
    {
    	assertion(false, "Can not get a DTM Unless a DTMManager has been set!");
    	return null;
    }
  
public com.sun.org.apache.xml.internal.dtm.DTMManagergetDTMManager()

see
DTMIterator#getDTMManager()

    return m_dtmMgr;
  
public booleangetExpandEntityReferences()

see
DTMIterator#getExpandEntityReferences()

  	if(null != m_iter)
  		return m_iter.getExpandEntityReferences();
  	else
    	return true;
  
public intgetLength()

see
DTMIterator#getLength()

  	if(hasCache())
  	{
        // If this NodeSequence wraps a mutable nodeset, then
        // m_last will not reflect the size of the nodeset if
        // it has been mutated...
        if (m_iter instanceof NodeSetDTM)
        {
            return m_iter.getLength();
        }    
        
	  	if(-1 == m_last)
	  	{
	  		int pos = m_next;
	  		runTo(-1);
	  		m_next = pos;
	  	}
	    return m_last;
  	}
  	else
  	{
  		return (-1 == m_last) ? (m_last = m_iter.getLength()) : m_last;
  	}
  
public intgetRoot()

see
DTMIterator#getRoot()

  	if(null != m_iter)
    	return m_iter.getRoot();
  	else
  	{
  		// NodeSetDTM will call this, and so it's not a good thing to throw 
  		// an assertion here.
  		// assertion(false, "Can not get the root from a non-iterated NodeSequence!");
  		return DTM.NULL;
  	}
  
protected com.sun.org.apache.xml.internal.utils.NodeVectorgetVector()
If this iterator needs to cache nodes that are fetched, they are stored in the Vector in the generic object.

    
                         
    
  
  	return (NodeVector)m_obj;
  
public intgetWhatToShow()

see
DTMIterator#getWhatToShow()

    return hasCache() ? (DTMFilter.SHOW_ALL & ~DTMFilter.SHOW_ENTITY_REFERENCE) 
    	: m_iter.getWhatToShow();
  
public booleanhasCache()
If this iterator needs to cache nodes that are fetched, they are stored here.

  	return (m_obj != null);
  
public booleanisDocOrdered()

see
DTMIterator#isDocOrdered()

  	if(null != m_iter)
  		return m_iter.isDocOrdered();
  	else
    	return true; // can't be sure?
  
public booleanisFresh()

see
DTMIterator#isFresh()

    return (0 == m_next);
  
public booleanisMutable()

see
DTMIterator#isMutable()

    return hasCache(); // though may be surprising if it also has an iterator!
  
public intitem(int index)

see
DTMIterator#item(int)

  	setCurrentPos(index);
  	int n = nextNode();
  	m_next = index;
  	return n;
  
public intnextNode()

see
DTMIterator#nextNode()

    // If the cache is on, and the node has already been found, then 
    // just return from the list.
    NodeVector vec = getVector();
    if (null != vec)
    {	
    	if(m_next < vec.size())
    	{
			int next = vec.elementAt(m_next);
	    	m_next++;
	    	return next;
    	}
    	else if((-1 != m_last) || (null == m_iter))
    	{
    		m_next++;
    		return DTM.NULL;
    	}
    }
    
  if (null == m_iter)
    return DTM.NULL;
  
 	int next = m_iter.nextNode();
    if(DTM.NULL != next)
    {
    	if(hasCache())
    	{
    		if(m_iter.isDocOrdered())
    	    {
    			getVector().addElement(next);
    			m_next++;
    		}
    		else
    		{
    			int insertIndex = addNodeInDocOrder(next);
    			if(insertIndex >= 0)
    				m_next++;
    		}
    	}
    	else
    		m_next++;
    }
    else
    {
    	m_last = m_next;
    	m_next++;
    }
    	
    return next;
  
public intpreviousNode()

see
DTMIterator#previousNode()

  	if(hasCache())
  	{
  		if(m_next <= 0)
  			return DTM.NULL;
  		else
  		{
  			m_next--;
  			return item(m_next);
  		}
  	}
  	else
  	{
	    int n = m_iter.previousNode();
	    m_next = m_iter.getCurrentPos();
	    return m_next;
  	}
  
public voidreset()

see
DTMIterator#reset()

  	m_next = 0;
  	// not resetting the iterator on purpose!!!
  
public voidrunTo(int index)

see
DTMIterator#runTo(int)

    int n;
    
    if (-1 == index)
    {
      int pos = m_next;
      while (DTM.NULL != (n = nextNode()));
      m_next = pos;
    }
    else if(m_next == index)
    {
      return;
    }
    else if(hasCache() && m_next < getVector().size())
    {
      m_next = index;
    }
    else if((null == getVector()) && (index < m_next))
    {
      while ((m_next >= index) && DTM.NULL != (n = previousNode()));
    }
    else
    {   
      while ((m_next < index) && DTM.NULL != (n = nextNode()));
    }
    
  
public voidsetCurrentPos(int i)

see
DTMIterator#setCurrentPos(int)

  	runTo(i);
  
public voidsetItem(int node, int index)

see
DTMIterator#setItem(int, int)

  	NodeVector vec = getVector();
  	if(null != vec)
  	{
  		vec.setElementAt(node, index);
  		m_last = vec.size();
  	}
  	else
  		m_iter.setItem(node, index);
  
public final voidsetIter(com.sun.org.apache.xml.internal.dtm.DTMIterator iter)
Set the functional iterator that fetches nodes.

param
iter The iterator that is to be contained.

  	m_iter = iter;
  
public voidsetRoot(int nodeHandle, java.lang.Object environment)

see
DTMIterator#setRoot(int, Object)

  	if(null != m_iter)
  	{
  		XPathContext xctxt = (XPathContext)environment;
  		m_dtmMgr = xctxt.getDTMManager();
  		m_iter.setRoot(nodeHandle, environment);
  		if(!m_iter.isDocOrdered())
  		{
  			if(!hasCache())
  				setShouldCacheNodes(true);
  			runTo(-1);
  			m_next=0;
  		}
  	}
  	else
  		assertion(false, "Can not setRoot on a non-iterated NodeSequence!");
  
public voidsetShouldCacheNodes(boolean b)

see
DTMIterator#setShouldCacheNodes(boolean)

    if (b)
    {
      if(!hasCache())
      {
        SetVector(new NodeVector());
      }
//	  else
//	    getVector().RemoveAllNoClear();  // Is this good?
    }
    else
      SetVector(null);