FileDocCategorySizeDatePackage
NodeSequence.javaAPI DocJava SE 6 API13815Tue Jun 10 00:23:14 BST 2008com.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
static final long
serialVersionUID
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
nodeVector

  	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
node The node to be added.
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

          NodeSequence clone = (NodeSequence) super.clone();
          if (null != m_iter) clone.m_iter = (DTMIterator) m_iter.clone();
          return 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 root is DTM.NULL, then something's wrong with the context
        if (nodeHandle == DTM.NULL) 
        {
            throw new RuntimeException("Unable to evaluate expression using " +
                    "this context");
        }
        
  	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);