Source Code Cross Referenced for BeanUtil.java in  » Web-Framework » aranea-mvc-1.1.1 » org » araneaframework » backend » util » 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 » Web Framework » aranea mvc 1.1.1 » org.araneaframework.backend.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Copyright 2006 Webmedia Group Ltd.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *  http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         **/package org.araneaframework.backend.util;
016:
017:        import java.lang.reflect.InvocationTargetException;
018:        import java.lang.reflect.Method;
019:        import java.lang.reflect.Modifier;
020:        import java.util.ArrayList;
021:        import java.util.Iterator;
022:        import java.util.List;
023:        import org.apache.commons.lang.StringUtils;
024:        import org.apache.commons.lang.Validate;
025:        import org.apache.commons.lang.exception.NestableRuntimeException;
026:        import org.araneaframework.core.Assert;
027:
028:        /**
029:         * This class provides methods to manipulate Bean fields.
030:         * 
031:         * Simple (e.g. 'name') as well as nested (e.g. 'location.city') Bean fields
032:         * are both supported.
033:         * 
034:         * To propagate an empty Bean by nested fields,
035:         * {@link #fillFieldValue(Object, String, Object)} method is recommended
036:         * instead of {@link #setFieldValue(Object, String, Object)} to create
037:         * missing Beans automatically.
038:         * 
039:         * @author <a href="mailto:rein@araneaframework.org">Rein Raudjärv</a>
040:         * 
041:         * @see BeanMapper
042:         */
043:        public class BeanUtil {
044:
045:            /**
046:             * The delimiter that separates the components of a nested reference.
047:             */
048:            public static final char NESTED_DELIM = '.';
049:
050:            /**
051:             * Returns <code>List&lt;String&gt;</code>- the <code>List</code> of Bean
052:             * field names.
053:             * <p>        
054:             * Only simple fields (not nested) are returned.
055:             * </p>
056:             * 
057:             * @param beanClass
058:             *         the class implementing the Bean pattern.
059:             * @return <code>List&lt;String&gt;</code>- the <code>List</code> of Bean
060:             *         field names.
061:             */
062:            public static List getFields(Class beanClass) {
063:                Assert.notNull(beanClass, "No bean class specified.");
064:
065:                List result = new ArrayList();
066:
067:                Method[] methods = beanClass.getMethods();
068:                for (int i = 0; i < methods.length; i++) {
069:                    Method method = methods[i];
070:                    // Checking that method may be a valid getter method
071:                    if (Modifier.isPublic(method.getModifiers())
072:                            && (method.getParameterTypes().length == 0)
073:                            && !(method.getReturnType()
074:                                    .isAssignableFrom(Void.class))) {
075:                        if (method.getName().startsWith("get")
076:                                && !"getClass".equals(method.getName())) {
077:                            //Adding the field...
078:                            result.add(method.getName().substring(3, 4)
079:                                    .toLowerCase()
080:                                    + method.getName().substring(4));
081:                        } else if (method.getName().startsWith("is")
082:                                && (Boolean.class
083:                                        .equals(method.getReturnType()) || boolean.class
084:                                        .equals(method.getReturnType()))) {
085:                            //Adding the field...
086:                            result.add(method.getName().substring(2, 3)
087:                                    .toLowerCase()
088:                                    + method.getName().substring(3));
089:                        }
090:                    }
091:                }
092:
093:                return result;
094:            }
095:
096:            /**
097:             * Returns the value of Bean field identified with name <code>field</code>
098:             * for object <code>bean</code>.
099:             * <p>
100:             * Returns null if no bean specified or such method found.
101:             * </p>
102:             * <p>
103:             * Only simple fields are supported.
104:             * Use {@link #getFieldValue(Object, String)} for nested fields.
105:             * </p>
106:             * 
107:             * @param bean
108:             *          Object, which value to return.
109:             * @param field
110:             *          The name of VO field.
111:             * @return The value of the field.
112:             */
113:            private static Object getSimpleFieldValue(Object bean, String field) {
114:                Validate.notNull(field, "No field name specified");
115:                if (bean == null) {
116:                    return null;
117:                }
118:
119:                Object result = null;
120:                try {
121:                    Method getter = getSimpleReadMethod(bean.getClass(), field);
122:                    if (getter != null) {
123:                        result = getter.invoke(bean, (Object[]) null);
124:                    }
125:                } catch (InvocationTargetException e) {
126:                    throw new NestableRuntimeException(
127:                            "There was a problem getting field '" + field
128:                                    + "' value", e);
129:                } catch (IllegalAccessException e) {
130:                    throw new NestableRuntimeException(
131:                            "There was a problem getting field '" + field
132:                                    + "' value", e);
133:                }
134:                return result;
135:            }
136:
137:            /**
138:             * Returns the value of Bean field identified with name <code>field</code>
139:             * for object <code>bean</code>.
140:             * <p>
141:             * Returns null if no bean specified or such method found.
142:             * </p>
143:             * 
144:             * @param bean
145:             *          Object, which value to return.
146:             * @param field
147:             *          The name of VO field.
148:             * @return The value of the field.
149:             */
150:            public static Object getFieldValue(Object bean, String field) {
151:                Validate.notNull(field, "No field name specified");
152:                if (bean == null) {
153:                    return null;
154:                }
155:
156:                String[] fields = StringUtils.split(field, NESTED_DELIM);
157:                Object subValue = bean;
158:                for (int i = 0; i < fields.length && subValue != null; i++) {
159:                    subValue = getSimpleFieldValue(subValue, fields[i]);
160:                }
161:                return subValue;
162:            }
163:
164:            /**
165:             * Sets the value of Bean field identified by name <code>field</code> for
166:             * object <code>bean</code>.
167:             * <p>
168:             * Nothing happens if no bean specified, one of its sub-field is null or
169:             * no such method found.
170:             * </p>
171:             * <p>
172:             * Only simple fields are supported.
173:             * Use {@link #setFieldValue(Object, String, Object)} for nested fields.
174:             * </p> 
175:             * 
176:             * @param bean
177:             *          bean Object, which value to set.
178:             * @param field
179:             *          The name of Bean field.
180:             * @param value
181:             *          The new value of the field.
182:             *          
183:             * @see #fillFieldValue(Object, String, Object)
184:             */
185:            private static void setSimpleFieldValue(Object bean, String field,
186:                    Object value) {
187:                Validate.notNull(field, "No field name specified");
188:                if (bean == null) {
189:                    return;
190:                }
191:
192:                try {
193:                    Method setter = getSimpleWriteMethod(bean.getClass(), field);
194:                    if (setter != null) {
195:                        setter.invoke(bean, new Object[] { value });
196:                    }
197:                } catch (InvocationTargetException e) {
198:                    throw new NestableRuntimeException(
199:                            "There was a problem setting field '" + field
200:                                    + "' to value " + value, e);
201:                } catch (IllegalAccessException e) {
202:                    throw new NestableRuntimeException(
203:                            "There was a problem setting field '" + field
204:                                    + "' to value " + value, e);
205:                }
206:            }
207:
208:            /**
209:             * Sets the value of Bean field identified by name <code>field</code> for
210:             * object <code>bean</code>.
211:             * <p>
212:             * Nothing happens if no bean specified, one of its sub-field is null or
213:             * no such method found.
214:             * </p>
215:             * <p>
216:             * If one of the sub-fields (not the last one) is null, they are not
217:             * automatically propagated. In order for this, use
218:             * {@link #fillFieldValue(Object, String, Object)} method.
219:             * </p>
220:             * 
221:             * @param bean
222:             *          bean Object, which value to set.
223:             * @param field
224:             *          The name of Bean field.
225:             * @param value
226:             *          The new value of the field.
227:             *          
228:             * @see #fillFieldValue(Object, String, Object)
229:             */
230:            public static void setFieldValue(Object bean, String field,
231:                    Object value) {
232:                Validate.notNull(field, "No field name specified");
233:                if (bean == null) {
234:                    return;
235:                }
236:
237:                String[] fields = StringUtils.split(field, NESTED_DELIM);
238:                Object subBean = bean;
239:                for (int i = 0; i < fields.length - 1 && subBean != null; i++) {
240:                    subBean = getSimpleFieldValue(subBean, fields[i]);
241:                }
242:                if (subBean != null) {
243:                    setSimpleFieldValue(subBean, fields[fields.length - 1],
244:                            value);
245:                }
246:            }
247:
248:            /**
249:             * Sets the value of Bean field identified by name <code>field</code> for
250:             * object <code>bean</code>.
251:             * <p>
252:             * Nothing happens if no bean specified or such method found.
253:             * </p>
254:             * This method is identical to
255:             * {@link #setFieldValue(Object, String, Object)} except that mssing beans
256:             * in sub-fields (not the last one) of bean Object are created
257:             * automatically.
258:             * 
259:             * @param bean
260:             *          bean Object, which value to set.
261:             * @param field
262:             *          The name of Bean field.
263:             * @param value
264:             *          The new value of the field.
265:             *          
266:             * @see #setFieldValue(Object, String, Object)
267:             */
268:            public static void fillFieldValue(Object bean, String field,
269:                    Object value) {
270:                Validate.notNull(field, "No field name specified");
271:                if (bean == null) {
272:                    return;
273:                }
274:
275:                String[] fields = StringUtils.split(field, NESTED_DELIM);
276:                Object subBean = bean;
277:                for (int i = 0; i < fields.length - 1 && subBean != null; i++) {
278:                    Object tmp = getSimpleFieldValue(subBean, fields[i]);
279:                    if (tmp == null) {
280:                        tmp = newInstance(getSimpleFieldType(
281:                                subBean.getClass(), fields[i]));
282:                        setSimpleFieldValue(subBean, fields[i], tmp);
283:                    }
284:                    subBean = tmp;
285:                }
286:                setSimpleFieldValue(subBean, fields[fields.length - 1], value);
287:            }
288:
289:            /**
290:             * Returns type of Bean field identified by name <code>field</code>.
291:             * <p>
292:             * Null is returned if no such method found.
293:             * </p>
294:             * <p>
295:             * Only simple fields are supported.
296:             * Use {@link #getFieldType(Class, String)} for nested fields.
297:             * </p>
298:             *  
299:             * @param beanClass
300:             *         the class implementing the Bean pattern.
301:             * @param field
302:             *          The name of Bean field.
303:             * @return The type of the field.
304:             */
305:            private static Class getSimpleFieldType(Class beanClass,
306:                    String field) {
307:                Validate.notNull(beanClass, "No bean class specified");
308:                Validate.notNull(field, "No field name specified");
309:
310:                Class result = null;
311:                Method getter = getSimpleReadMethod(beanClass, field);
312:                if (getter != null) {
313:                    result = getter.getReturnType();
314:                }
315:                return result;
316:            }
317:
318:            /**
319:             * Returns type of Bean field identified by name <code>field</code>.
320:             * <p>
321:             * Null is returned if no such method found.
322:             * </p>
323:             * 
324:             * @param beanClass
325:             *         the class implementing the Bean pattern.
326:             * @param field
327:             *          The name of Bean field.
328:             * @return The type of the field.
329:             */
330:            public static Class getFieldType(Class beanClass, String field) {
331:                Validate.notNull(beanClass, "No bean class specified");
332:                Validate.notNull(field, "No field name specified");
333:
334:                String[] fields = StringUtils.split(field, NESTED_DELIM);
335:                Class subBeanType = beanClass;
336:                for (int i = 0; i < fields.length && subBeanType != null; i++) {
337:                    subBeanType = getSimpleFieldType(subBeanType, fields[i]);
338:                }
339:                return subBeanType;
340:            }
341:
342:            /**
343:             * Checks that the field identified by <code>field</code> is a valid
344:             * Bean field (can be read-only).
345:             * <p>
346:             * To enable reading the field, the spcfified <code>beanClass</code> must
347:             * have getter (field's name starts with <code>get</code> or
348:             * <code>is</code>) for this field.
349:             * </p>
350:             * 
351:             * @param beanClass
352:             *         the class implementing the Bean pattern.
353:             * @param field
354:             *          Bean field name.
355:             * @return if this field is in Bean.
356:             */
357:            public static boolean isReadable(Class beanClass, String field) {
358:                return (getReadMethod(beanClass, field) != null);
359:            }
360:
361:            /**
362:             * Checks that the field identified by <code>field</code> is a writable
363:             * Bean field.
364:             * <p>
365:             * To enable writing the field, the spcfified <code>beanClass</code> must
366:             * have setter (field's name starts with <code>set</code>) for this field.
367:             * </p>
368:             * 
369:             * @param beanClass
370:             *         the class implementing the Bean pattern.
371:             * @param field
372:             *          Bean field name.
373:             * @return if this field is in Bean.
374:             */
375:            public static boolean isWritable(Class beanClass, String field) {
376:                return (getWriteMethod(beanClass, field) != null);
377:            }
378:
379:            /**
380:             * Returns write method (setter) for the field.
381:             * <p>
382:             * Null is returned if no such method found.
383:             * </p>
384:             * <p>
385:             * Only simple fields are supported.
386:             * Use {@link #getWriteMethod(Class, String)} for nested fields.
387:             * </p> 
388:             * 
389:             * @param beanClass
390:             *         the class implementing the Bean pattern.
391:             * @param field
392:             *          Bean field name.
393:             * @return write method (setter) for the field.
394:             */
395:            private static Method getSimpleWriteMethod(Class beanClass,
396:                    String field) {
397:                Validate.notNull(beanClass, "No bean class specified");
398:                Validate.notNull(field, "No field name specified");
399:
400:                String setterName = "set" + field.substring(0, 1).toUpperCase()
401:                        + field.substring(1);
402:                try {
403:                    return beanClass
404:                            .getMethod(setterName,
405:                                    new Class[] { getSimpleFieldType(beanClass,
406:                                            field) });
407:                } catch (NoSuchMethodException e) {
408:                    // There is no 'set' method for this field
409:                }
410:
411:                return null;
412:            }
413:
414:            /**
415:             * Returns write method (setter) for the field.
416:             * <p>
417:             * Null is returned if no such method found.
418:             * </p>
419:             * 
420:             * @param beanClass
421:             *         the class implementing the Bean pattern.
422:             * @param field
423:             *          Bean field name.
424:             * @return write method (setter) for the field.
425:             */
426:            public static Method getWriteMethod(Class beanClass, String field) {
427:                Validate.notNull(beanClass, "No bean class specified");
428:                Validate.notNull(field, "No field name specified");
429:
430:                String[] fields = StringUtils.split(field, NESTED_DELIM);
431:                Class subBeanType = beanClass;
432:                for (int i = 0; i < fields.length - 1 && subBeanType != null; i++) {
433:                    subBeanType = getSimpleFieldType(subBeanType, fields[i]);
434:                }
435:                if (subBeanType != null) {
436:                    return getSimpleWriteMethod(subBeanType,
437:                            fields[fields.length - 1]);
438:                }
439:                return null;
440:            }
441:
442:            /**
443:             * Returns read method (getter) for the field.
444:             * <p>
445:             * Null is returned if no such method found.
446:             * </p>
447:             * <p>
448:             * Only simple fields are supported.
449:             * Use {@link #getWriteMethod(Class, String)} for nested fields.
450:             * </p>
451:             *  
452:             * @param beanClass
453:             *         the class implementing the Bean pattern.
454:             * @param field
455:             *          Bean field name.
456:             * @return read method (getter) for the field.
457:             */
458:            private static Method getSimpleReadMethod(Class beanClass,
459:                    String field) {
460:                Validate.notNull(beanClass, "No bean class specified");
461:                Validate.notNull(field, "No field name specified");
462:
463:                String getterName = "get" + field.substring(0, 1).toUpperCase()
464:                        + field.substring(1);
465:                try {
466:                    return beanClass.getMethod(getterName, (Class[]) null);
467:                } catch (NoSuchMethodException e) {
468:                    // There is no 'get' method for this field
469:                }
470:
471:                getterName = "is" + field.substring(0, 1).toUpperCase()
472:                        + field.substring(1);
473:                try {
474:                    return beanClass.getMethod(getterName, (Class[]) null);
475:                } catch (NoSuchMethodException e) {
476:                    // There is no 'is' method for this field
477:                }
478:
479:                return null;
480:            }
481:
482:            /**
483:             * Returns read method (getter) for the field.
484:             * <p>
485:             * Null is returned if no such method found.
486:             * </p>
487:             * 
488:             * @param beanClass
489:             *         the class implementing the Bean pattern.
490:             * @param field
491:             *          Bean field name.
492:             * @return read method (getter) for the field.
493:             */
494:            public static Method getReadMethod(Class beanClass, String field) {
495:                Validate.notNull(beanClass, "No bean class specified");
496:                Validate.notNull(field, "No field name specified");
497:
498:                String[] fields = StringUtils.split(field, NESTED_DELIM);
499:                Class subBeanType = beanClass;
500:                for (int i = 0; i < fields.length - 1 && subBeanType != null; i++) {
501:                    subBeanType = getSimpleFieldType(subBeanType, fields[i]);
502:                }
503:                if (subBeanType != null) {
504:                    return getSimpleReadMethod(subBeanType,
505:                            fields[fields.length - 1]);
506:                }
507:                return null;
508:            }
509:
510:            /**
511:             * Creates new instance of the specified <code>beanClass</code>.
512:             * <p>
513:             * In order to be Bean type, it must have a constructor without arguments. 
514:             * <p>
515:             * <p>
516:             * If creating the new instance fails, a RuntimeException is thrown. 
517:             * </p>
518:             * 
519:             * @param beanClass
520:             *         the class implementing the Bean pattern.
521:             * @return new instance of the Bean type.
522:             */
523:            public static Object newInstance(Class beanClass) {
524:                Validate.notNull(beanClass, "No bean class specified");
525:
526:                Object result;
527:                try {
528:                    result = beanClass.newInstance();
529:                } catch (InstantiationException e) {
530:                    throw new NestableRuntimeException(
531:                            "Could not create an instance of class '"
532:                                    + beanClass + "'", e);
533:                } catch (IllegalAccessException e) {
534:                    throw new NestableRuntimeException(
535:                            "Could not create an instance of class '"
536:                                    + beanClass + "'", e);
537:                }
538:                return result;
539:            }
540:
541:            /**
542:             * Sets all the fields with same names to same values.
543:             * <p> 
544:             * NB! the values are references (there'is no deep copy made)!
545:             * </p>
546:             * <p>
547:             * <code>from</code> Bean fields that are not supported by <code>to</code>
548:             * are ignored. 
549:             * </p>
550:             * 
551:             * @param from
552:             *          <code>Bean</code> from which to convert.
553:             * @param to
554:             *          <code>Bean</code> to which to convert.
555:             * @return <code>to</code> with <codefrom</code> values
556:             * 
557:             * @see #copy(Object, Class)
558:             */
559:            public static Object copy(Object from, Object to) {
560:                Assert.isTrue(from != null && to != null,
561:                        "BeanUtil.copy() cannot accept NULL arguments.");
562:
563:                List fromVoFields = getFields(from.getClass());
564:                for (Iterator i = fromVoFields.iterator(); i.hasNext();) {
565:                    String field = (String) i.next();
566:                    Class toFieldType = getSimpleFieldType(to.getClass(), field);
567:                    Class fromFieldType = getSimpleFieldType(from.getClass(),
568:                            field);
569:                    if (isWritable(to.getClass(), field)
570:                            && toFieldType.isAssignableFrom(fromFieldType)) {
571:                        setSimpleFieldValue(to, field, getSimpleFieldValue(
572:                                from, field));
573:                    }
574:                }
575:                return to;
576:            }
577:
578:            /**
579:             * Creates a new instance of Class <code>toType</code> and sets its field values to be
580:             * the same as given <code>from</code> Object. Only fields with same names that exist in
581:             * both <code>from</code> object and <code>toType</code> class are affected.
582:             * 
583:             * @param from
584:             *          <code>Bean</code> from which to read field values.
585:             * @param toType
586:             *          <code>Class</code> which object instance to create.
587:             * @return new instance of <code>toType</code> with <code>from</code> values
588:             * 
589:             * @see #copy(Object, Object)
590:             * @see #clone() 
591:             */
592:            public static Object copy(Object from, Class toType) {
593:                Validate.isTrue(from != null && from != null,
594:                        "You cannot convert a Bean to null or vice versa");
595:                return copy(from, newInstance(toType));
596:            }
597:
598:            /**
599:             * Clones <code>bean</code> by copying its fields values (references) to a
600:             * new instance of the same type.
601:             * 
602:             * @param bean
603:             *          bean Object, which value to set.
604:             * @return new instance of <code>bean</code> type with same fields values
605:             * (references)
606:             * 
607:             * @see #copy(Object, Object)
608:             * @see #copy(Object, Class)
609:             */
610:            public static Object clone(Object bean) {
611:                Validate.notNull(bean, "No bean specified");
612:                return copy(bean, bean.getClass());
613:            }
614:
615:            /**
616:             * Returns whether the given object type is a Bean type.
617:             * 
618:             * @param clazz
619:             *         the class.
620:             * @return whether the given object type is a Bean type.
621:             */
622:            public static boolean isBean(Class clazz) {
623:                return (getFields(clazz).size() != 0);
624:            }
625:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.