KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > beanutils > LazyDynaClass


1 /*
2  * Copyright 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.beanutils;
17
18 /**
19  * <p>DynaClass which implements the <code>MutableDynaClass</code> interface.</p>
20  *
21  * <p>A <code>MutableDynaClass</code> is a specialized extension to <code>DynaClass</code>
22  * that allows properties to be added or removed dynamically.</p>
23  *
24  * <p>This implementation has one slightly unusual default behaviour - calling
25  * the <code>getDynaProperty(name)</code> method for a property which doesn't
26  * exist returns a <code>DynaProperty</code> rather than <code>null</code>. The
27  * reason for this is that <code>BeanUtils</code> calls this method to check if
28  * a property exists before trying to set the value. This would defeat the object
29  * of the <code>LazyDynaBean</code> which automatically adds missing properties
30  * when any of its <code>set()</code> methods are called. For this reason the
31  * <code>isDynaProperty(name)</code> method has been added to this implementation
32  * in order to determine if a property actually exists. If the more <i>normal</i>
33  * behaviour of returning <code>null</code> is required, then this can be achieved
34  * by calling the <code>setReturnNull(true)</code>.</p>
35  *
36  * <p>The <code>add(name, type, readable, writable)</code> method is not implemented
37  * and always throws an <code>UnsupportedOperationException</code>. I believe
38  * this attributes need to be added to the <code>DynaProperty</code> class
39  * in order to control read/write facilities.</p>
40  *
41  * @see LazyDynaBean
42  * @author Niall Pemberton
43  */

44 public class LazyDynaClass extends BasicDynaClass implements MutableDynaClass {
45
46     /**
47      * Controls whether changes to this DynaClass's properties are allowed.
48      */

49     protected boolean restricted;
50
51     /**
52      * <p>Controls whether the <code>getDynaProperty()</code> method returns
53      * null if a property doesn't exist - or creates a new one.</p>
54      *
55      * <p>Default is <code>false</code>.
56      */

57     protected boolean returnNull = false;
58
59     /**
60      * Construct a new LazyDynaClass with default parameters.
61      */

62     public LazyDynaClass() {
63         this(null, (DynaProperty[])null);
64     }
65
66     /**
67      * Construct a new LazyDynaClass with the specified name.
68      *
69      * @param name Name of this DynaBean class
70      */

71     public LazyDynaClass(String JavaDoc name) {
72         this(name, (DynaProperty[])null);
73     }
74
75     /**
76      * Construct a new LazyDynaClass with the specified name and DynaBean class.
77      *
78      * @param name Name of this DynaBean class
79      * @param dynaBeanClass The implementation class for new instances
80      */

81     public LazyDynaClass(String JavaDoc name, Class JavaDoc dynaBeanClass) {
82         this(name, dynaBeanClass, null);
83     }
84
85     /**
86      * Construct a new LazyDynaClass with the specified name and properties.
87      *
88      * @param name Name of this DynaBean class
89      * @param properties Property descriptors for the supported properties
90      */

91     public LazyDynaClass(String JavaDoc name, DynaProperty[] properties) {
92         this(name, LazyDynaBean.class, properties);
93     }
94
95     /**
96      * Construct a new LazyDynaClass with the specified name, DynaBean class and properties.
97      *
98      * @param name Name of this DynaBean class
99      * @param dynaBeanClass The implementation class for new intances
100      * @param properties Property descriptors for the supported properties
101      */

102     public LazyDynaClass(String JavaDoc name, Class JavaDoc dynaBeanClass, DynaProperty properties[]) {
103         super(name, dynaBeanClass, properties);
104     }
105
106     /**
107      * <p>Is this DynaClass currently restricted.</p>
108      * <p>If restricted, no changes to the existing registration of
109      * property names, data types, readability, or writeability are allowed.</p>
110      */

111     public boolean isRestricted() {
112         return restricted;
113     }
114
115     /**
116      * <p>Set whether this DynaClass is currently restricted.</p>
117      * <p>If restricted, no changes to the existing registration of
118      * property names, data types, readability, or writeability are allowed.</p>
119      */

120     public void setRestricted(boolean restricted) {
121         this.restricted = restricted;
122     }
123
124     /**
125      * Should this DynaClass return a <code>null</code> from
126      * the <code>getDynaProperty(name)</code> method if the property
127      * doesn't exist.
128      */

129     public boolean isReturnNull() {
130         return returnNull;
131     }
132
133     /**
134      * Set whether this DynaClass should return a <code>null</code> from
135      * the <code>getDynaProperty(name)</code> method if the property
136      * doesn't exist.
137      */

138     public void setReturnNull(boolean returnNull) {
139         this.returnNull = returnNull;
140     }
141
142     /**
143      * Add a new dynamic property with no restrictions on data type,
144      * readability, or writeability.
145      *
146      * @param name Name of the new dynamic property
147      *
148      * @exception IllegalArgumentException if name is null
149      * @exception IllegalStateException if this DynaClass is currently
150      * restricted, so no new properties can be added
151      */

152     public void add(String JavaDoc name) {
153         add(new DynaProperty(name));
154     }
155
156     /**
157      * Add a new dynamic property with the specified data type, but with
158      * no restrictions on readability or writeability.
159      *
160      * @param name Name of the new dynamic property
161      * @param type Data type of the new dynamic property (null for no
162      * restrictions)
163      *
164      * @exception IllegalArgumentException if name is null
165      * @exception IllegalStateException if this DynaClass is currently
166      * restricted, so no new properties can be added
167      */

168     public void add(String JavaDoc name, Class JavaDoc type) {
169         add(new DynaProperty(name, type));
170     }
171
172     /**
173      * <p>Add a new dynamic property with the specified data type, readability,
174      * and writeability.</p>
175      *
176      * <p><strong>N.B.</strong>Support for readable/writeable properties has not been implemented
177      * and this method always throws a <code>UnsupportedOperationException</code>.</p>
178      *
179      * <p>I'm not sure the intention of the original authors for this method, but it seems to
180      * me that readable/writable should be attributes of the <code>DynaProperty</code> class
181      * (which they are not) and is the reason this method has not been implemented.</p>
182      *
183      * @param name Name of the new dynamic property
184      * @param type Data type of the new dynamic property (null for no
185      * restrictions)
186      * @param readable Set to <code>true</code> if this property value
187      * should be readable
188      * @param writeable Set to <code>true</code> if this property value
189      * should be writeable
190      *
191      * @exception UnsupportedOperationException anytime this method is called
192      */

193     public void add(String JavaDoc name, Class JavaDoc type, boolean readable, boolean writeable) {
194         throw new java.lang.UnsupportedOperationException JavaDoc("readable/writable properties not supported");
195     }
196
197     /**
198      * Add a new dynamic property.
199      *
200      * @param property Property the new dynamic property to add.
201      *
202      * @exception IllegalArgumentException if name is null
203      * @exception IllegalStateException if this DynaClass is currently
204      * restricted, so no new properties can be added
205      */

206     protected void add(DynaProperty property) {
207
208         if (property.getName() == null) {
209             throw new IllegalArgumentException JavaDoc("Property name is missing.");
210         }
211
212         if (isRestricted()) {
213             throw new IllegalStateException JavaDoc("DynaClass is currently restricted. No new properties can be added.");
214         }
215
216         // Check if property already exists
217
if (propertiesMap.get(property.getName()) != null) {
218            return;
219         }
220
221         // Create a new property array with the specified property
222
DynaProperty[] oldProperties = getDynaProperties();
223         DynaProperty[] newProperties = new DynaProperty[oldProperties.length+1];
224         System.arraycopy(oldProperties, 0, newProperties, 0, oldProperties.length);
225         newProperties[oldProperties.length] = property;
226
227        // Update the properties
228
setProperties(newProperties);
229
230     }
231
232     /**
233      * Remove the specified dynamic property, and any associated data type,
234      * readability, and writeability, from this dynamic class.
235      * <strong>NOTE</strong> - This does <strong>NOT</strong> cause any
236      * corresponding property values to be removed from DynaBean instances
237      * associated with this DynaClass.
238      *
239      * @param name Name of the dynamic property to remove
240      *
241      * @exception IllegalArgumentException if name is null
242      * @exception IllegalStateException if this DynaClass is currently
243      * restricted, so no properties can be removed
244      */

245     public void remove(String JavaDoc name) {
246
247         if (name == null) {
248             throw new IllegalArgumentException JavaDoc("Property name is missing.");
249         }
250
251         if (isRestricted()) {
252             throw new IllegalStateException JavaDoc("DynaClass is currently restricted. No properties can be removed.");
253         }
254
255         // Ignore if property doesn't exist
256
if (propertiesMap.get(name) == null) {
257             return;
258         }
259
260
261         // Create a new property array of without the specified property
262
DynaProperty[] oldProperties = getDynaProperties();
263         DynaProperty[] newProperties = new DynaProperty[oldProperties.length-1];
264         int j = 0;
265         for (int i = 0; i < oldProperties.length; i++) {
266             if (!(name.equals(oldProperties[i].getName()))) {
267                 newProperties[j] = oldProperties[i];
268                 j++;
269             }
270         }
271
272         // Update the properties
273
setProperties(newProperties);
274
275     }
276
277     /**
278      * <p>Return a property descriptor for the specified property.</p>
279      *
280      * <p>If the property is not found and the <code>returnNull</code> indicator is
281      * <code>true</code>, this method always returns <code>null</code>.</p>
282      *
283      * <p>If the property is not found and the <code>returnNull</code> indicator is
284      * <code>false</code> a new property descriptor is created and returned (although
285      * its not actually added to the DynaClass's properties). This is the default
286      * beahviour.</p>
287      *
288      * <p>The reason for not returning a <code>null</code> property descriptor is that
289      * <code>BeanUtils</code> uses this method to check if a property exists
290      * before trying to set it - since these <i>Lazy</i> implementations automatically
291      * add any new properties when they are set, returning <code>null</code> from
292      * this method would defeat their purpose.</p>
293      *
294      * @param name Name of the dynamic property for which a descriptor
295      * is requested
296      *
297      * @exception IllegalArgumentException if no property name is specified
298      */

299     public DynaProperty getDynaProperty(String JavaDoc name) {
300
301         if (name == null) {
302             throw new IllegalArgumentException JavaDoc("Property name is missing.");
303         }
304
305         DynaProperty dynaProperty = (DynaProperty)propertiesMap.get(name);
306
307         // If it doesn't exist and returnNull is false
308
// create a new DynaProperty
309
if (dynaProperty == null && !isReturnNull() && !isRestricted()) {
310             dynaProperty = new DynaProperty(name);
311         }
312
313         return dynaProperty;
314
315     }
316
317     /**
318      * <p>Indicate whether a property actually exists.</p>
319      *
320      * <p><strong>N.B.</strong> Using <code>getDynaProperty(name) == null</code>
321      * doesn't work in this implementation because that method might
322      * return a DynaProperty if it doesn't exist (depending on the
323      * <code>returnNull</code> indicator).</p>
324      *
325      * @exception IllegalArgumentException if no property name is specified
326      */

327     public boolean isDynaProperty(String JavaDoc name) {
328
329         if (name == null) {
330             throw new IllegalArgumentException JavaDoc("Property name is missing.");
331         }
332
333         return propertiesMap.get(name) == null ? false : true;
334
335     }
336
337 }
Popular Tags