KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jxpath > ri > model > VariablePointer


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.jxpath.ri.model;
17
18 import org.apache.commons.jxpath.AbstractFactory;
19 import org.apache.commons.jxpath.JXPathContext;
20 import org.apache.commons.jxpath.JXPathException;
21 import org.apache.commons.jxpath.JXPathIntrospector;
22 import org.apache.commons.jxpath.Variables;
23 import org.apache.commons.jxpath.ri.QName;
24 import org.apache.commons.jxpath.ri.compiler.NodeTest;
25 import org.apache.commons.jxpath.ri.model.beans.NullPointer;
26 import org.apache.commons.jxpath.util.ValueUtils;
27
28 /**
29  * Pointer to a context variable.
30  *
31  * @author Dmitri Plotnikov
32  * @version $Revision: 1.18 $ $Date: 2004/04/04 22:06:36 $
33  */

34 public class VariablePointer extends NodePointer {
35     private Variables variables;
36     private QName name;
37     private NodePointer valuePointer;
38     private boolean actual;
39
40     public VariablePointer(Variables variables, QName name) {
41         super(null);
42         this.variables = variables;
43         this.name = name;
44         actual = true;
45     }
46
47     public VariablePointer(QName name) {
48         super(null);
49         this.name = name;
50         actual = false;
51     }
52
53     public boolean isContainer() {
54         return true;
55     }
56
57     public QName getName() {
58         return name;
59     }
60
61     public Object JavaDoc getBaseValue() {
62         if (!actual) {
63             throw new JXPathException("Undefined variable: " + name);
64         }
65         return variables.getVariable(name.toString());
66     }
67     
68     public boolean isLeaf() {
69         Object JavaDoc value = getNode();
70         return value == null
71             || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
72     }
73     
74     public boolean isCollection() {
75         Object JavaDoc value = getBaseValue();
76         return value != null && ValueUtils.isCollection(value);
77     }
78
79     public Object JavaDoc getImmediateNode() {
80         Object JavaDoc value = getBaseValue();
81         if (index != WHOLE_COLLECTION) {
82             return ValueUtils.getValue(value, index);
83         }
84         else {
85             return ValueUtils.getValue(value);
86         }
87     }
88
89     public void setValue(Object JavaDoc value) {
90         if (!actual) {
91             throw new JXPathException("Cannot set undefined variable: " + name);
92         }
93         valuePointer = null;
94         if (index != WHOLE_COLLECTION) {
95             Object JavaDoc collection = getBaseValue();
96             ValueUtils.setValue(collection, index, value);
97         }
98         else {
99             variables.declareVariable(name.toString(), value);
100         }
101     }
102
103     public boolean isActual() {
104         return actual;
105     }
106     
107     public void setIndex(int index) {
108         super.setIndex(index);
109         valuePointer = null;
110     }
111
112     public NodePointer getImmediateValuePointer() {
113         if (valuePointer == null) {
114             Object JavaDoc value = null;
115             if (actual) {
116                 value = getImmediateNode();
117                 valuePointer =
118                     NodePointer.newChildNodePointer(this, null, value);
119             }
120             else {
121                 return new NullPointer(this, getName()) {
122                     public Object JavaDoc getImmediateNode() {
123                         throw new JXPathException(
124                             "Undefined variable: " + name);
125                     }
126                 };
127             }
128         }
129         return valuePointer;
130     }
131     
132     public int getLength() {
133         if (actual) {
134             Object JavaDoc value = getBaseValue();
135             if (value == null) {
136                 return 1;
137             }
138             return ValueUtils.getLength(value);
139         }
140         return 0;
141     }
142
143     public NodePointer createPath(JXPathContext context, Object JavaDoc value) {
144         if (actual) {
145             setValue(value);
146             return this;
147         }
148         NodePointer ptr = createPath(context);
149         ptr.setValue(value);
150         return ptr;
151     }
152
153     public NodePointer createPath(JXPathContext context) {
154         if (!actual) {
155             AbstractFactory factory = getAbstractFactory(context);
156             if (!factory.declareVariable(context, name.toString())) {
157                 throw new JXPathException(
158                     "Factory cannot define variable '"
159                         + name
160                         + "' for path: "
161                         + asPath());
162             }
163             findVariables(context);
164             // Assert: actual == true
165
}
166         return this;
167     }
168
169     public NodePointer createChild(
170         JXPathContext context,
171         QName name,
172         int index)
173     {
174         Object JavaDoc collection = createCollection(context, index);
175         if (!isActual() || (index != 0 && index != WHOLE_COLLECTION)) {
176             AbstractFactory factory = getAbstractFactory(context);
177             boolean success =
178                 factory.createObject(
179                     context,
180                     this,
181                     collection,
182                     getName().toString(),
183                     index);
184             if (!success) {
185                 throw new JXPathException(
186                     "Factory could not create object path: " + asPath());
187             }
188             NodePointer cln = (NodePointer) clone();
189             cln.setIndex(index);
190             return cln;
191         }
192         return this;
193     }
194
195     public NodePointer createChild(
196             JXPathContext context,
197             QName name,
198             int index,
199             Object JavaDoc value)
200     {
201         Object JavaDoc collection = createCollection(context, index);
202         ValueUtils.setValue(collection, index, value);
203         NodePointer cl = (NodePointer) clone();
204         cl.setIndex(index);
205         return cl;
206     }
207
208     private Object JavaDoc createCollection(JXPathContext context, int index) {
209         createPath(context);
210
211         Object JavaDoc collection = getBaseValue();
212         if (collection == null) {
213             throw new JXPathException(
214                 "Factory did not assign a collection to variable '"
215                     + name
216                     + "' for path: "
217                     + asPath());
218         }
219
220         if (index == WHOLE_COLLECTION) {
221             index = 0;
222         }
223         else if (index < 0) {
224             throw new JXPathException("Index is less than 1: " + asPath());
225         }
226
227         if (index >= getLength()) {
228             collection = ValueUtils.expandCollection(collection, index + 1);
229             variables.declareVariable(name.toString(), collection);
230         }
231
232         return collection;
233     }
234
235     public void remove() {
236         if (actual) {
237             if (index == WHOLE_COLLECTION) {
238                 variables.undeclareVariable(name.toString());
239             }
240             else {
241                 if (index < 0) {
242                     throw new JXPathException(
243                         "Index is less than 1: " + asPath());
244                 }
245
246                 Object JavaDoc collection = getBaseValue();
247                 if (collection != null && index < getLength()) {
248                     collection = ValueUtils.remove(collection, index);
249                     variables.declareVariable(name.toString(), collection);
250                 }
251             }
252         }
253     }
254
255     protected void findVariables(JXPathContext context) {
256         valuePointer = null;
257         JXPathContext varCtx = context;
258         while (varCtx != null) {
259             variables = varCtx.getVariables();
260             if (variables.isDeclaredVariable(name.toString())) {
261                 actual = true;
262                 break;
263             }
264             varCtx = varCtx.getParentContext();
265             variables = null;
266         }
267     }
268
269     public int hashCode() {
270         return (actual ? System.identityHashCode(variables) : 0)
271             + name.hashCode()
272             + index;
273     }
274
275     public boolean equals(Object JavaDoc object) {
276         if (object == this) {
277             return true;
278         }
279
280         if (!(object instanceof VariablePointer)) {
281             return false;
282         }
283
284         VariablePointer other = (VariablePointer) object;
285         return variables == other.variables
286             && name.equals(other.name)
287             && index == other.index;
288     }
289
290     public String JavaDoc asPath() {
291         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
292         buffer.append('$');
293         buffer.append(name);
294         if (!actual) {
295             if (index != WHOLE_COLLECTION) {
296                 buffer.append('[').append(index + 1).append(']');
297             }
298         }
299         else if (
300             index != WHOLE_COLLECTION
301                 && (getNode() == null || isCollection())) {
302             buffer.append('[').append(index + 1).append(']');
303         }
304         return buffer.toString();
305     }
306
307     public NodeIterator childIterator(
308         NodeTest test,
309         boolean reverse,
310         NodePointer startWith)
311     {
312         return getValuePointer().childIterator(test, reverse, startWith);
313     }
314
315     public NodeIterator attributeIterator(QName name) {
316         return getValuePointer().attributeIterator(name);
317     }
318
319     public NodeIterator namespaceIterator() {
320         return getValuePointer().namespaceIterator();
321     }
322
323     public NodePointer namespacePointer(String JavaDoc name) {
324         return getValuePointer().namespacePointer(name);
325     }
326
327     public boolean testNode(NodeTest nodeTest) {
328         return getValuePointer().testNode(nodeTest);
329     }
330
331     private AbstractFactory getAbstractFactory(JXPathContext context) {
332         AbstractFactory factory = context.getFactory();
333         if (factory == null) {
334             throw new JXPathException(
335               "Factory is not set on the JXPathContext - cannot create path: "
336               + asPath());
337         }
338         return factory;
339     }
340
341     public int compareChildNodePointers(
342         NodePointer pointer1,
343         NodePointer pointer2)
344     {
345         return pointer1.getIndex() - pointer2.getIndex();
346     }
347 }
Popular Tags