001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.jxpath.ri.model.beans;
017:
018: import java.util.Locale;
019:
020: import org.apache.commons.jxpath.JXPathContext;
021: import org.apache.commons.jxpath.JXPathIntrospector;
022: import org.apache.commons.jxpath.ri.QName;
023: import org.apache.commons.jxpath.ri.compiler.NodeTest;
024: import org.apache.commons.jxpath.ri.model.NodeIterator;
025: import org.apache.commons.jxpath.ri.model.NodePointer;
026: import org.apache.commons.jxpath.util.ValueUtils;
027:
028: /**
029: * Transparent pointer to a collection (array or Collection).
030: *
031: * @author Dmitri Plotnikov
032: * @version $Revision: 1.19 $ $Date: 2004/04/04 22:06:35 $
033: */
034: public class CollectionPointer extends NodePointer {
035: private Object collection;
036: private NodePointer valuePointer;
037:
038: public CollectionPointer(Object collection, Locale locale) {
039: super (null, locale);
040: this .collection = collection;
041: }
042:
043: public CollectionPointer(NodePointer parent, Object collection) {
044: super (parent);
045: this .collection = collection;
046: }
047:
048: public QName getName() {
049: return null;
050: }
051:
052: public Object getBaseValue() {
053: return collection;
054: }
055:
056: public boolean isCollection() {
057: return true;
058: }
059:
060: public int getLength() {
061: return ValueUtils.getLength(getBaseValue());
062: }
063:
064: public boolean isLeaf() {
065: Object value = getNode();
066: return value == null
067: || JXPathIntrospector.getBeanInfo(value.getClass())
068: .isAtomic();
069: }
070:
071: public boolean isContainer() {
072: return index != WHOLE_COLLECTION;
073: }
074:
075: public Object getImmediateNode() {
076: if (index != WHOLE_COLLECTION) {
077: return ValueUtils.getValue(collection, index);
078: } else {
079: return ValueUtils.getValue(collection);
080: }
081: }
082:
083: public void setValue(Object value) {
084: if (index == WHOLE_COLLECTION) {
085: parent.setValue(value);
086: } else {
087: ValueUtils.setValue(collection, index, value);
088: }
089: }
090:
091: public void setIndex(int index) {
092: super .setIndex(index);
093: valuePointer = null;
094: }
095:
096: public NodePointer getValuePointer() {
097: if (valuePointer == null) {
098: if (index == WHOLE_COLLECTION) {
099: valuePointer = this ;
100: } else {
101: Object value = getImmediateNode();
102: valuePointer = NodePointer.newChildNodePointer(this ,
103: getName(), value);
104: }
105: }
106: return valuePointer;
107: }
108:
109: public NodePointer createPath(JXPathContext context) {
110: Object collection = getBaseValue();
111: if (ValueUtils.getLength(collection) <= index) {
112: collection = ValueUtils.expandCollection(getNode(),
113: index + 1);
114: }
115: return this ;
116: }
117:
118: public NodePointer createPath(JXPathContext context, Object value) {
119: NodePointer ptr = createPath(context);
120: ptr.setValue(value);
121: return ptr;
122: }
123:
124: public NodePointer createChild(JXPathContext context, QName name,
125: int index, Object value) {
126: NodePointer ptr = (NodePointer) clone();
127: ptr.setIndex(index);
128: return ptr.createPath(context, value);
129: }
130:
131: public NodePointer createChild(JXPathContext context, QName name,
132: int index) {
133: NodePointer ptr = (NodePointer) clone();
134: ptr.setIndex(index);
135: return ptr.createPath(context);
136: }
137:
138: public int hashCode() {
139: return System.identityHashCode(collection) + index;
140: }
141:
142: public boolean equals(Object object) {
143: if (object == this ) {
144: return true;
145: }
146:
147: if (!(object instanceof CollectionPointer)) {
148: return false;
149: }
150:
151: CollectionPointer other = (CollectionPointer) object;
152: return collection == other.collection && index == other.index;
153: }
154:
155: public NodeIterator childIterator(NodeTest test, boolean reverse,
156: NodePointer startWith) {
157: if (index == WHOLE_COLLECTION) {
158: return new CollectionChildNodeIterator(this , test, reverse,
159: startWith);
160: } else {
161: return getValuePointer().childIterator(test, reverse,
162: startWith);
163: }
164: }
165:
166: public NodeIterator attributeIterator(QName name) {
167: if (index == WHOLE_COLLECTION) {
168: return new CollectionAttributeNodeIterator(this , name);
169: }
170: return getValuePointer().attributeIterator(name);
171: }
172:
173: public NodeIterator namespaceIterator() {
174: if (index == WHOLE_COLLECTION) {
175: return null;
176: }
177: return getValuePointer().namespaceIterator();
178: }
179:
180: public NodePointer namespacePointer(String namespace) {
181: if (index == WHOLE_COLLECTION) {
182: return null;
183: }
184: return getValuePointer().namespacePointer(namespace);
185: }
186:
187: public boolean testNode(NodeTest nodeTest) {
188: // if (index
189: /** @todo: infinite loop here */
190: return getValuePointer().testNode(nodeTest);
191: }
192:
193: public int compareChildNodePointers(NodePointer pointer1,
194: NodePointer pointer2) {
195: return pointer1.getIndex() - pointer2.getIndex();
196: }
197:
198: /**
199: * Returns an XPath that maps to this Pointer.
200: */
201: public String asPath() {
202: StringBuffer buffer = new StringBuffer();
203: NodePointer parent = getImmediateParentPointer();
204: if (parent != null) {
205: buffer.append(parent.asPath());
206: if (index != WHOLE_COLLECTION) {
207: // Address the list[1][2] case
208: if (parent.getIndex() != WHOLE_COLLECTION) {
209: buffer.append("/.");
210: }
211: buffer.append("[").append(index + 1).append(']');
212: }
213: } else {
214: if (index != WHOLE_COLLECTION) {
215: buffer.append("/.[").append(index + 1).append(']');
216: } else {
217: buffer.append("/");
218: }
219: }
220:
221: return buffer.toString();
222: }
223: }
|