1. package org.apache.xpath.axes;
  2. import java.util.Vector;
  3. import javax.xml.transform.TransformerException;
  4. import org.apache.xml.dtm.Axis;
  5. import org.apache.xml.dtm.DTM;
  6. import org.apache.xml.utils.PrefixResolver;
  7. import org.apache.xpath.Expression;
  8. import org.apache.xpath.ExpressionOwner;
  9. import org.apache.xpath.VariableStack;
  10. import org.apache.xpath.XPathContext;
  11. import org.apache.xpath.XPathVisitor;
  12. import org.apache.xpath.objects.XNodeSet;
  13. /**
  14. * Class to use for one-step iteration that doesn't have a predicate, and
  15. * doesn't need to set the context.
  16. */
  17. public class FilterExprIteratorSimple extends LocPathIterator
  18. {
  19. /** The contained expression. Should be non-null.
  20. * @serial */
  21. private Expression m_expr;
  22. /** The result of executing m_expr. Needs to be deep cloned on clone op. */
  23. transient private XNodeSet m_exprObj;
  24. private boolean m_mustHardReset = false;
  25. private boolean m_canDetachNodeset = true;
  26. /**
  27. * Create a ChildTestIterator object.
  28. *
  29. * @param traverser Traverser that tells how the KeyIterator is to be handled.
  30. *
  31. * @throws javax.xml.transform.TransformerException
  32. */
  33. public FilterExprIteratorSimple()
  34. {
  35. super(null);
  36. }
  37. /**
  38. * Create a ChildTestIterator object.
  39. *
  40. * @param traverser Traverser that tells how the KeyIterator is to be handled.
  41. *
  42. * @throws javax.xml.transform.TransformerException
  43. */
  44. public FilterExprIteratorSimple(Expression expr)
  45. {
  46. super(null);
  47. m_expr = expr;
  48. }
  49. /**
  50. * Initialize the context values for this expression
  51. * after it is cloned.
  52. *
  53. * @param execContext The XPath runtime context for this
  54. * transformation.
  55. */
  56. public void setRoot(int context, Object environment)
  57. {
  58. super.setRoot(context, environment);
  59. m_exprObj = executeFilterExpr(context, m_execContext, getPrefixResolver(),
  60. getIsTopLevel(), m_stackFrame, m_expr);
  61. }
  62. /**
  63. * Execute the expression. Meant for reuse by other FilterExpr iterators
  64. * that are not derived from this object.
  65. */
  66. public static XNodeSet executeFilterExpr(int context, XPathContext xctxt,
  67. PrefixResolver prefixResolver,
  68. boolean isTopLevel,
  69. int stackFrame,
  70. Expression expr )
  71. throws org.apache.xml.utils.WrappedRuntimeException
  72. {
  73. PrefixResolver savedResolver = xctxt.getNamespaceContext();
  74. XNodeSet result = null;
  75. try
  76. {
  77. xctxt.pushCurrentNode(context);
  78. xctxt.setNamespaceContext(prefixResolver);
  79. // The setRoot operation can take place with a reset operation,
  80. // and so we may not be in the context of LocPathIterator#nextNode,
  81. // so we have to set up the variable context, execute the expression,
  82. // and then restore the variable context.
  83. if (isTopLevel)
  84. {
  85. // System.out.println("calling m_expr.execute(getXPathContext())");
  86. VariableStack vars = xctxt.getVarStack();
  87. // These three statements need to be combined into one operation.
  88. int savedStart = vars.getStackFrame();
  89. vars.setStackFrame(stackFrame);
  90. result = (org.apache.xpath.objects.XNodeSet) expr.execute(xctxt);
  91. result.setShouldCacheNodes(true);
  92. // These two statements need to be combined into one operation.
  93. vars.setStackFrame(savedStart);
  94. }
  95. else
  96. result = (org.apache.xpath.objects.XNodeSet) expr.execute(xctxt);
  97. }
  98. catch (javax.xml.transform.TransformerException se)
  99. {
  100. // TODO: Fix...
  101. throw new org.apache.xml.utils.WrappedRuntimeException(se);
  102. }
  103. finally
  104. {
  105. xctxt.popCurrentNode();
  106. xctxt.setNamespaceContext(savedResolver);
  107. }
  108. return result;
  109. }
  110. /**
  111. * Returns the next node in the set and advances the position of the
  112. * iterator in the set. After a NodeIterator is created, the first call
  113. * to nextNode() returns the first node in the set.
  114. *
  115. * @return The next <code>Node</code> in the set being iterated over, or
  116. * <code>null</code> if there are no more members in that set.
  117. */
  118. public int nextNode()
  119. {
  120. if(m_foundLast)
  121. return DTM.NULL;
  122. int next;
  123. if (null != m_exprObj)
  124. {
  125. m_lastFetched = next = m_exprObj.nextNode();
  126. }
  127. else
  128. m_lastFetched = next = DTM.NULL;
  129. // m_lastFetched = next;
  130. if (DTM.NULL != next)
  131. {
  132. m_pos++;
  133. return next;
  134. }
  135. else
  136. {
  137. m_foundLast = true;
  138. return DTM.NULL;
  139. }
  140. }
  141. /**
  142. * Detaches the walker from the set which it iterated over, releasing
  143. * any computational resources and placing the iterator in the INVALID
  144. * state.
  145. */
  146. public void detach()
  147. {
  148. if(m_allowDetach)
  149. {
  150. super.detach();
  151. m_exprObj.detach();
  152. m_exprObj = null;
  153. }
  154. }
  155. /**
  156. * This function is used to fixup variables from QNames to stack frame
  157. * indexes at stylesheet build time.
  158. * @param vars List of QNames that correspond to variables. This list
  159. * should be searched backwards for the first qualified name that
  160. * corresponds to the variable reference qname. The position of the
  161. * QName in the vector from the start of the vector will be its position
  162. * in the stack frame (but variables above the globalsTop value will need
  163. * to be offset to the current stack frame).
  164. */
  165. public void fixupVariables(java.util.Vector vars, int globalsSize)
  166. {
  167. super.fixupVariables(vars, globalsSize);
  168. m_expr.fixupVariables(vars, globalsSize);
  169. }
  170. /**
  171. * Get the inner contained expression of this filter.
  172. */
  173. public Expression getInnerExpression()
  174. {
  175. return m_expr;
  176. }
  177. /**
  178. * Set the inner contained expression of this filter.
  179. */
  180. public void setInnerExpression(Expression expr)
  181. {
  182. expr.exprSetParent(this);
  183. m_expr = expr;
  184. }
  185. /**
  186. * Get the analysis bits for this walker, as defined in the WalkerFactory.
  187. * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  188. */
  189. public int getAnalysisBits()
  190. {
  191. if (null != m_expr && m_expr instanceof PathComponent)
  192. {
  193. return ((PathComponent) m_expr).getAnalysisBits();
  194. }
  195. return WalkerFactory.BIT_FILTER;
  196. }
  197. /**
  198. * Returns true if all the nodes in the iteration well be returned in document
  199. * order.
  200. * Warning: This can only be called after setRoot has been called!
  201. *
  202. * @return true as a default.
  203. */
  204. public boolean isDocOrdered()
  205. {
  206. return m_exprObj.isDocOrdered();
  207. }
  208. class filterExprOwner implements ExpressionOwner
  209. {
  210. /**
  211. * @see ExpressionOwner#getExpression()
  212. */
  213. public Expression getExpression()
  214. {
  215. return m_expr;
  216. }
  217. /**
  218. * @see ExpressionOwner#setExpression(Expression)
  219. */
  220. public void setExpression(Expression exp)
  221. {
  222. exp.exprSetParent(FilterExprIteratorSimple.this);
  223. m_expr = exp;
  224. }
  225. }
  226. /**
  227. * This will traverse the heararchy, calling the visitor for
  228. * each member. If the called visitor method returns
  229. * false, the subtree should not be called.
  230. *
  231. * @param owner The owner of the visitor, where that path may be
  232. * rewritten if needed.
  233. * @param visitor The visitor whose appropriate method will be called.
  234. */
  235. public void callPredicateVisitors(XPathVisitor visitor)
  236. {
  237. m_expr.callVisitors(new filterExprOwner(), visitor);
  238. super.callPredicateVisitors(visitor);
  239. }
  240. /**
  241. * @see Expression#deepEquals(Expression)
  242. */
  243. public boolean deepEquals(Expression expr)
  244. {
  245. if (!super.deepEquals(expr))
  246. return false;
  247. FilterExprIteratorSimple fet = (FilterExprIteratorSimple) expr;
  248. if (!m_expr.deepEquals(fet.m_expr))
  249. return false;
  250. return true;
  251. }
  252. /**
  253. * Returns the axis being iterated, if it is known.
  254. *
  255. * @return Axis.CHILD, etc., or -1 if the axis is not known or is of multiple
  256. * types.
  257. */
  258. public int getAxis()
  259. {
  260. if(null != m_exprObj)
  261. return m_exprObj.getAxis();
  262. else
  263. return Axis.FILTEREDLIST;
  264. }
  265. }