001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.jxpath.ri.axes;
018    
019    import org.apache.commons.jxpath.Function;
020    import org.apache.commons.jxpath.JXPathContext;
021    import org.apache.commons.jxpath.NodeSet;
022    import org.apache.commons.jxpath.ri.EvalContext;
023    import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
024    import org.apache.commons.jxpath.ri.QName;
025    import org.apache.commons.jxpath.ri.model.NodePointer;
026    
027    /**
028     * EvalContext that is used to hold the root node for the path traversal.
029     *
030     * @author Dmitri Plotnikov
031     * @version $Revision: 652845 $ $Date: 2008-05-02 12:46:46 -0500 (Fri, 02 May 2008) $
032     */
033    public class RootContext extends EvalContext {
034        private JXPathContextReferenceImpl jxpathContext;
035        private NodePointer pointer;
036        private Object[] registers;
037        private int availableRegister = 0;
038        public static final Object UNKNOWN_VALUE = new Object();
039        private static final int MAX_REGISTER = 4;
040    
041        /**
042         * Create a new RootContext.
043         * @param jxpathContext context
044         * @param pointer pointer
045         */
046        public RootContext(JXPathContextReferenceImpl jxpathContext,
047                NodePointer pointer) {
048            super(null);
049            this.jxpathContext = jxpathContext;
050            this.pointer = pointer;
051            if (pointer != null) {
052                pointer.setNamespaceResolver(jxpathContext.getNamespaceResolver());
053            }
054        }
055    
056        public JXPathContext getJXPathContext() {
057            return jxpathContext;
058        }
059    
060        public RootContext getRootContext() {
061            return this;
062        }
063    
064        /**
065         * Get absolute root context
066         * @return EvalContext
067         */
068        public EvalContext getAbsoluteRootContext() {
069            return jxpathContext.getAbsoluteRootContext();
070        }
071    
072        public NodePointer getCurrentNodePointer() {
073            return pointer;
074        }
075    
076        public Object getValue() {
077            return pointer;
078        }
079    
080        public int getCurrentPosition() {
081            throw new UnsupportedOperationException();
082        }
083    
084        public boolean nextNode() {
085            throw new UnsupportedOperationException();
086        }
087    
088        public boolean nextSet() {
089            throw new UnsupportedOperationException();
090        }
091    
092        public boolean setPosition(int position) {
093            throw new UnsupportedOperationException();
094        }
095    
096        /**
097         * Get a context that points to the specified object.
098         * @param constant object
099         * @return EvalContext
100         */
101        public EvalContext getConstantContext(Object constant) {
102            if (constant instanceof NodeSet) {
103                return new NodeSetContext(
104                    new RootContext(jxpathContext, null),
105                    (NodeSet) constant);
106            }
107    
108            NodePointer pointer;
109            if (constant instanceof NodePointer) {
110                pointer = (NodePointer) constant;
111            }
112            else {
113                pointer = NodePointer.newNodePointer(
114                        new QName(null, ""),
115                        constant,
116                        null);
117            }
118            return new InitialContext(new RootContext(jxpathContext, pointer));
119        }
120    
121        /**
122         * Get variable context.
123         * @param variableName variable name
124         * @return EvalContext
125         */
126        public EvalContext getVariableContext(QName variableName) {
127            return new InitialContext(
128                new RootContext(
129                    jxpathContext,
130                    jxpathContext.getVariablePointer(variableName)));
131        }
132    
133        /**
134         * Get the specified function from the context.
135         * @param functionName QName
136         * @param parameters Object[]
137         * @return Function
138         */
139        public Function getFunction(QName functionName, Object[] parameters) {
140            return jxpathContext.getFunction(functionName, parameters);
141        }
142    
143        /**
144         * Get a registered value.
145         * @param id int
146         * @return Object
147         */
148        public Object getRegisteredValue(int id) {
149            if (registers == null || id >= MAX_REGISTER || id == -1) {
150                return UNKNOWN_VALUE;
151            }
152            return registers[id];
153        }
154    
155        /**
156         * Set the next registered value.
157         * @param value Object
158         * @return the id that can reclaim value.
159         */
160        public int setRegisteredValue(Object value) {
161            if (registers == null) {
162                registers = new Object[MAX_REGISTER];
163                for (int i = 0; i < MAX_REGISTER; i++) {
164                    registers[i] = UNKNOWN_VALUE;
165                }
166            }
167            if (availableRegister >= MAX_REGISTER) {
168                return -1;
169            }
170            registers[availableRegister] = value;
171            availableRegister++;
172            return availableRegister - 1;
173        }
174    
175        public String toString() {
176            return super.toString() + ":" + pointer.asPath();
177        }
178    }