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 */
017package org.apache.commons.jxpath.ri.axes;
018
019import org.apache.commons.jxpath.Function;
020import org.apache.commons.jxpath.JXPathContext;
021import org.apache.commons.jxpath.NodeSet;
022import org.apache.commons.jxpath.ri.EvalContext;
023import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
024import org.apache.commons.jxpath.ri.QName;
025import 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 13:46:46 -0400 (Fri, 02 May 2008) $
032 */
033public 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}