📄 locpathiterator.java
字号:
/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: LocPathIterator.java,v 1.2.4.2 2005/09/14 19:45:22 jeffsuttor Exp $ */package com.sun.org.apache.xpath.internal.axes;import com.sun.org.apache.xalan.internal.res.XSLMessages;import com.sun.org.apache.xml.internal.dtm.DTM;import com.sun.org.apache.xml.internal.dtm.DTMFilter;import com.sun.org.apache.xml.internal.dtm.DTMIterator;import com.sun.org.apache.xml.internal.dtm.DTMManager;import com.sun.org.apache.xml.internal.utils.PrefixResolver;import com.sun.org.apache.xpath.internal.ExpressionOwner;import com.sun.org.apache.xpath.internal.XPathContext;import com.sun.org.apache.xpath.internal.XPathVisitor;import com.sun.org.apache.xpath.internal.compiler.Compiler;import com.sun.org.apache.xpath.internal.objects.XNodeSet;import com.sun.org.apache.xpath.internal.objects.XObject;import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;/** * This class extends NodeSetDTM, which implements NodeIterator, * and fetches nodes one at a time in document order based on a XPath * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a>. * * <p>If setShouldCacheNodes(true) is called, * as each node is iterated via nextNode(), the node is also stored * in the NodeVector, so that previousNode() can easily be done, except in * the case where the LocPathIterator is "owned" by a UnionPathIterator, * in which case the UnionPathIterator will cache the nodes.</p> * @xsl.usage advanced */public abstract class LocPathIterator extends PredicatedNodeTest implements Cloneable, DTMIterator, java.io.Serializable, PathComponent{ static final long serialVersionUID = -4602476357268405754L; /** * Create a LocPathIterator object. * */ protected LocPathIterator() { } /** * Create a LocPathIterator object. * * @param nscontext The namespace context for this iterator, * should be OK if null. */ protected LocPathIterator(PrefixResolver nscontext) { setLocPathIterator(this); m_prefixResolver = nscontext; } /** * Create a LocPathIterator object, including creation * of step walkers from the opcode list, and call back * into the Compiler to create predicate expressions. * * @param compiler The Compiler which is creating * this expression. * @param opPos The position of this iterator in the * opcode list from the compiler. * * @throws javax.xml.transform.TransformerException */ protected LocPathIterator(Compiler compiler, int opPos, int analysis) throws javax.xml.transform.TransformerException { this(compiler, opPos, analysis, true); } /** * Create a LocPathIterator object, including creation * of step walkers from the opcode list, and call back * into the Compiler to create predicate expressions. * * @param compiler The Compiler which is creating * this expression. * @param opPos The position of this iterator in the * opcode list from the compiler. * @param shouldLoadWalkers True if walkers should be * loaded, or false if this is a derived iterator and * it doesn't wish to load child walkers. * * @throws javax.xml.transform.TransformerException */ protected LocPathIterator( Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers) throws javax.xml.transform.TransformerException { setLocPathIterator(this); } /** * Get the analysis bits for this walker, as defined in the WalkerFactory. * @return One of WalkerFactory#BIT_DESCENDANT, etc. */ public int getAnalysisBits() { int axis = getAxis(); int bit = WalkerFactory.getAnalysisBitFromAxes(axis); return bit; } /** * Read the object from a serialization stream. * * @param stream Input stream to read from * * @throws java.io.IOException * @throws javax.xml.transform.TransformerException */ private void readObject(java.io.ObjectInputStream stream) throws java.io.IOException, javax.xml.transform.TransformerException { try { stream.defaultReadObject(); m_clones = new IteratorPool(this); } catch (ClassNotFoundException cnfe) { throw new javax.xml.transform.TransformerException(cnfe); } } /** * 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. * * <p>At this time the exact implementation of this environment is application * dependent. Probably a proper interface will be created fairly soon.</p> * * @param environment The environment object. */ public void setEnvironment(Object environment) { // no-op for now. } /** * 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. */ public DTM getDTM(int nodeHandle) { // %OPT% return m_execContext.getDTM(nodeHandle); } /** * 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. */ public DTMManager getDTMManager() { return m_execContext.getDTMManager(); } /** * Execute this iterator, meaning create a clone that can * store state, and initialize it for fast execution from * the current runtime state. When this is called, no actual * query from the current context node is performed. * * @param xctxt The XPath execution context. * * @return An XNodeSet reference that holds this iterator. * * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance()); iter.setRoot(xctxt.getCurrentNode(), xctxt); return iter; } /** * Execute an expression in the XPath runtime context, and return the * result of the expression. * * * @param xctxt The XPath runtime context. * @param handler The target content handler. * * @return The result of the expression in the form of a <code>XObject</code>. * * @throws javax.xml.transform.TransformerException if a runtime exception * occurs. * @throws org.xml.sax.SAXException */ public void executeCharsToContentHandler( XPathContext xctxt, org.xml.sax.ContentHandler handler) throws javax.xml.transform.TransformerException, org.xml.sax.SAXException { LocPathIterator clone = (LocPathIterator)m_clones.getInstance(); int current = xctxt.getCurrentNode(); clone.setRoot(current, xctxt); int node = clone.nextNode(); DTM dtm = clone.getDTM(node); clone.detach(); if(node != DTM.NULL) { dtm.dispatchCharactersEvents(node, handler, false); } } /** * Given an select expression and a context, evaluate the XPath * and return the resulting iterator. * * @param xctxt The execution context. * @param contextNode The node that "." expresses. * @throws TransformerException thrown if the active ProblemListener decides * the error condition is severe enough to halt processing. * * @throws javax.xml.transform.TransformerException * @xsl.usage experimental */ public DTMIterator asIterator( XPathContext xctxt, int contextNode) throws javax.xml.transform.TransformerException { XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance()); iter.setRoot(contextNode, xctxt); return iter; } /** * Tell if the expression is a nodeset expression. * * @return true if the expression can be represented as a nodeset. */ public boolean isNodesetExpr() { return true; } /** * Return the first node out of the nodeset, if this expression is * a nodeset expression. This is the default implementation for * nodesets. Derived classes should try and override this and return a * value without having to do a clone operation. * @param xctxt The XPath runtime context. * @return the first node out of the nodeset, or DTM.NULL. */ public int asNode(XPathContext xctxt) throws javax.xml.transform.TransformerException { DTMIterator iter = (DTMIterator)m_clones.getInstance(); int current = xctxt.getCurrentNode(); iter.setRoot(current, xctxt); int next = iter.nextNode(); // m_clones.freeInstance(iter); iter.detach(); return next; } /** * Evaluate this operation directly to a boolean. * * @param xctxt The runtime execution context. * * @return The result of the operation as a boolean. * * @throws javax.xml.transform.TransformerException */ public boolean bool(XPathContext xctxt) throws javax.xml.transform.TransformerException { return (asNode(xctxt) != DTM.NULL); } /** * Set if this is an iterator at the upper level of * the XPath. * * @param b true if this location path is at the top level of the * expression. * @xsl.usage advanced */ public void setIsTopLevel(boolean b) { m_isTopLevel = b; } /** * Get if this is an iterator at the upper level of * the XPath. * * @return true if this location path is at the top level of the * expression. * @xsl.usage advanced */ public boolean getIsTopLevel() { return m_isTopLevel; } /** * Initialize the context values for this expression * after it is cloned. * * @param context The XPath runtime context for this * transformation. */ public void setRoot(int context, Object environment) { m_context = context; XPathContext xctxt = (XPathContext)environment; m_execContext = xctxt; m_cdtm = xctxt.getDTM(context); m_currentContextNode = context; // only if top level? // Yech, shouldn't have to do this. -sb if(null == m_prefixResolver) m_prefixResolver = xctxt.getNamespaceContext(); m_lastFetched = DTM.NULL; m_foundLast = false; m_pos = 0; m_length = -1; if (m_isTopLevel) this.m_stackFrame = xctxt.getVarStack().getStackFrame(); // reset(); } /** * Set the next position index of this iterator. * * @param next A value greater than or equal to zero that indicates the next * node position to fetch. */ protected void setNextPosition(int next) { assertion(false, "setNextPosition not supported in this iterator!"); } /** * 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 A value greater than or equal to zero that indicates the next * node position to fetch. */ public final int getCurrentPos() { return m_pos; } /** * If setShouldCacheNodes(true) is called, then nodes will * be cached. They are not cached by default. * * @param b True if this iterator should cache nodes. */ public void setShouldCacheNodes(boolean b) { assertion(false, "setShouldCacheNodes not supported by this iterater!"); } /** * Tells if this iterator can have nodes added to it or set via * the <code>setItem(int node, int index)</code> method. * * @return True if the nodelist can be mutated. */ public boolean isMutable() { return false; } /** * Set the current position in the node set. * * @param i Must be a valid index greater * than or equal to zero and less than m_cachedNodes.size(). */ public void setCurrentPos(int i) { assertion(false, "setCurrentPos not supported by this iterator!"); } /** * Increment the current position in the node set. */ public void incrementCurrentPos() { m_pos++; } /** * Get the length of the cached nodes. * * <p>Note: for the moment at least, this only returns * the size of the nodes that have been fetched to date, * it doesn't attempt to run to the end to make sure we * have found everything. This should be reviewed.</p> * * @return The size of the current cache list. */ public int size() { assertion(false, "size() not supported by this iterator!"); return 0; } /** * Returns the <code>index</code> th item in the collection. If * <code>index</code> is greater than or equal to the number of nodes in * the list, this returns <code>null</code> . * @param index Index into the collection. * @return The node at the <code>index</code> th position in the * <code>NodeList</code> , or <code>null</code> if that is not a valid * index. */ public int item(int index) { assertion(false, "item(int index) not supported by this iterator!"); return 0; } /** * Sets the node at the specified index of this vector to be the * specified node. The previous component at that position is discarded. * * <p>The index must be a value greater than or equal to 0 and less * than the current size of the vector. * The iterator must be in cached mode.</p> * * <p>Meant to be used for sorted iterators.</p> * * @param node Node to set * @param index Index of where to set the node */ public void setItem(int node, int index) { assertion(false, "setItem not supported by this iterator!"); } /** * The number of nodes in the list. The range of valid child node indices * is 0 to <code>length-1</code> inclusive. * * @return The number of nodes in the list, always greater or equal to zero. */ public int getLength() { // Tell if this is being called from within a predicate. boolean isPredicateTest = (this == m_execContext.getSubContextList()); // And get how many total predicates are part of this step. int predCount = getPredicateCount(); // If we have already calculated the length, and the current predicate // is the first predicate, then return the length. We don't cache // the anything but the length of the list to the first predicate. if (-1 != m_length && isPredicateTest && m_predicateIndex < 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -