View Javadoc

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.beans;
17  
18  import java.util.Locale;
19  
20  import org.apache.commons.jxpath.JXPathContext;
21  import org.apache.commons.jxpath.JXPathIntrospector;
22  import org.apache.commons.jxpath.ri.QName;
23  import org.apache.commons.jxpath.ri.compiler.NodeTest;
24  import org.apache.commons.jxpath.ri.model.NodeIterator;
25  import org.apache.commons.jxpath.ri.model.NodePointer;
26  import org.apache.commons.jxpath.util.ValueUtils;
27  
28  /***
29   * Transparent pointer to a collection (array or Collection).
30   *
31   * @author Dmitri Plotnikov
32   * @version $Revision: 1.19 $ $Date: 2004/04/04 22:06:35 $
33   */
34  public class CollectionPointer extends NodePointer {
35      private Object collection;
36      private NodePointer valuePointer;
37  
38      public CollectionPointer(Object collection, Locale locale) {
39          super(null, locale);
40          this.collection = collection;
41      }
42  
43      public CollectionPointer(NodePointer parent, Object collection) {
44          super(parent);
45          this.collection = collection;
46      }
47  
48      public QName getName() {
49          return null;
50      }
51  
52      public Object getBaseValue() {
53          return collection;
54      }
55  
56      public boolean isCollection() {
57          return true;
58      }
59  
60      public int getLength() {
61          return ValueUtils.getLength(getBaseValue());
62      }
63  
64      public boolean isLeaf() {
65          Object value = getNode();
66          return value == null
67              || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
68      }
69  
70      public boolean isContainer() {
71          return index != WHOLE_COLLECTION;
72      }
73  
74      public Object getImmediateNode() {
75          if (index != WHOLE_COLLECTION) {
76              return ValueUtils.getValue(collection, index);
77          }
78          else {
79              return ValueUtils.getValue(collection);
80          }
81      }
82  
83      public void setValue(Object value) {
84          if (index == WHOLE_COLLECTION) {
85              parent.setValue(value);
86          }
87          else {
88              ValueUtils.setValue(collection, index, value);
89          }
90      }
91  
92      public void setIndex(int index) {
93          super.setIndex(index);
94          valuePointer = null;
95      }
96  
97      public NodePointer getValuePointer() {
98          if (valuePointer == null) {
99              if (index == WHOLE_COLLECTION) {
100                 valuePointer = this;
101             }
102             else {
103                 Object value = getImmediateNode();
104                 valuePointer =
105                     NodePointer.newChildNodePointer(this, getName(), value);
106             }
107         }
108         return valuePointer;
109     }
110 
111     public NodePointer createPath(JXPathContext context) {
112         Object collection = getBaseValue();
113         if (ValueUtils.getLength(collection) <= index) {
114             collection = ValueUtils.expandCollection(getNode(), index + 1);
115         }
116         return this;
117     }
118 
119     public NodePointer createPath(JXPathContext context, Object value) {
120         NodePointer ptr = createPath(context);
121         ptr.setValue(value);
122         return ptr;
123     }
124 
125     public NodePointer createChild(
126         JXPathContext context,
127         QName name,
128         int index,
129         Object value) 
130     {
131         NodePointer ptr = (NodePointer) clone();
132         ptr.setIndex(index);
133         return ptr.createPath(context, value);
134     }
135 
136     public NodePointer createChild(
137         JXPathContext context,
138         QName name,
139         int index) 
140     {
141         NodePointer ptr = (NodePointer) clone();
142         ptr.setIndex(index);
143         return ptr.createPath(context);
144     }
145 
146     public int hashCode() {
147         return System.identityHashCode(collection) + index;
148     }
149 
150     public boolean equals(Object object) {
151         if (object == this) {
152             return true;
153         }
154 
155         if (!(object instanceof CollectionPointer)) {
156             return false;
157         }
158 
159         CollectionPointer other = (CollectionPointer) object;
160         return collection == other.collection && index == other.index;
161     }
162 
163     public NodeIterator childIterator(NodeTest test, 
164                 boolean reverse, NodePointer startWith)
165     {
166         if (index == WHOLE_COLLECTION) {
167             return new CollectionChildNodeIterator(
168                 this,
169                 test,
170                 reverse,
171                 startWith);
172         }
173         else {
174             return getValuePointer().childIterator(test, reverse, startWith);
175         }
176     }
177 
178     public NodeIterator attributeIterator(QName name) {
179         if (index == WHOLE_COLLECTION) {
180             return new CollectionAttributeNodeIterator(this, name);
181         }
182         return getValuePointer().attributeIterator(name);
183     }
184 
185     public NodeIterator namespaceIterator() {
186         if (index == WHOLE_COLLECTION) {
187             return null;
188         }
189         return getValuePointer().namespaceIterator();
190     }
191 
192     public NodePointer namespacePointer(String namespace) {
193         if (index == WHOLE_COLLECTION) {
194             return null;
195         }
196         return getValuePointer().namespacePointer(namespace);
197     }
198 
199     public boolean testNode(NodeTest nodeTest) {
200 //        if (index
201         /*** @todo: infinite loop here */
202         return getValuePointer().testNode(nodeTest);
203     }
204 
205     public int compareChildNodePointers(
206                 NodePointer pointer1, NodePointer pointer2)
207     {
208         return pointer1.getIndex() - pointer2.getIndex();
209     }
210 
211     /***
212      * Returns an XPath that maps to this Pointer.
213      */
214     public String asPath() {
215         StringBuffer buffer = new StringBuffer();
216         NodePointer parent = getImmediateParentPointer();
217         if (parent != null) {
218             buffer.append(parent.asPath());
219             if (index != WHOLE_COLLECTION) {
220                 // Address the list[1][2] case
221                 if (parent.getIndex() != WHOLE_COLLECTION) {
222                     buffer.append("/.");
223                 }
224                 buffer.append("[").append(index + 1).append(']');
225             }
226         }
227         else {
228             if (index != WHOLE_COLLECTION) {
229                 buffer.append("/.[").append(index + 1).append(']');
230             }
231             else {
232                 buffer.append("/");
233             }
234         }
235         
236         return buffer.toString();
237     }
238 }