1. package org.apache.xpath.axes;
  2. import java.util.Vector;
  3. import org.apache.xml.dtm.DTM;
  4. import org.apache.xpath.Expression;
  5. import org.apache.xpath.ExpressionOwner;
  6. import org.apache.xpath.XPathVisitor;
  7. import org.apache.xpath.objects.XNodeSet;
  8. public class FilterExprIterator extends BasicTestIterator
  9. {
  10. /** The contained expression. Should be non-null.
  11. * @serial */
  12. private Expression m_expr;
  13. /** The result of executing m_expr. Needs to be deep cloned on clone op. */
  14. transient private XNodeSet m_exprObj;
  15. private boolean m_mustHardReset = false;
  16. private boolean m_canDetachNodeset = true;
  17. /**
  18. * Create a ChildTestIterator object.
  19. *
  20. * @param traverser Traverser that tells how the KeyIterator is to be handled.
  21. *
  22. * @throws javax.xml.transform.TransformerException
  23. */
  24. public FilterExprIterator()
  25. {
  26. super(null);
  27. }
  28. /**
  29. * Create a ChildTestIterator object.
  30. *
  31. * @param traverser Traverser that tells how the KeyIterator is to be handled.
  32. *
  33. * @throws javax.xml.transform.TransformerException
  34. */
  35. public FilterExprIterator(Expression expr)
  36. {
  37. super(null);
  38. m_expr = expr;
  39. }
  40. /**
  41. * Initialize the context values for this expression
  42. * after it is cloned.
  43. *
  44. * @param execContext The XPath runtime context for this
  45. * transformation.
  46. */
  47. public void setRoot(int context, Object environment)
  48. {
  49. super.setRoot(context, environment);
  50. m_exprObj = FilterExprIteratorSimple.executeFilterExpr(context,
  51. m_execContext, getPrefixResolver(),
  52. getIsTopLevel(), m_stackFrame, m_expr);
  53. }
  54. /**
  55. * Get the next node via getNextXXX. Bottlenecked for derived class override.
  56. * @return The next node on the axis, or DTM.NULL.
  57. */
  58. protected int getNextNode()
  59. {
  60. if (null != m_exprObj)
  61. {
  62. m_lastFetched = m_exprObj.nextNode();
  63. }
  64. else
  65. m_lastFetched = DTM.NULL;
  66. return m_lastFetched;
  67. }
  68. /**
  69. * Detaches the walker from the set which it iterated over, releasing
  70. * any computational resources and placing the iterator in the INVALID
  71. * state.
  72. */
  73. public void detach()
  74. {
  75. super.detach();
  76. m_exprObj.detach();
  77. m_exprObj = null;
  78. }
  79. /**
  80. * This function is used to fixup variables from QNames to stack frame
  81. * indexes at stylesheet build time.
  82. * @param vars List of QNames that correspond to variables. This list
  83. * should be searched backwards for the first qualified name that
  84. * corresponds to the variable reference qname. The position of the
  85. * QName in the vector from the start of the vector will be its position
  86. * in the stack frame (but variables above the globalsTop value will need
  87. * to be offset to the current stack frame).
  88. */
  89. public void fixupVariables(java.util.Vector vars, int globalsSize)
  90. {
  91. super.fixupVariables(vars, globalsSize);
  92. m_expr.fixupVariables(vars, globalsSize);
  93. }
  94. /**
  95. * Get the inner contained expression of this filter.
  96. */
  97. public Expression getInnerExpression()
  98. {
  99. return m_expr;
  100. }
  101. /**
  102. * Set the inner contained expression of this filter.
  103. */
  104. public void setInnerExpression(Expression expr)
  105. {
  106. expr.exprSetParent(this);
  107. m_expr = expr;
  108. }
  109. /**
  110. * Get the analysis bits for this walker, as defined in the WalkerFactory.
  111. * @return One of WalkerFactory#BIT_DESCENDANT, etc.
  112. */
  113. public int getAnalysisBits()
  114. {
  115. if (null != m_expr && m_expr instanceof PathComponent)
  116. {
  117. return ((PathComponent) m_expr).getAnalysisBits();
  118. }
  119. return WalkerFactory.BIT_FILTER;
  120. }
  121. /**
  122. * Returns true if all the nodes in the iteration well be returned in document
  123. * order.
  124. * Warning: This can only be called after setRoot has been called!
  125. *
  126. * @return true as a default.
  127. */
  128. public boolean isDocOrdered()
  129. {
  130. return m_exprObj.isDocOrdered();
  131. }
  132. class filterExprOwner implements ExpressionOwner
  133. {
  134. /**
  135. * @see ExpressionOwner#getExpression()
  136. */
  137. public Expression getExpression()
  138. {
  139. return m_expr;
  140. }
  141. /**
  142. * @see ExpressionOwner#setExpression(Expression)
  143. */
  144. public void setExpression(Expression exp)
  145. {
  146. exp.exprSetParent(FilterExprIterator.this);
  147. m_expr = exp;
  148. }
  149. }
  150. /**
  151. * This will traverse the heararchy, calling the visitor for
  152. * each member. If the called visitor method returns
  153. * false, the subtree should not be called.
  154. *
  155. * @param owner The owner of the visitor, where that path may be
  156. * rewritten if needed.
  157. * @param visitor The visitor whose appropriate method will be called.
  158. */
  159. public void callPredicateVisitors(XPathVisitor visitor)
  160. {
  161. m_expr.callVisitors(new filterExprOwner(), visitor);
  162. super.callPredicateVisitors(visitor);
  163. }
  164. /**
  165. * @see Expression#deepEquals(Expression)
  166. */
  167. public boolean deepEquals(Expression expr)
  168. {
  169. if (!super.deepEquals(expr))
  170. return false;
  171. FilterExprIterator fet = (FilterExprIterator) expr;
  172. if (!m_expr.deepEquals(fet.m_expr))
  173. return false;
  174. return true;
  175. }
  176. }