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: HasPositionalPredChecker.java 468655 2006-10-28 07:12:06Z minchau $
020     */
021    package org.apache.xpath.axes;
022    
023    import org.apache.xpath.Expression;
024    import org.apache.xpath.ExpressionOwner;
025    import org.apache.xpath.XPathVisitor;
026    import org.apache.xpath.functions.FuncLast;
027    import org.apache.xpath.functions.FuncPosition;
028    import org.apache.xpath.functions.Function;
029    import org.apache.xpath.objects.XNumber;
030    import org.apache.xpath.operations.Div;
031    import org.apache.xpath.operations.Minus;
032    import org.apache.xpath.operations.Mod;
033    import org.apache.xpath.operations.Mult;
034    import org.apache.xpath.operations.Plus;
035    import org.apache.xpath.operations.Quo;
036    import org.apache.xpath.operations.Variable;
037    
038    public class HasPositionalPredChecker extends XPathVisitor
039    {
040            private boolean m_hasPositionalPred = false;
041            private int m_predDepth = 0;
042            
043            /**
044             * Process the LocPathIterator to see if it contains variables 
045             * or functions that may make it context dependent.
046             * @param path LocPathIterator that is assumed to be absolute, but needs checking.
047             * @return true if the path is confirmed to be absolute, false if it 
048             * may contain context dependencies.
049             */
050            public static boolean check(LocPathIterator path)
051            {
052                    HasPositionalPredChecker hppc = new HasPositionalPredChecker();
053                    path.callVisitors(null, hppc);
054                    return hppc.m_hasPositionalPred;
055            }
056            
057            /**
058             * Visit a function.
059             * @param owner The owner of the expression, to which the expression can 
060             *              be reset if rewriting takes place.
061             * @param func The function reference object.
062             * @return true if the sub expressions should be traversed.
063             */
064            public boolean visitFunction(ExpressionOwner owner, Function func)
065            {
066                    if((func instanceof FuncPosition) ||
067                       (func instanceof FuncLast))
068                            m_hasPositionalPred = true;
069                    return true;
070            }
071            
072    //      /**
073    //       * Visit a variable reference.
074    //       * @param owner The owner of the expression, to which the expression can 
075    //       *              be reset if rewriting takes place.
076    //       * @param var The variable reference object.
077    //       * @return true if the sub expressions should be traversed.
078    //       */
079    //      public boolean visitVariableRef(ExpressionOwner owner, Variable var)
080    //      {
081    //              m_hasPositionalPred = true;
082    //              return true;
083    //      }
084            
085      /**
086       * Visit a predicate within a location path.  Note that there isn't a 
087       * proper unique component for predicates, and that the expression will 
088       * be called also for whatever type Expression is.
089       * 
090       * @param owner The owner of the expression, to which the expression can 
091       *              be reset if rewriting takes place.
092       * @param pred The predicate object.
093       * @return true if the sub expressions should be traversed.
094       */
095      public boolean visitPredicate(ExpressionOwner owner, Expression pred)
096      {
097        m_predDepth++;
098    
099        if(m_predDepth == 1)
100        {
101          if((pred instanceof Variable) || 
102             (pred instanceof XNumber) ||
103             (pred instanceof Div) ||
104             (pred instanceof Plus) ||
105             (pred instanceof Minus) ||
106             (pred instanceof Mod) ||
107             (pred instanceof Quo) ||
108             (pred instanceof Mult) ||
109             (pred instanceof org.apache.xpath.operations.Number) ||
110             (pred instanceof Function))
111              m_hasPositionalPred = true;
112          else
113            pred.callVisitors(owner, this);
114        }
115    
116        m_predDepth--;
117    
118        // Don't go have the caller go any further down the subtree.
119        return false;
120      }
121    
122    
123    }
124