Source Code Cross Referenced for LazyDynaBean.java in  » Library » Apache-commons-beanutils-1.8.0-BETA-src » org » apache » commons » beanutils » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache commons beanutils 1.8.0 BETA src » org.apache.commons.beanutils 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.commons.beanutils;
018:
019:        import java.util.List;
020:        import java.util.ArrayList;
021:        import java.util.Map;
022:        import java.util.HashMap;
023:        import java.util.Date;
024:        import java.lang.reflect.Array;
025:        import java.math.BigDecimal;
026:        import java.math.BigInteger;
027:        import java.io.Serializable;
028:        import org.apache.commons.logging.Log;
029:        import org.apache.commons.logging.LogFactory;
030:
031:        /**
032:         * <p>DynaBean which automatically adds properties to the <code>DynaClass</code>
033:         *   and provides <i>Lazy List</i> and <i>Lazy Map</i> features.</p>
034:         *
035:         * <p>DynaBeans deal with three types of properties - <i>simple</i>, <i>indexed</i> and <i>mapped</i> and
036:         *    have the following <code>get()</code> and <code>set()</code> methods for
037:         *    each of these types:</p>
038:         *    <ul>
039:         *        <li><i>Simple</i> property methods - <code>get(name)</code> and
040:         *                          <code>set(name, value)</code></li>
041:         *        <li><i>Indexed</i> property methods - <code>get(name, index)</code> and
042:         *                          <code>set(name, index, value)</code></li>
043:         *        <li><i>Mapped</i> property methods - <code>get(name, key)</code> and
044:         *                          <code>set(name, key, value)</code></li>
045:         *    </ul>
046:         *
047:         * <p><b><u>Getting Property Values</u></b></p>
048:         * <p>Calling any of the <code>get()</code> methods, for a property which
049:         *    doesn't exist, returns <code>null</code> in this implementation.</p>
050:         *
051:         * <p><b><u>Setting Simple Properties</u></b></p>
052:         *    <p>The <code>LazyDynaBean</code> will automatically add a property to the <code>DynaClass</code>
053:         *       if it doesn't exist when the <code>set(name, value)</code> method is called.</p>
054:         *
055:         *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
056:         *     <code>myBean.set("myProperty", "myValue");</code></br>
057:         *
058:         * <p><b><u>Setting Indexed Properties</u></b></p>
059:         *    <p>If the property <b>doesn't</b> exist, the <code>LazyDynaBean</code> will automatically add
060:         *       a property with an <code>ArrayList</code> type to the <code>DynaClass</code> when
061:         *       the <code>set(name, index, value)</code> method is called.
062:         *       It will also instantiate a new <code>ArrayList</code> and automatically <i>grow</i>
063:         *       the <code>List</code> so that it is big enough to accomodate the index being set.
064:         *       <code>ArrayList</code> is the default indexed property that LazyDynaBean uses but
065:         *       this can be easily changed by overriding the <code>defaultIndexedProperty(name)</code>
066:         *       method.</p>
067:         *
068:         *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
069:         *     <code>myBean.set("myIndexedProperty", 0, "myValue1");</code></br>
070:         *     <code>myBean.set("myIndexedProperty", 1, "myValue2");</code></br>
071:         *
072:         *    <p>If the indexed property <b>does</b> exist in the <code>DynaClass</code> but is set to
073:         *      <code>null</code> in the <code>LazyDynaBean</code>, then it will instantiate a
074:         *      new <code>List</code> or <code>Array</code> as specified by the property's type
075:         *      in the <code>DynaClass</code> and automatically <i>grow</i> the <code>List</code>
076:         *      or <code>Array</code> so that it is big enough to accomodate the index being set.</p>
077:         *
078:         *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
079:         *     <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();</code></br>
080:         *     <code>myClass.add("myIndexedProperty", int[].class);</code></br>
081:         *     <code>myBean.set("myIndexedProperty", 0, new Integer(10));</code></br>
082:         *     <code>myBean.set("myIndexedProperty", 1, new Integer(20));</code></br>
083:         *
084:         * <p><b><u>Setting Mapped Properties</u></b></p>
085:         *    <p>If the property <b>doesn't</b> exist, the <code>LazyDynaBean</code> will automatically add
086:         *       a property with a <code>HashMap</code> type to the <code>DynaClass</code> and
087:         *       instantiate a new <code>HashMap</code> in the DynaBean when the
088:         *       <code>set(name, key, value)</code> method is called. <code>HashMap</code> is the default
089:         *       mapped property that LazyDynaBean uses but this can be easily changed by overriding
090:         *       the <code>defaultMappedProperty(name)</code> method.</p>
091:         *
092:         *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
093:         *     <code>myBean.set("myMappedProperty", "myKey", "myValue");</code></br>
094:         *
095:         *    <p>If the mapped property <b>does</b> exist in the <code>DynaClass</code> but is set to
096:         *      <code>null</code> in the <code>LazyDynaBean</code>, then it will instantiate a
097:         *      new <code>Map</code> as specified by the property's type in the <code>DynaClass</code>.</p>
098:         *
099:         *     <code>DynaBean myBean = new LazyDynaBean();</code></br>
100:         *     <code>MutableDynaClass myClass = (MutableDynaClass)myBean.getDynaClass();</code></br>
101:         *     <code>myClass.add("myMappedProperty", TreeMap.class);</code></br>
102:         *     <code>myBean.set("myMappedProperty", "myKey", "myValue");</code></br>
103:         *
104:         * <p><b><u><i>Restricted</i> DynaClass</u></b></p>
105:         *    <p><code>MutableDynaClass</code> have a facility to <i>restrict</i> the <code>DynaClass</code>
106:         *       so that its properties cannot be modified. If the <code>MutableDynaClass</code> is
107:         *       restricted then calling any of the <code>set()</code> methods for a property which
108:         *       doesn't exist will result in a <code>IllegalArgumentException</code> being thrown.</p>
109:         *
110:         * @see LazyDynaClass
111:         * @author Niall Pemberton
112:         */
113:        public class LazyDynaBean implements  DynaBean, Serializable {
114:
115:            /**
116:             * Commons Logging
117:             */
118:            private transient Log logger = LogFactory
119:                    .getLog(LazyDynaBean.class);
120:
121:            /** BigInteger Zero */
122:            protected static final BigInteger BigInteger_ZERO = new BigInteger(
123:                    "0");
124:            /** BigDecimal Zero */
125:            protected static final BigDecimal BigDecimal_ZERO = new BigDecimal(
126:                    "0");
127:            /** Character Space */
128:            protected static final Character Character_SPACE = new Character(
129:                    ' ');
130:            /** Byte Zero */
131:            protected static final Byte Byte_ZERO = new Byte((byte) 0);
132:            /** Short Zero */
133:            protected static final Short Short_ZERO = new Short((short) 0);
134:            /** Integer Zero */
135:            protected static final Integer Integer_ZERO = new Integer(0);
136:            /** Long Zero */
137:            protected static final Long Long_ZERO = new Long(0);
138:            /** Float Zero */
139:            protected static final Float Float_ZERO = new Float((byte) 0);
140:            /** Double Zero */
141:            protected static final Double Double_ZERO = new Double((byte) 0);
142:
143:            /**
144:             * The <code>MutableDynaClass</code> "base class" that this DynaBean
145:             * is associated with.
146:             */
147:            protected Map values;
148:
149:            /** Map decorator for this DynaBean */
150:            private transient Map mapDecorator;
151:
152:            /**
153:             * The <code>MutableDynaClass</code> "base class" that this DynaBean
154:             * is associated with.
155:             */
156:            protected MutableDynaClass dynaClass;
157:
158:            // ------------------- Constructors ----------------------------------
159:
160:            /**
161:             * Construct a new <code>LazyDynaBean</code> with a <code>LazyDynaClass</code> instance.
162:             */
163:            public LazyDynaBean() {
164:                this (new LazyDynaClass());
165:            }
166:
167:            /**
168:             * Construct a new <code>LazyDynaBean</code> with a <code>LazyDynaClass</code> instance.
169:             *
170:             * @param name Name of this DynaBean class
171:             */
172:            public LazyDynaBean(String name) {
173:                this (new LazyDynaClass(name));
174:            }
175:
176:            /**
177:             * Construct a new <code>DynaBean</code> associated with the specified
178:             * <code>DynaClass</code> instance - if its not a <code>MutableDynaClass</code>
179:             * then a new <code>LazyDynaClass</code> is created and the properties copied.
180:             *
181:             * @param dynaClass The DynaClass we are associated with
182:             */
183:            public LazyDynaBean(DynaClass dynaClass) {
184:
185:                values = newMap();
186:
187:                if (dynaClass instanceof  MutableDynaClass) {
188:                    this .dynaClass = (MutableDynaClass) dynaClass;
189:                } else {
190:                    this .dynaClass = new LazyDynaClass(dynaClass.getName(),
191:                            dynaClass.getDynaProperties());
192:                }
193:
194:            }
195:
196:            // ------------------- Public Methods ----------------------------------
197:
198:            /**
199:             * Return a Map representation of this DynaBean.
200:             * </p>
201:             * This, for example, could be used in JSTL in the following way to access
202:             * a DynaBean's <code>fooProperty</code>:
203:             * <ul><li><code>${myDynaBean.<b>map</b>.fooProperty}</code></li></ul>
204:             *
205:             * @return a Map representation of this DynaBean
206:             */
207:            public Map getMap() {
208:                // cache the Map
209:                if (mapDecorator == null) {
210:                    mapDecorator = new DynaBeanMapDecorator(this );
211:                }
212:                return mapDecorator;
213:            }
214:
215:            /**
216:             * <p>Return the size of an indexed or mapped property.</p>
217:             *
218:             * @param name Name of the property
219:             * @return The indexed or mapped property size
220:             * @exception IllegalArgumentException if no property name is specified
221:             */
222:            public int size(String name) {
223:
224:                if (name == null) {
225:                    throw new IllegalArgumentException(
226:                            "No property name specified");
227:                }
228:
229:                Object value = values.get(name);
230:                if (value == null) {
231:                    return 0;
232:                }
233:
234:                if (value instanceof  Map) {
235:                    return ((Map) value).size();
236:                }
237:
238:                if (value instanceof  List) {
239:                    return ((List) value).size();
240:                }
241:
242:                if ((value.getClass().isArray())) {
243:                    return Array.getLength(value);
244:                }
245:
246:                return 0;
247:
248:            }
249:
250:            // ------------------- DynaBean Methods ----------------------------------
251:
252:            /**
253:             * Does the specified mapped property contain a value for the specified
254:             * key value?
255:             *
256:             * @param name Name of the property to check
257:             * @param key Name of the key to check
258:             * @return <code>true<code> if the mapped property contains a value for
259:             * the specified key, otherwise <code>false</code>
260:             *
261:             * @exception IllegalArgumentException if no property name is specified
262:             */
263:            public boolean contains(String name, String key) {
264:
265:                if (name == null) {
266:                    throw new IllegalArgumentException(
267:                            "No property name specified");
268:                }
269:
270:                Object value = values.get(name);
271:                if (value == null) {
272:                    return false;
273:                }
274:
275:                if (value instanceof  Map) {
276:                    return (((Map) value).containsKey(key));
277:                }
278:
279:                return false;
280:
281:            }
282:
283:            /**
284:             * <p>Return the value of a simple property with the specified name.</p>
285:             *
286:             * <p><strong>N.B.</strong> Returns <code>null</code> if there is no property
287:             *  of the specified name.</p>
288:             *
289:             * @param name Name of the property whose value is to be retrieved.
290:             * @return The property's value
291:             * @exception IllegalArgumentException if no property name is specified
292:             */
293:            public Object get(String name) {
294:
295:                if (name == null) {
296:                    throw new IllegalArgumentException(
297:                            "No property name specified");
298:                }
299:
300:                // Value found
301:                Object value = values.get(name);
302:                if (value != null) {
303:                    return value;
304:                }
305:
306:                // Property doesn't exist
307:                if (!isDynaProperty(name)) {
308:                    return null;
309:                }
310:
311:                // Property doesn't exist
312:                value = createProperty(name, dynaClass.getDynaProperty(name)
313:                        .getType());
314:
315:                if (value != null) {
316:                    set(name, value);
317:                }
318:
319:                return value;
320:
321:            }
322:
323:            /**
324:             * <p>Return the value of an indexed property with the specified name.</p>
325:             *
326:             * <p><strong>N.B.</strong> Returns <code>null</code> if there is no 'indexed'
327:             * property of the specified name.</p>
328:             *
329:             * @param name Name of the property whose value is to be retrieved
330:             * @param index Index of the value to be retrieved
331:             * @return The indexed property's value
332:             *
333:             * @exception IllegalArgumentException if the specified property
334:             *  exists, but is not indexed
335:             * @exception IndexOutOfBoundsException if the specified index
336:             *  is outside the range of the underlying property
337:             */
338:            public Object get(String name, int index) {
339:
340:                // If its not a property, then create default indexed property
341:                if (!isDynaProperty(name)) {
342:                    set(name, defaultIndexedProperty(name));
343:                }
344:
345:                // Get the indexed property
346:                Object indexedProperty = get(name);
347:
348:                // Check that the property is indexed
349:                if (!dynaClass.getDynaProperty(name).isIndexed()) {
350:                    throw new IllegalArgumentException(
351:                            "Non-indexed property for '" + name + "[" + index
352:                                    + "]' "
353:                                    + dynaClass.getDynaProperty(name).getName());
354:                }
355:
356:                // Grow indexed property to appropriate size
357:                indexedProperty = growIndexedProperty(name, indexedProperty,
358:                        index);
359:
360:                // Return the indexed value
361:                if (indexedProperty.getClass().isArray()) {
362:                    return Array.get(indexedProperty, index);
363:                } else if (indexedProperty instanceof  List) {
364:                    return ((List) indexedProperty).get(index);
365:                } else {
366:                    throw new IllegalArgumentException(
367:                            "Non-indexed property for '" + name + "[" + index
368:                                    + "]' "
369:                                    + indexedProperty.getClass().getName());
370:                }
371:
372:            }
373:
374:            /**
375:             * <p>Return the value of a mapped property with the specified name.</p>
376:             *
377:             * <p><strong>N.B.</strong> Returns <code>null</code> if there is no 'mapped'
378:             * property of the specified name.</p>
379:             *
380:             * @param name Name of the property whose value is to be retrieved
381:             * @param key Key of the value to be retrieved
382:             * @return The mapped property's value
383:             *
384:             * @exception IllegalArgumentException if the specified property
385:             *  exists, but is not mapped
386:             */
387:            public Object get(String name, String key) {
388:
389:                // If its not a property, then create default mapped property
390:                if (!isDynaProperty(name)) {
391:                    set(name, defaultMappedProperty(name));
392:                }
393:
394:                // Get the mapped property
395:                Object mappedProperty = get(name);
396:
397:                // Check that the property is mapped
398:                if (!dynaClass.getDynaProperty(name).isMapped()) {
399:                    throw new IllegalArgumentException(
400:                            "Non-mapped property for '"
401:                                    + name
402:                                    + "("
403:                                    + key
404:                                    + ")' "
405:                                    + dynaClass.getDynaProperty(name).getType()
406:                                            .getName());
407:                }
408:
409:                // Get the value from the Map
410:                if (mappedProperty instanceof  Map) {
411:                    return (((Map) mappedProperty).get(key));
412:                } else {
413:                    throw new IllegalArgumentException(
414:                            "Non-mapped property for '" + name + "(" + key
415:                                    + ")'"
416:                                    + mappedProperty.getClass().getName());
417:                }
418:
419:            }
420:
421:            /**
422:             * Return the <code>DynaClass</code> instance that describes the set of
423:             * properties available for this DynaBean.
424:             *
425:             * @return The associated DynaClass
426:             */
427:            public DynaClass getDynaClass() {
428:                return dynaClass;
429:            }
430:
431:            /**
432:             * Remove any existing value for the specified key on the
433:             * specified mapped property.
434:             *
435:             * @param name Name of the property for which a value is to
436:             *  be removed
437:             * @param key Key of the value to be removed
438:             *
439:             * @exception IllegalArgumentException if there is no property
440:             *  of the specified name
441:             */
442:            public void remove(String name, String key) {
443:
444:                if (name == null) {
445:                    throw new IllegalArgumentException(
446:                            "No property name specified");
447:                }
448:
449:                Object value = values.get(name);
450:                if (value == null) {
451:                    return;
452:                }
453:
454:                if (value instanceof  Map) {
455:                    ((Map) value).remove(key);
456:                } else {
457:                    throw new IllegalArgumentException(
458:                            "Non-mapped property for '" + name + "(" + key
459:                                    + ")'" + value.getClass().getName());
460:                }
461:
462:            }
463:
464:            /**
465:             * Set the value of a simple property with the specified name.
466:             *
467:             * @param name Name of the property whose value is to be set
468:             * @param value Value to which this property is to be set
469:             *
470:             * @exception IllegalArgumentException if this is not an existing property
471:             *  name for our DynaClass and the MutableDynaClass is restricted
472:             * @exception ConversionException if the specified value cannot be
473:             *  converted to the type required for this property
474:             * @exception NullPointerException if an attempt is made to set a
475:             *  primitive property to null
476:             */
477:            public void set(String name, Object value) {
478:
479:                // If the property doesn't exist, then add it
480:                if (!isDynaProperty(name)) {
481:
482:                    if (dynaClass.isRestricted()) {
483:                        throw new IllegalArgumentException(
484:                                "Invalid property name '" + name
485:                                        + "' (DynaClass is restricted)");
486:                    }
487:                    if (value == null) {
488:                        dynaClass.add(name);
489:                    } else {
490:                        dynaClass.add(name, value.getClass());
491:                    }
492:
493:                }
494:
495:                DynaProperty descriptor = dynaClass.getDynaProperty(name);
496:
497:                if (value == null) {
498:                    if (descriptor.getType().isPrimitive()) {
499:                        throw new NullPointerException("Primitive value for '"
500:                                + name + "'");
501:                    }
502:                } else if (!isAssignable(descriptor.getType(), value.getClass())) {
503:                    throw new ConversionException(
504:                            "Cannot assign value of type '"
505:                                    + value.getClass().getName()
506:                                    + "' to property '" + name + "' of type '"
507:                                    + descriptor.getType().getName() + "'");
508:                }
509:
510:                // Set the property's value
511:                values.put(name, value);
512:
513:            }
514:
515:            /**
516:             * Set the value of an indexed property with the specified name.
517:             *
518:             * @param name Name of the property whose value is to be set
519:             * @param index Index of the property to be set
520:             * @param value Value to which this property is to be set
521:             *
522:             * @exception ConversionException if the specified value cannot be
523:             *  converted to the type required for this property
524:             * @exception IllegalArgumentException if there is no property
525:             *  of the specified name
526:             * @exception IllegalArgumentException if the specified property
527:             *  exists, but is not indexed
528:             * @exception IndexOutOfBoundsException if the specified index
529:             *  is outside the range of the underlying property
530:             */
531:            public void set(String name, int index, Object value) {
532:
533:                // If its not a property, then create default indexed property
534:                if (!isDynaProperty(name)) {
535:                    set(name, defaultIndexedProperty(name));
536:                }
537:
538:                // Get the indexed property
539:                Object indexedProperty = get(name);
540:
541:                // Check that the property is indexed
542:                if (!dynaClass.getDynaProperty(name).isIndexed()) {
543:                    throw new IllegalArgumentException(
544:                            "Non-indexed property for '"
545:                                    + name
546:                                    + "["
547:                                    + index
548:                                    + "]'"
549:                                    + dynaClass.getDynaProperty(name).getType()
550:                                            .getName());
551:                }
552:
553:                // Grow indexed property to appropriate size
554:                indexedProperty = growIndexedProperty(name, indexedProperty,
555:                        index);
556:
557:                // Set the value in an array
558:                if (indexedProperty.getClass().isArray()) {
559:                    Array.set(indexedProperty, index, value);
560:                } else if (indexedProperty instanceof  List) {
561:                    ((List) indexedProperty).set(index, value);
562:                } else {
563:                    throw new IllegalArgumentException(
564:                            "Non-indexed property for '" + name + "[" + index
565:                                    + "]' "
566:                                    + indexedProperty.getClass().getName());
567:                }
568:
569:            }
570:
571:            /**
572:             * Set the value of a mapped property with the specified name.
573:             *
574:             * @param name Name of the property whose value is to be set
575:             * @param key Key of the property to be set
576:             * @param value Value to which this property is to be set
577:             *
578:             * @exception ConversionException if the specified value cannot be
579:             *  converted to the type required for this property
580:             * @exception IllegalArgumentException if there is no property
581:             *  of the specified name
582:             * @exception IllegalArgumentException if the specified property
583:             *  exists, but is not mapped
584:             */
585:            public void set(String name, String key, Object value) {
586:
587:                // If the 'mapped' property doesn't exist, then add it
588:                if (!isDynaProperty(name)) {
589:                    set(name, defaultMappedProperty(name));
590:                }
591:
592:                // Get the mapped property
593:                Object mappedProperty = get(name);
594:
595:                // Check that the property is mapped
596:                if (!dynaClass.getDynaProperty(name).isMapped()) {
597:                    throw new IllegalArgumentException(
598:                            "Non-mapped property for '"
599:                                    + name
600:                                    + "("
601:                                    + key
602:                                    + ")'"
603:                                    + dynaClass.getDynaProperty(name).getType()
604:                                            .getName());
605:                }
606:
607:                // Set the value in the Map
608:                ((Map) mappedProperty).put(key, value);
609:
610:            }
611:
612:            // ------------------- protected Methods ----------------------------------
613:
614:            /**
615:             * Grow the size of an indexed property
616:             * @param name The name of the property
617:             * @param indexedProperty The current property value
618:             * @param index The indexed value to grow the property to (i.e. one less than
619:             * the required size)
620:             * @return The new property value (grown to the appropriate size)
621:             */
622:            protected Object growIndexedProperty(String name,
623:                    Object indexedProperty, int index) {
624:
625:                // Grow a List to the appropriate size
626:                if (indexedProperty instanceof  List) {
627:
628:                    List list = (List) indexedProperty;
629:                    while (index >= list.size()) {
630:                        Class contentType = getDynaClass()
631:                                .getDynaProperty(name).getContentType();
632:                        Object value = null;
633:                        if (contentType != null) {
634:                            value = createProperty(name + "[" + list.size()
635:                                    + "]", contentType);
636:                        }
637:                        list.add(value);
638:                    }
639:
640:                }
641:
642:                // Grow an Array to the appropriate size
643:                if ((indexedProperty.getClass().isArray())) {
644:
645:                    int length = Array.getLength(indexedProperty);
646:                    if (index >= length) {
647:                        Class componentType = indexedProperty.getClass()
648:                                .getComponentType();
649:                        Object newArray = Array.newInstance(componentType,
650:                                (index + 1));
651:                        System.arraycopy(indexedProperty, 0, newArray, 0,
652:                                length);
653:                        indexedProperty = newArray;
654:                        set(name, indexedProperty);
655:                        int newLength = Array.getLength(indexedProperty);
656:                        for (int i = length; i < newLength; i++) {
657:                            Array.set(indexedProperty, i, createProperty(name
658:                                    + "[" + i + "]", componentType));
659:                        }
660:                    }
661:                }
662:
663:                return indexedProperty;
664:
665:            }
666:
667:            /**
668:             * Create a new Instance of a Property
669:             * @param name The name of the property
670:             * @param type The class of the property
671:             * @return The new value
672:             */
673:            protected Object createProperty(String name, Class type) {
674:                if (type == null) {
675:                    return null;
676:                }
677:
678:                // Create Lists, arrays or DynaBeans
679:                if (type.isArray() || List.class.isAssignableFrom(type)) {
680:                    return createIndexedProperty(name, type);
681:                }
682:
683:                if (Map.class.isAssignableFrom(type)) {
684:                    return createMappedProperty(name, type);
685:                }
686:
687:                if (DynaBean.class.isAssignableFrom(type)) {
688:                    return createDynaBeanProperty(name, type);
689:                }
690:
691:                if (type.isPrimitive()) {
692:                    return createPrimitiveProperty(name, type);
693:                }
694:
695:                if (Number.class.isAssignableFrom(type)) {
696:                    return createNumberProperty(name, type);
697:                }
698:
699:                return createOtherProperty(name, type);
700:
701:            }
702:
703:            /**
704:             * Create a new Instance of an 'Indexed' Property
705:             * @param name The name of the property
706:             * @param type The class of the property
707:             * @return The new value
708:             */
709:            protected Object createIndexedProperty(String name, Class type) {
710:
711:                // Create the indexed object
712:                Object indexedProperty = null;
713:
714:                if (type == null) {
715:
716:                    indexedProperty = defaultIndexedProperty(name);
717:
718:                } else if (type.isArray()) {
719:
720:                    indexedProperty = Array.newInstance(
721:                            type.getComponentType(), 0);
722:
723:                } else if (List.class.isAssignableFrom(type)) {
724:                    if (type.isInterface()) {
725:                        indexedProperty = defaultIndexedProperty(name);
726:                    } else {
727:                        try {
728:                            indexedProperty = type.newInstance();
729:                        } catch (Exception ex) {
730:                            throw new IllegalArgumentException(
731:                                    "Error instantiating indexed property of type '"
732:                                            + type.getName() + "' for '" + name
733:                                            + "' " + ex);
734:                        }
735:                    }
736:                } else {
737:
738:                    throw new IllegalArgumentException(
739:                            "Non-indexed property of type '" + type.getName()
740:                                    + "' for '" + name + "'");
741:                }
742:
743:                return indexedProperty;
744:
745:            }
746:
747:            /**
748:             * Create a new Instance of a 'Mapped' Property
749:             * @param name The name of the property
750:             * @param type The class of the property
751:             * @return The new value
752:             */
753:            protected Object createMappedProperty(String name, Class type) {
754:
755:                // Create the mapped object
756:                Object mappedProperty = null;
757:
758:                if (type == null) {
759:
760:                    mappedProperty = defaultMappedProperty(name);
761:
762:                } else if (type.isInterface()) {
763:
764:                    mappedProperty = defaultMappedProperty(name);
765:
766:                } else if (Map.class.isAssignableFrom(type)) {
767:                    try {
768:                        mappedProperty = type.newInstance();
769:                    } catch (Exception ex) {
770:                        throw new IllegalArgumentException(
771:                                "Error instantiating mapped property of type '"
772:                                        + type.getName() + "' for '" + name
773:                                        + "' " + ex);
774:                    }
775:                } else {
776:
777:                    throw new IllegalArgumentException(
778:                            "Non-mapped property of type '" + type.getName()
779:                                    + "' for '" + name + "'");
780:                }
781:
782:                return mappedProperty;
783:
784:            }
785:
786:            /**
787:             * Create a new Instance of a 'DynaBean' Property.
788:             * @param name The name of the property
789:             * @param type The class of the property
790:             * @return The new value
791:             */
792:            protected Object createDynaBeanProperty(String name, Class type) {
793:                try {
794:                    return type.newInstance();
795:                } catch (Exception ex) {
796:                    if (logger().isWarnEnabled()) {
797:                        logger().warn(
798:                                "Error instantiating DynaBean property of type '"
799:                                        + type.getName() + "' for '" + name
800:                                        + "' " + ex);
801:                    }
802:                    return null;
803:                }
804:            }
805:
806:            /**
807:             * Create a new Instance of a 'Primitive' Property.
808:             * @param name The name of the property
809:             * @param type The class of the property
810:             * @return The new value
811:             */
812:            protected Object createPrimitiveProperty(String name, Class type) {
813:
814:                if (type == Boolean.TYPE) {
815:                    return Boolean.FALSE;
816:                } else if (type == Integer.TYPE) {
817:                    return Integer_ZERO;
818:                } else if (type == Long.TYPE) {
819:                    return Long_ZERO;
820:                } else if (type == Double.TYPE) {
821:                    return Double_ZERO;
822:                } else if (type == Float.TYPE) {
823:                    return Float_ZERO;
824:                } else if (type == Byte.TYPE) {
825:                    return Byte_ZERO;
826:                } else if (type == Short.TYPE) {
827:                    return Short_ZERO;
828:                } else if (type == Character.TYPE) {
829:                    return Character_SPACE;
830:                } else {
831:                    return null;
832:                }
833:
834:            }
835:
836:            /**
837:             * Create a new Instance of a <code>java.lang.Number</code> Property.
838:             * @param name The name of the property
839:             * @param type The class of the property
840:             * @return The new value
841:             */
842:            protected Object createNumberProperty(String name, Class type) {
843:
844:                return null;
845:
846:            }
847:
848:            /**
849:             * Create a new Instance of other Property types
850:             * @param name The name of the property
851:             * @param type The class of the property
852:             * @return The new value
853:             */
854:            protected Object createOtherProperty(String name, Class type) {
855:
856:                if (type == Object.class || type == String.class
857:                        || type == Boolean.class || type == Character.class
858:                        || Date.class.isAssignableFrom(type)) {
859:
860:                    return null;
861:
862:                }
863:
864:                try {
865:                    return type.newInstance();
866:                } catch (Exception ex) {
867:                    if (logger().isWarnEnabled()) {
868:                        logger().warn(
869:                                "Error instantiating property of type '"
870:                                        + type.getName() + "' for '" + name
871:                                        + "' " + ex);
872:                    }
873:                    return null;
874:                }
875:            }
876:
877:            /**
878:             * <p>Creates a new <code>ArrayList</code> for an 'indexed' property
879:             *    which doesn't exist.</p>
880:             *
881:             * <p>This method shouls be overriden if an alternative <code>List</code>
882:             *    or <code>Array</code> implementation is required for 'indexed' properties.</p>
883:             *
884:             * @param name Name of the 'indexed property.
885:             * @return The default value for an indexed property (java.util.ArrayList)
886:             */
887:            protected Object defaultIndexedProperty(String name) {
888:                return new ArrayList();
889:            }
890:
891:            /**
892:             * <p>Creates a new <code>HashMap</code> for a 'mapped' property
893:             *    which doesn't exist.</p>
894:             *
895:             * <p>This method can be overriden if an alternative <code>Map</code>
896:             *    implementation is required for 'mapped' properties.</p>
897:             *
898:             * @param name Name of the 'mapped property.
899:             * @return The default value for a mapped property (java.util.HashMap)
900:             */
901:            protected Map defaultMappedProperty(String name) {
902:                return new HashMap();
903:            }
904:
905:            /**
906:             * Indicates if there is a property with the specified name.
907:             * @param name The name of the property to check
908:             * @return <code>true<code> if there is a property of the
909:             * specified name, otherwise <code>false</code>
910:             */
911:            protected boolean isDynaProperty(String name) {
912:
913:                if (name == null) {
914:                    throw new IllegalArgumentException(
915:                            "No property name specified");
916:                }
917:
918:                // Handle LazyDynaClasses
919:                if (dynaClass instanceof  LazyDynaClass) {
920:                    return ((LazyDynaClass) dynaClass).isDynaProperty(name);
921:                }
922:
923:                // Handle other MutableDynaClass
924:                return dynaClass.getDynaProperty(name) == null ? false : true;
925:
926:            }
927:
928:            /**
929:             * Is an object of the source class assignable to the destination class?
930:             *
931:             * @param dest Destination class
932:             * @param source Source class
933:             * @return <code>true<code> if the source class is assignable to the
934:             * destination class, otherwise <code>false</code>
935:             */
936:            protected boolean isAssignable(Class dest, Class source) {
937:
938:                if (dest.isAssignableFrom(source)
939:                        || ((dest == Boolean.TYPE) && (source == Boolean.class))
940:                        || ((dest == Byte.TYPE) && (source == Byte.class))
941:                        || ((dest == Character.TYPE) && (source == Character.class))
942:                        || ((dest == Double.TYPE) && (source == Double.class))
943:                        || ((dest == Float.TYPE) && (source == Float.class))
944:                        || ((dest == Integer.TYPE) && (source == Integer.class))
945:                        || ((dest == Long.TYPE) && (source == Long.class))
946:                        || ((dest == Short.TYPE) && (source == Short.class))) {
947:                    return (true);
948:                } else {
949:                    return (false);
950:                }
951:
952:            }
953:
954:            /**
955:             * <p>Creates a new instance of the <code>Map</code>.</p>
956:             * @return a new Map instance
957:             */
958:            protected Map newMap() {
959:                return new HashMap();
960:            }
961:
962:            /**
963:             * <p>Returns the <code>Log</code>.
964:             */
965:            private Log logger() {
966:                if (logger == null) {
967:                    logger = LogFactory.getLog(LazyDynaBean.class);
968:                }
969:                return logger;
970:            }
971:
972:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.