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