001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: FilterExprIterator.java 468655 2006-10-28 07:12:06Z minchau $
020 */
021 package org.apache.xpath.axes;
022
023 import org.apache.xml.dtm.DTM;
024 import org.apache.xpath.Expression;
025 import org.apache.xpath.ExpressionOwner;
026 import org.apache.xpath.XPathVisitor;
027 import org.apache.xpath.objects.XNodeSet;
028
029 public class FilterExprIterator extends BasicTestIterator
030 {
031 static final long serialVersionUID = 2552176105165737614L;
032 /** The contained expression. Should be non-null.
033 * @serial */
034 private Expression m_expr;
035
036 /** The result of executing m_expr. Needs to be deep cloned on clone op. */
037 transient private XNodeSet m_exprObj;
038
039 private boolean m_mustHardReset = false;
040 private boolean m_canDetachNodeset = true;
041
042 /**
043 * Create a FilterExprIterator object.
044 *
045 */
046 public FilterExprIterator()
047 {
048 super(null);
049 }
050
051 /**
052 * Create a FilterExprIterator object.
053 *
054 */
055 public FilterExprIterator(Expression expr)
056 {
057 super(null);
058 m_expr = expr;
059 }
060
061 /**
062 * Initialize the context values for this expression
063 * after it is cloned.
064 *
065 * @param context The XPath runtime context for this
066 * transformation.
067 */
068 public void setRoot(int context, Object environment)
069 {
070 super.setRoot(context, environment);
071
072 m_exprObj = FilterExprIteratorSimple.executeFilterExpr(context,
073 m_execContext, getPrefixResolver(),
074 getIsTopLevel(), m_stackFrame, m_expr);
075 }
076
077
078 /**
079 * Get the next node via getNextXXX. Bottlenecked for derived class override.
080 * @return The next node on the axis, or DTM.NULL.
081 */
082 protected int getNextNode()
083 {
084 if (null != m_exprObj)
085 {
086 m_lastFetched = m_exprObj.nextNode();
087 }
088 else
089 m_lastFetched = DTM.NULL;
090
091 return m_lastFetched;
092 }
093
094 /**
095 * Detaches the walker from the set which it iterated over, releasing
096 * any computational resources and placing the iterator in the INVALID
097 * state.
098 */
099 public void detach()
100 {
101 super.detach();
102 m_exprObj.detach();
103 m_exprObj = null;
104 }
105
106 /**
107 * This function is used to fixup variables from QNames to stack frame
108 * indexes at stylesheet build time.
109 * @param vars List of QNames that correspond to variables. This list
110 * should be searched backwards for the first qualified name that
111 * corresponds to the variable reference qname. The position of the
112 * QName in the vector from the start of the vector will be its position
113 * in the stack frame (but variables above the globalsTop value will need
114 * to be offset to the current stack frame).
115 */
116 public void fixupVariables(java.util.Vector vars, int globalsSize)
117 {
118 super.fixupVariables(vars, globalsSize);
119 m_expr.fixupVariables(vars, globalsSize);
120 }
121
122 /**
123 * Get the inner contained expression of this filter.
124 */
125 public Expression getInnerExpression()
126 {
127 return m_expr;
128 }
129
130 /**
131 * Set the inner contained expression of this filter.
132 */
133 public void setInnerExpression(Expression expr)
134 {
135 expr.exprSetParent(this);
136 m_expr = expr;
137 }
138
139 /**
140 * Get the analysis bits for this walker, as defined in the WalkerFactory.
141 * @return One of WalkerFactory#BIT_DESCENDANT, etc.
142 */
143 public int getAnalysisBits()
144 {
145 if (null != m_expr && m_expr instanceof PathComponent)
146 {
147 return ((PathComponent) m_expr).getAnalysisBits();
148 }
149 return WalkerFactory.BIT_FILTER;
150 }
151
152 /**
153 * Returns true if all the nodes in the iteration well be returned in document
154 * order.
155 * Warning: This can only be called after setRoot has been called!
156 *
157 * @return true as a default.
158 */
159 public boolean isDocOrdered()
160 {
161 return m_exprObj.isDocOrdered();
162 }
163
164 class filterExprOwner implements ExpressionOwner
165 {
166 /**
167 * @see ExpressionOwner#getExpression()
168 */
169 public Expression getExpression()
170 {
171 return m_expr;
172 }
173
174 /**
175 * @see ExpressionOwner#setExpression(Expression)
176 */
177 public void setExpression(Expression exp)
178 {
179 exp.exprSetParent(FilterExprIterator.this);
180 m_expr = exp;
181 }
182
183 }
184
185 /**
186 * This will traverse the heararchy, calling the visitor for
187 * each member. If the called visitor method returns
188 * false, the subtree should not be called.
189 *
190 * @param visitor The visitor whose appropriate method will be called.
191 */
192 public void callPredicateVisitors(XPathVisitor visitor)
193 {
194 m_expr.callVisitors(new filterExprOwner(), visitor);
195
196 super.callPredicateVisitors(visitor);
197 }
198
199 /**
200 * @see Expression#deepEquals(Expression)
201 */
202 public boolean deepEquals(Expression expr)
203 {
204 if (!super.deepEquals(expr))
205 return false;
206
207 FilterExprIterator fet = (FilterExprIterator) expr;
208 if (!m_expr.deepEquals(fet.m_expr))
209 return false;
210
211 return true;
212 }
213
214 }