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    }