1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath.ri.model.beans;
19
20 import org.apache.commons.jxpath.AbstractFactory;
21 import org.apache.commons.jxpath.JXPathAbstractFactoryException;
22 import org.apache.commons.jxpath.JXPathContext;
23 import org.apache.commons.jxpath.JXPathIntrospector;
24 import org.apache.commons.jxpath.ri.QName;
25 import org.apache.commons.jxpath.ri.model.NodePointer;
26 import org.apache.commons.jxpath.util.ValueUtils;
27
28
29
30
31 public abstract class PropertyPointer extends NodePointer {
32
33 private static final long serialVersionUID = 1L;
34
35
36
37 public static final int UNSPECIFIED_PROPERTY = Integer.MIN_VALUE;
38 private static final Object UNINITIALIZED = new Object();
39
40
41 protected int propertyIndex = UNSPECIFIED_PROPERTY;
42
43
44 protected Object bean;
45
46
47
48
49 private Object value = UNINITIALIZED;
50
51
52
53
54
55
56 public PropertyPointer(final NodePointer parent) {
57 super(parent);
58 }
59
60 @Override
61 public int compareChildNodePointers(final NodePointer pointer1, final NodePointer pointer2) {
62 return getValuePointer().compareChildNodePointers(pointer1, pointer2);
63 }
64
65 @Override
66 public NodePointer createChild(final JXPathContext context, final QName qName, final int index) {
67 final PropertyPointer prop = (PropertyPointer) clone();
68 if (qName != null) {
69 prop.setPropertyName(qName.toString());
70 }
71 prop.setIndex(index);
72 return prop.createPath(context);
73 }
74
75 @Override
76 public NodePointer createChild(final JXPathContext context, final QName qName, final int index, final Object value) {
77 final PropertyPointer prop = (PropertyPointer) clone();
78 if (qName != null) {
79 prop.setPropertyName(qName.toString());
80 }
81 prop.setIndex(index);
82 return prop.createPath(context, value);
83 }
84
85 @Override
86 public NodePointer createPath(final JXPathContext context) {
87 if (getImmediateNode() == null) {
88 final AbstractFactory factory = getAbstractFactory(context);
89 final int inx = index == WHOLE_COLLECTION ? 0 : index;
90 final boolean success = factory.createObject(context, this, getBean(), getPropertyName(), inx);
91 if (!success) {
92 throw new JXPathAbstractFactoryException("Factory " + factory + " could not create an object for path: " + asPath());
93 }
94 }
95 return this;
96 }
97
98 @Override
99 public NodePointer createPath(final JXPathContext context, final Object value) {
100
101 if (index != WHOLE_COLLECTION && index >= getLength()) {
102 createPath(context);
103 }
104 setValue(value);
105 return this;
106 }
107
108 @Override
109 public boolean equals(final Object object) {
110 if (object == this) {
111 return true;
112 }
113 if (!(object instanceof PropertyPointer)) {
114 return false;
115 }
116 final PropertyPointer other = (PropertyPointer) object;
117 if (parent != other.parent && (parent == null || !parent.equals(other.parent))) {
118 return false;
119 }
120 if (getPropertyIndex() != other.getPropertyIndex() || !getPropertyName().equals(other.getPropertyName())) {
121 return false;
122 }
123 final int iThis = index == WHOLE_COLLECTION ? 0 : index;
124 final int iOther = other.index == WHOLE_COLLECTION ? 0 : other.index;
125 return iThis == iOther;
126 }
127
128
129
130
131
132
133 public Object getBean() {
134 if (bean == null) {
135 bean = getImmediateParentPointer().getNode();
136 }
137 return bean;
138 }
139
140 @Override
141 public Object getImmediateNode() {
142 if (value == UNINITIALIZED) {
143 value = index == WHOLE_COLLECTION ? ValueUtils.getValue(getBaseValue()) : ValueUtils.getValue(getBaseValue(), index);
144 }
145 return value;
146 }
147
148
149
150
151
152
153 @Override
154 public NodePointer getImmediateValuePointer() {
155 return newChildNodePointer((NodePointer) clone(), getName(), getImmediateNode());
156 }
157
158
159
160
161
162
163 @Override
164 public int getLength() {
165 final Object baseValue = getBaseValue();
166 return baseValue == null ? 1 : ValueUtils.getLength(baseValue);
167 }
168
169 @Override
170 public QName getName() {
171 return new QName(null, getPropertyName());
172 }
173
174
175
176
177
178
179 public abstract int getPropertyCount();
180
181
182
183
184
185
186 public int getPropertyIndex() {
187 return propertyIndex;
188 }
189
190
191
192
193
194
195 public abstract String getPropertyName();
196
197
198
199
200
201
202 public abstract String[] getPropertyNames();
203
204 @Override
205 public int hashCode() {
206 return getImmediateParentPointer().hashCode() + propertyIndex + index;
207 }
208
209 @Override
210 public boolean isActual() {
211 if (!isActualProperty()) {
212 return false;
213 }
214 return super.isActual();
215 }
216
217
218
219
220
221
222 protected abstract boolean isActualProperty();
223
224 @Override
225 public boolean isCollection() {
226 final Object value = getBaseValue();
227 return value != null && ValueUtils.isCollection(value);
228 }
229
230 @Override
231 public boolean isLeaf() {
232 final Object value = getNode();
233 return value == null || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic();
234 }
235
236
237
238
239
240
241 public void setPropertyIndex(final int index) {
242 if (propertyIndex != index) {
243 propertyIndex = index;
244 setIndex(WHOLE_COLLECTION);
245 }
246 }
247
248
249
250
251
252
253 public abstract void setPropertyName(String propertyName);
254 }