1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath.ri.model.beans;
17
18 import java.util.Locale;
19
20 import org.apache.commons.jxpath.JXPathException;
21 import org.apache.commons.jxpath.ri.Compiler;
22 import org.apache.commons.jxpath.ri.QName;
23 import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
24 import org.apache.commons.jxpath.ri.compiler.NodeTest;
25 import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
26 import org.apache.commons.jxpath.ri.model.NodeIterator;
27 import org.apache.commons.jxpath.ri.model.NodePointer;
28 import org.apache.commons.jxpath.util.ValueUtils;
29
30 /***
31 * A pointer describing a node that has properties, each of which could be
32 * a collection.
33 *
34 * @author Dmitri Plotnikov
35 * @version $Revision: 1.19 $ $Date: 2004/04/04 22:06:36 $
36 */
37 public abstract class PropertyOwnerPointer extends NodePointer {
38
39 public NodeIterator childIterator(
40 NodeTest test,
41 boolean reverse,
42 NodePointer startWith)
43 {
44 if (test == null) {
45 return createNodeIterator(null, reverse, startWith);
46 }
47 else if (test instanceof NodeNameTest) {
48 NodeNameTest nodeNameTest = (NodeNameTest) test;
49 QName testName = nodeNameTest.getNodeName();
50 String property;
51 if (!isDefaultNamespace(testName.getPrefix())) {
52 return null;
53 }
54 else if (nodeNameTest.isWildcard()) {
55 property = null;
56 }
57 else {
58 property = testName.getName();
59 }
60 return createNodeIterator(property, reverse, startWith);
61 }
62 else if (test instanceof NodeTypeTest) {
63 if (((NodeTypeTest) test).getNodeType()
64 == Compiler.NODE_TYPE_NODE) {
65 return createNodeIterator(null, reverse, startWith);
66 }
67 }
68 return null;
69 }
70
71 public NodeIterator createNodeIterator(
72 String property,
73 boolean reverse,
74 NodePointer startWith)
75 {
76 return new PropertyIterator(this, property, reverse, startWith);
77 }
78
79 public NodeIterator attributeIterator(QName name) {
80 return new BeanAttributeIterator(this, name);
81 }
82
83 protected PropertyOwnerPointer(NodePointer parent, Locale locale) {
84 super(parent, locale);
85 }
86
87 protected PropertyOwnerPointer(NodePointer parent) {
88 super(parent);
89 }
90
91 public void setIndex(int index) {
92 if (this.index != index) {
93 super.setIndex(index);
94 value = UNINITIALIZED;
95 }
96 }
97
98 private static final Object UNINITIALIZED = new Object();
99
100 private Object value = UNINITIALIZED;
101 public Object getImmediateNode() {
102 if (value == UNINITIALIZED) {
103 if (index == WHOLE_COLLECTION) {
104 value = ValueUtils.getValue(getBaseValue());
105 }
106 else {
107 value = ValueUtils.getValue(getBaseValue(), index);
108 }
109 }
110 return value;
111 }
112
113 public abstract QName getName();
114
115 /***
116 * Throws an exception if you try to change the root element, otherwise
117 * forwards the call to the parent pointer.
118 */
119 public void setValue(Object value) {
120 this.value = value;
121 if (parent.isContainer()) {
122 parent.setValue(value);
123 }
124 else if (parent != null) {
125 if (index == WHOLE_COLLECTION) {
126 throw new UnsupportedOperationException(
127 "Cannot setValue of an object that is not "
128 + "some other object's property");
129 }
130 else {
131 throw new JXPathException(
132 "The specified collection element does not exist: " + this);
133 }
134 }
135 else {
136 throw new UnsupportedOperationException(
137 "Cannot replace the root object");
138 }
139 }
140
141 /***
142 * If this is a root node pointer, throws an exception; otherwise
143 * forwards the call to the parent node.
144 */
145 public void remove() {
146 this.value = null;
147 if (parent != null) {
148 parent.remove();
149 }
150 else {
151 throw new UnsupportedOperationException(
152 "Cannot remove an object that is not "
153 + "some other object's property or a collection element");
154 }
155 }
156
157 public abstract PropertyPointer getPropertyPointer();
158
159 /***
160 * @return true if the property owner can set a property "does not exist".
161 * A good example is a Map. You can always assign a value to any
162 * key even if it has never been "declared".
163 */
164 public boolean isDynamicPropertyDeclarationSupported() {
165 return false;
166 }
167
168 public int compareChildNodePointers(
169 NodePointer pointer1,
170 NodePointer pointer2)
171 {
172 int r =
173 pointer1.getName().toString().compareTo(
174 pointer2.getName().toString());
175 if (r != 0) {
176 return r;
177 }
178 return pointer1.getIndex() - pointer2.getIndex();
179 }
180 }