View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jxpath.ri.axes;
19  
20  import org.apache.commons.jxpath.Function;
21  import org.apache.commons.jxpath.JXPathContext;
22  import org.apache.commons.jxpath.NodeSet;
23  import org.apache.commons.jxpath.ri.EvalContext;
24  import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
25  import org.apache.commons.jxpath.ri.QName;
26  import org.apache.commons.jxpath.ri.model.NodePointer;
27  
28  /**
29   * EvalContext that is used to hold the root node for the path traversal.
30   */
31  public class RootContext extends EvalContext {
32  
33      /**
34       * Unknown value marker.
35       */
36      public static final Object UNKNOWN_VALUE = new Object();
37  
38      private static final int MAX_REGISTER = 4;
39      private final JXPathContextReferenceImpl jxpathContext;
40      private final NodePointer pointer;
41      private Object[] registers;
42      private int availableRegister;
43  
44      /**
45       * Constructs a new RootContext.
46       *
47       * @param jxpathContext context
48       * @param pointer       pointer
49       */
50      public RootContext(final JXPathContextReferenceImpl jxpathContext, final NodePointer pointer) {
51          super(null);
52          this.jxpathContext = jxpathContext;
53          this.pointer = pointer;
54          if (pointer != null) {
55              pointer.setNamespaceResolver(jxpathContext.getNamespaceResolver());
56          }
57      }
58  
59      /**
60       * Gets absolute root context
61       *
62       * @return EvalContext
63       */
64      public EvalContext getAbsoluteRootContext() {
65          return jxpathContext.getAbsoluteRootContext();
66      }
67  
68      /**
69       * Gets a context that points to the specified object.
70       *
71       * @param constant object
72       * @return EvalContext
73       */
74      public EvalContext getConstantContext(final Object constant) {
75          if (constant instanceof NodeSet) {
76              return new NodeSetContext(new RootContext(jxpathContext, null), (NodeSet) constant);
77          }
78          NodePointer pointer;
79          if (constant instanceof NodePointer) {
80              pointer = (NodePointer) constant;
81          } else {
82              pointer = NodePointer.newNodePointer(new QName(null, ""), constant, null);
83          }
84          return new InitialContext(new RootContext(jxpathContext, pointer));
85      }
86  
87      @Override
88      public NodePointer getCurrentNodePointer() {
89          return pointer;
90      }
91  
92      @Override
93      public int getCurrentPosition() {
94          throw new UnsupportedOperationException();
95      }
96  
97      /**
98       * Gets the specified function from the context.
99       *
100      * @param functionName QName
101      * @param parameters   Object[]
102      * @return Function
103      */
104     public Function getFunction(final QName functionName, final Object[] parameters) {
105         return jxpathContext.getFunction(functionName, parameters);
106     }
107 
108     @Override
109     public JXPathContext getJXPathContext() {
110         return jxpathContext;
111     }
112 
113     /**
114      * Gets a registered value.
115      *
116      * @param id int
117      * @return Object
118      */
119     public Object getRegisteredValue(final int id) {
120         if (registers == null || id >= MAX_REGISTER || id == -1) {
121             return UNKNOWN_VALUE;
122         }
123         return registers[id];
124     }
125 
126     @Override
127     public RootContext getRootContext() {
128         return this;
129     }
130 
131     @Override
132     public Object getValue() {
133         return pointer;
134     }
135 
136     /**
137      * Gets variable context.
138      *
139      * @param variableName variable name
140      * @return EvalContext
141      */
142     public EvalContext getVariableContext(final QName variableName) {
143         return new InitialContext(new RootContext(jxpathContext, jxpathContext.getVariablePointer(variableName)));
144     }
145 
146     @Override
147     public boolean nextNode() {
148         throw new UnsupportedOperationException();
149     }
150 
151     @Override
152     public boolean nextSet() {
153         throw new UnsupportedOperationException();
154     }
155 
156     @Override
157     public boolean setPosition(final int position) {
158         throw new UnsupportedOperationException();
159     }
160 
161     /**
162      * Sets the next registered value.
163      *
164      * @param value Object
165      * @return the id that can reclaim value.
166      */
167     public int setRegisteredValue(final Object value) {
168         if (registers == null) {
169             registers = new Object[MAX_REGISTER];
170             for (int i = 0; i < MAX_REGISTER; i++) {
171                 registers[i] = UNKNOWN_VALUE;
172             }
173         }
174         if (availableRegister >= MAX_REGISTER) {
175             return -1;
176         }
177         registers[availableRegister] = value;
178         availableRegister++;
179         return availableRegister - 1;
180     }
181 
182     @Override
183     public String toString() {
184         return super.toString() + ":" + pointer.asPath();
185     }
186 }