KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jxpath > ri > model > dynamic > DynamicPropertyPointer


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.dynamic;
17
18 import java.util.Arrays JavaDoc;
19 import java.util.Map JavaDoc;
20
21 import org.apache.commons.jxpath.AbstractFactory;
22 import org.apache.commons.jxpath.DynamicPropertyHandler;
23 import org.apache.commons.jxpath.JXPathContext;
24 import org.apache.commons.jxpath.JXPathException;
25 import org.apache.commons.jxpath.ri.model.NodePointer;
26 import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
27 import org.apache.commons.jxpath.util.ValueUtils;
28
29 /**
30  * Pointer pointing to a property of an object with dynamic properties.
31  *
32  * @author Dmitri Plotnikov
33  * @version $Revision: 1.8 $ $Date: 2004/04/04 22:06:36 $
34  */

35 public class DynamicPropertyPointer extends PropertyPointer {
36     private DynamicPropertyHandler handler;
37     private String JavaDoc name;
38     private String JavaDoc[] names;
39     private String JavaDoc requiredPropertyName;
40
41     public DynamicPropertyPointer(
42             NodePointer parent,
43             DynamicPropertyHandler handler)
44     {
45         super(parent);
46         this.handler = handler;
47     }
48     /**
49      * This type of node is auxiliary.
50      */

51     public boolean isContainer() {
52         return true;
53     }
54
55     /**
56      * Number of the DP object's properties.
57      */

58     public int getPropertyCount() {
59         return getPropertyNames().length;
60     }
61
62     /**
63      * Names of all properties, sorted alphabetically
64      */

65     public String JavaDoc[] getPropertyNames() {
66         if (names == null) {
67             String JavaDoc allNames[] = handler.getPropertyNames(getBean());
68             names = new String JavaDoc[allNames.length];
69             for (int i = 0; i < names.length; i++) {
70                 names[i] = allNames[i];
71             }
72             Arrays.sort(names);
73             if (requiredPropertyName != null) {
74                 int inx = Arrays.binarySearch(names, requiredPropertyName);
75                 if (inx < 0) {
76                     allNames = names;
77                     names = new String JavaDoc[allNames.length + 1];
78                     names[0] = requiredPropertyName;
79                     System.arraycopy(allNames, 0, names, 1, allNames.length);
80                     Arrays.sort(names);
81                 }
82             }
83         }
84         return names;
85     }
86
87     /**
88      * Returns the name of the currently selected property or "*"
89      * if none has been selected.
90      */

91     public String JavaDoc getPropertyName() {
92         if (name == null) {
93             String JavaDoc names[] = getPropertyNames();
94             if (propertyIndex >= 0 && propertyIndex < names.length) {
95                 name = names[propertyIndex];
96             }
97             else {
98                 name = "*";
99             }
100         }
101         return name;
102     }
103
104     /**
105      * Select a property by name. If the supplied name is
106      * not one of the object's existing properties, it implicitly
107      * adds this name to the object's property name list. It does not
108      * set the property value though. In order to set the property
109      * value, call setValue().
110      */

111     public void setPropertyName(String JavaDoc propertyName) {
112         setPropertyIndex(UNSPECIFIED_PROPERTY);
113         this.name = propertyName;
114         requiredPropertyName = propertyName;
115         if (names != null && Arrays.binarySearch(names, propertyName) < 0) {
116             names = null;
117         }
118     }
119
120     /**
121      * Index of the currently selected property in the list of all
122      * properties sorted alphabetically.
123      */

124     public int getPropertyIndex() {
125         if (propertyIndex == UNSPECIFIED_PROPERTY) {
126             String JavaDoc names[] = getPropertyNames();
127             for (int i = 0; i < names.length; i++) {
128                 if (names[i].equals(name)) {
129                     setPropertyIndex(i);
130                     break;
131                 }
132             }
133         }
134         return super.getPropertyIndex();
135     }
136
137     /**
138      * Index a property by its index in the list of all
139      * properties sorted alphabetically.
140      */

141     public void setPropertyIndex(int index) {
142         if (propertyIndex != index) {
143             super.setPropertyIndex(index);
144             name = null;
145         }
146     }
147
148     /**
149      * Returns the value of the property, not an element of the collection
150      * represented by the property, if any.
151      */

152     public Object JavaDoc getBaseValue() {
153         return handler.getProperty(getBean(), getPropertyName());
154     }
155
156     /**
157      * If index == WHOLE_COLLECTION, the value of the property, otherwise
158      * the value of the index'th element of the collection represented by the
159      * property. If the property is not a collection, index should be zero
160      * and the value will be the property itself.
161      */

162     public Object JavaDoc getImmediateNode() {
163         Object JavaDoc value;
164         if (index == WHOLE_COLLECTION) {
165             value = ValueUtils.getValue(handler.getProperty(
166                     getBean(),
167                     getPropertyName()));
168         }
169         else {
170             value = ValueUtils.getValue(handler.getProperty(
171                     getBean(),
172                     getPropertyName()), index);
173         }
174         return value;
175     }
176
177     /**
178      * A dynamic property is always considered actual - all keys are apparently
179      * existing with possibly the value of null.
180      */

181     protected boolean isActualProperty() {
182         return true;
183     }
184
185     /**
186      * If index == WHOLE_COLLECTION, change the value of the property, otherwise
187      * change the value of the index'th element of the collection
188      * represented by the property.
189      */

190     public void setValue(Object JavaDoc value) {
191         if (index == WHOLE_COLLECTION) {
192             handler.setProperty(getBean(), getPropertyName(), value);
193         }
194         else {
195             ValueUtils.setValue(
196                 handler.getProperty(getBean(), getPropertyName()),
197                 index,
198                 value);
199         }
200     }
201
202     public NodePointer createPath(JXPathContext context) {
203         // Ignore the name passed to us, use our own data
204
Object JavaDoc collection = getBaseValue();
205         if (collection == null) {
206             AbstractFactory factory = getAbstractFactory(context);
207             boolean success =
208                 factory.createObject(
209                     context,
210                     this,
211                     getBean(),
212                     getPropertyName(),
213                     0);
214             if (!success) {
215                 throw new JXPathException(
216                     "Factory could not create an object for path: " + asPath());
217             }
218             collection = getBaseValue();
219         }
220
221         if (index != WHOLE_COLLECTION) {
222             if (index < 0) {
223                 throw new JXPathException("Index is less than 1: " + asPath());
224             }
225     
226             if (index >= getLength()) {
227                 collection = ValueUtils.expandCollection(collection, index + 1);
228                 handler.setProperty(getBean(), getPropertyName(), collection);
229             }
230         }
231         
232         return this;
233     }
234     
235     public NodePointer createPath(JXPathContext context, Object JavaDoc value) {
236         if (index == WHOLE_COLLECTION) {
237             handler.setProperty(getBean(), getPropertyName(), value);
238         }
239         else {
240             createPath(context);
241             ValueUtils.setValue(getBaseValue(), index, value);
242         }
243         return this;
244     }
245
246     public void remove() {
247         if (index == WHOLE_COLLECTION) {
248             removeKey();
249         }
250         else if (isCollection()) {
251             Object JavaDoc collection = ValueUtils.remove(getBaseValue(), index);
252             handler.setProperty(getBean(), getPropertyName(), collection);
253         }
254         else if (index == 0) {
255             removeKey();
256         }
257     }
258
259     private void removeKey() {
260         Object JavaDoc bean = getBean();
261         if (bean instanceof Map JavaDoc) {
262             ((Map JavaDoc) bean).remove(getPropertyName());
263         }
264         else {
265             handler.setProperty(bean, getPropertyName(), null);
266         }
267     }
268     
269     public String JavaDoc asPath() {
270         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
271         buffer.append(getImmediateParentPointer().asPath());
272         if (buffer.length() == 0) {
273             buffer.append("/.");
274         }
275         else if (buffer.charAt(buffer.length() - 1) == '/') {
276             buffer.append('.');
277         }
278         buffer.append("[@name='");
279         buffer.append(escape(getPropertyName()));
280         buffer.append("']");
281         if (index != WHOLE_COLLECTION && isCollection()) {
282             buffer.append('[').append(index + 1).append(']');
283         }
284         return buffer.toString();
285     }
286
287     private String JavaDoc escape(String JavaDoc string) {
288         int index = string.indexOf('\'');
289         while (index != -1) {
290             string =
291                 string.substring(0, index)
292                     + "&apos;"
293                     + string.substring(index + 1);
294             index = string.indexOf('\'');
295         }
296         index = string.indexOf('\"');
297         while (index != -1) {
298             string =
299                 string.substring(0, index)
300                     + "&quot;"
301                     + string.substring(index + 1);
302             index = string.indexOf('\"');
303         }
304         return string;
305     }
306
307     private AbstractFactory getAbstractFactory(JXPathContext context) {
308         AbstractFactory factory = context.getFactory();
309         if (factory == null) {
310             throw new JXPathException(
311                 "Factory is not set on the JXPathContext - cannot create path: "
312                     + asPath());
313         }
314         return factory;
315     }
316 }
Popular Tags