KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > beans > JavaBeanTools


1 /*
2  * Copyright (c) 2003, Inversoft
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.beans;
8
9
10 import java.beans.Introspector JavaDoc;
11 import java.lang.reflect.Method JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15
16 import com.inversoft.util.ReflectionException;
17 import com.inversoft.util.ReflectionTools;
18
19
20 /**
21  * This class is a library of tools that can be used when working with
22  * JavaBeans.
23  *
24  * @author Brian Pontarelli
25  */

26 public class JavaBeanTools {
27
28     /**
29      * The string that starts standard Java bean retrieval methods <tt>get</tt>
30      */

31     public static final String JavaDoc GET_STRING = "get";
32
33     /**
34      * The string that starts standard Java bean update methods <tt>set</tt>
35      */

36     public static final String JavaDoc SET_STRING = "set";
37     public static final int GET_LENGTH = GET_STRING.length();
38
39     /**
40      * The string that starts standard Java bean boolean retrieval methods
41      * <tt>is</tt>
42      */

43     public static final String JavaDoc IS_STRING = "is";
44     public static final int IS_LENGTH = IS_STRING.length();
45
46     /**
47      * The string that starts non-standard Java bean handle methods <tt>handle</tt>
48      */

49     public static final String JavaDoc HANDLE_STRING = "handle";
50     public static final int HANDLE_LENGTH = HANDLE_STRING.length();
51
52     /** Singleton toolkit */
53     private JavaBeanTools() {
54         // static class
55
}
56
57
58     /**
59      * Using the given Method, it returns the name of the java bean property.<BR>
60      * Examples:<p>
61      * getFoo -> foo<br>
62      * getX -> x<br>
63      * getURL -> URL<br>
64      * @param method The method to translate
65      * @return The property name or null if this was not a valid property Method
66      */

67     public static String JavaDoc getPropertyName(Method JavaDoc method) {
68         String JavaDoc name = method.getName();
69
70         // Determine what type of property it is
71
if (name.startsWith(IS_STRING)) {
72
73             // Make sure that it is a proper property method
74
if (name.length() <= IS_LENGTH ||
75                     Character.isLowerCase(name.charAt(IS_LENGTH))) {
76                 return null;
77             }
78
79             return Introspector.decapitalize(name.substring(IS_LENGTH));
80
81         } else if (name.startsWith(GET_STRING) || name.startsWith(SET_STRING)) {
82
83             // Make sure that it is a proper property method
84
if (name.length() <= GET_LENGTH ||
85                     Character.isLowerCase(name.charAt(GET_LENGTH))) {
86                 return null;
87             }
88
89             return Introspector.decapitalize(name.substring(GET_LENGTH));
90
91         }
92
93         return null; // Invalid property name, return null
94
}
95
96     /**
97      * Capitalizes the first letter of the given String. If the String starts
98      * with white space, then it is returned as is.
99      *
100      * @param lowerCase The string to capitalize
101      * @return The capitalized string
102      * @throws NullPointerException If the parameter is null
103      */

104     public static String JavaDoc capitalize(String JavaDoc lowerCase) {
105
106         char [] chars = lowerCase.toCharArray();
107         chars[0] = Character.toUpperCase(chars[0]);
108
109         return new String JavaDoc(chars);
110     }
111
112     /**
113      * Using the propertyName, returns the Java Bean standard getter method name. If
114      * the parameter String starts with white space or only contains white space or
115      * is empty, the it is simply concatenated to the GET constant of this class. It
116      * is the job of the calling code to make certain that the parameter is a properly
117      * formatted String if that check is desired.
118      * @param propertyName The property name to make into the name of the getter
119      * method
120      * @return The name of the getter method or null if propertyName is empty or null
121      * @throws NullPointerException If the parameter is null
122      */

123     public static String JavaDoc makeGetter(String JavaDoc propertyName) {
124         return GET_STRING + capitalize(propertyName);
125     }
126
127     /**
128      * Using the propertyName, returns the Java Bean standard setter method name. If
129      * the parameter String starts with white space or only contains white space or
130      * is empty, the it is simply concatenated to the SET constant of this class. It
131      * is the job of the calling code to make certain that the parameter is a properly
132      * formatted String if that check is desired.
133      * @param propertyName The property name to make into the name of the setter
134      * method
135      * @return The name of the setter method or null if propertyName is empty or null
136      * @throws NullPointerException If the parameter is null
137      */

138     public static String JavaDoc makeSetter(String JavaDoc propertyName) {
139         return SET_STRING + capitalize(propertyName);
140     }
141
142     /**
143      * Using the propertyName, returns the Java Bean standard boolean getter
144      * method name. If the parameter String starts with white space or only
145      * contains white space or is empty, the it is simply concatenated to the
146      * IS constant of this class. It is the job of the calling code to make
147      * certain that the parameter is a properly formatted String if that check
148      * is desired.
149      *
150      * @param propertyName The property name to make into the name of the is
151      * method
152      * @return The name of the is method or null if propertyName is empty or null
153      * @throws NullPointerException If the parameter is null
154      */

155     public static String JavaDoc makeIs(String JavaDoc propertyName) {
156         return IS_STRING + capitalize(propertyName);
157     }
158
159     /**
160      * Using the propertyName, returns the non-standard Java Bean handle method
161      * name. If the parameter String starts with white space or only contains
162      * white space or is empty, the it is simply concatenated to the HANDLE
163      * constant of this class. It is the job of the calling code to make certain
164      * that the parameter is a properly formatted String if that check is desired.
165      *
166      * @param propertyName The property name to make into the name of the handle
167      * method
168      * @return The name of the handle method or null if propertyName is empty or null
169      * @throws NullPointerException If the parameter is null
170      */

171     public static String JavaDoc makeHandle(String JavaDoc propertyName) {
172         return HANDLE_STRING + capitalize(propertyName);
173     }
174
175     /**
176      * Check if the method is a proper java bean getter-property method. This
177      * means that it starts with get, has the form getFoo or getFOO, has no
178      * parameters and returns a non-void value
179      * @param method The method to check
180      * @return True if valid, false otherwise
181      */

182     public static boolean isValidGetter(Method JavaDoc method) {
183         return ((method.getName().startsWith(GET_STRING) ||
184                  method.getName().startsWith(IS_STRING)) &&
185             getPropertyName(method) != null &&
186             method.getParameterTypes().length == 0 &&
187             method.getReturnType() != Void.TYPE);
188     }
189
190     /**
191      * Check if the method is a proper java bean indexed getter method. This
192      * means that it starts with get, has the form getFoo or getFOO, has one
193      * parameter, an indices, and returns a non-void value
194      * @param method The method to check
195      * @return True if valid, false otherwise
196      */

197     public static boolean isValidIndexedGetter(Method JavaDoc method) {
198         return ((method.getName().startsWith(GET_STRING) ||
199                  method.getName().startsWith(IS_STRING)) &&
200             getPropertyName(method) != null &&
201             method.getParameterTypes().length == 1 &&
202             method.getParameterTypes()[0] == int.class &&
203             method.getReturnType() != Void.TYPE);
204     }
205
206     /**
207      * Does the same check as {@link #isValidGetter(Method) isValidGetter()} is
208      * checkName is true, but does not check the name if checkName is false. The
209      * only benefit of not checking the name is the performance increase. Checking
210      * the name is a simple procedure but requires a number of string comparisons
211      * and method calls.
212      *
213      * @param method The method to check
214      * @param checkName Whether or not to check the method's name
215      * @return True if the method is a valid getter and false otherwise
216      */

217     public static boolean isValidGetter(Method JavaDoc method, boolean checkName) {
218
219         if (checkName) {
220             return isValidGetter(method);
221         }
222
223         return (method.getParameterTypes().length == 0 &&
224             method.getReturnType() != Void.TYPE);
225     }
226
227     /**
228      * Does the same check as {@link #isValidIndexedGetter(Method)
229      * isValidIndexedGetter()} if checkName is true, but does not check the name
230      * if checkName is false. The only benefit of not checking the name is the
231      * performance increase. Checking the name is a simple procedure but requires
232      * a number of string comparisons and method calls.
233      *
234      * @param method The method to check
235      * @param checkName Whether or not to check the method name
236      * @return True if the method is a valid indexed getter and false otherwise
237      */

238     public static boolean isValidIndexedGetter(Method JavaDoc method, boolean checkName) {
239
240         if (checkName) {
241             return isValidIndexedGetter(method);
242         }
243
244         return (method.getParameterTypes().length == 1 &&
245             method.getParameterTypes()[0] == int.class &&
246             method.getReturnType() != Void.TYPE);
247     }
248
249     /**
250      * Check if the method is a proper java bean setter-property method. This
251      * means that it starts with set, has the form setFoo or setFOO, takes a
252      * single parameter and returns void
253      *
254      * @param method The method to check
255      * @return True if valid, false otherwise
256      */

257     public static boolean isValidSetter(Method JavaDoc method) {
258         return (method.getName().startsWith(SET_STRING) &&
259             getPropertyName(method) != null &&
260             method.getParameterTypes().length == 1 &&
261             method.getReturnType() == Void.TYPE);
262     }
263
264     /**
265      * Check if the method is a proper java bean indexed setter method. This
266      * means that it starts with set, has the form setFoo or setFOO, takes a
267      * two parameters, an indices and a value and returns void
268      *
269      * @param method The method to check
270      * @return True if valid, false otherwise
271      */

272     public static boolean isValidIndexedSetter(Method JavaDoc method) {
273         return (method.getName().startsWith(SET_STRING) &&
274             getPropertyName(method) != null &&
275             method.getParameterTypes().length == 2 &&
276             method.getParameterTypes()[0] == int.class &&
277             method.getReturnType() == Void.TYPE);
278     }
279
280     /**
281      * Does the same check as {@link #isValidSetter(Method) isValidSetter()} is checkName
282      * is true, but does not check the name if checkName is false. The only benefit of
283      * not checking the name is the performance increase. Checking the name is a simple
284      * procedure but requires a number of string comparisons and method calls.
285      *
286      * @param method The method to check
287      * @param checkName Whether or not to check the method name
288      * @return True if the method is a valid setter and false otherwise
289      */

290     public static boolean isValidSetter(Method JavaDoc method, boolean checkName) {
291
292         if (checkName) {
293             return isValidSetter(method);
294         }
295
296         return (method.getParameterTypes().length == 1 &&
297             method.getReturnType() == Void.TYPE);
298     }
299
300     /**
301      * Does the same check as {@link #isValidIndexedSetter(Method)
302      * isValidIndexedSetter()} if checkName is true, but does not check the name
303      * if checkName is false. The only benefit of not checking the name is the
304      * performance increase. Checking the name is a simple procedure but requires
305      * a number of string comparisons and method calls.
306      *
307      * @param method The method to check
308      * @param checkName Whether or not to check the method name
309      * @return True if the method is a valid indexed setter and false otherwise
310      */

311     public static boolean isValidIndexedSetter(Method JavaDoc method, boolean checkName) {
312
313         if (checkName) {
314             return isValidIndexedSetter(method);
315         }
316
317         return (method.getParameterTypes().length == 2 &&
318             method.getParameterTypes()[0] == int.class &&
319             method.getReturnType() == Void.TYPE);
320     }
321
322     /**
323      * Finds either a get method or is method in the class given for the given
324      * property name. All white space on the property String parameter is trimmed
325      * automatically when locating the Method.
326      *
327      * @param property The name of the property to find the write method for
328      * @param beanClass The class object for the bean
329      * @return The read Method for the given property name and never null
330      * @throws BeanException If the write method can not be found
331      * @throws NullPointerException If the property String is null
332      */

333     public static Method JavaDoc findReadMethod(String JavaDoc property, Class JavaDoc beanClass)
334     throws BeanException {
335
336         // Trim the string and check if the String is empty
337
property = property.trim();
338         if (property.length() == 0) {
339             throw new BeanException("The property name String is empty or contains " +
340                 "only white space and is not valid");
341         }
342
343         String JavaDoc getter = makeGetter(property);
344         Method JavaDoc method;
345
346         try {
347             method = beanClass.getMethod(getter, null);
348         } catch (SecurityException JavaDoc se) {
349             throw new BeanException(se.getMessage(), se);
350         } catch (NoSuchMethodException JavaDoc nsme) {
351
352             String JavaDoc is = makeIs(property);
353
354             // The getter failed, try the is version
355
try {
356                 method = beanClass.getMethod(is, null);
357             } catch (SecurityException JavaDoc se) {
358                 throw new BeanException(se);
359             } catch (NoSuchMethodException JavaDoc nsme2) {
360                 throw new BeanException("Getter/is for property named: " + property
361                     + " does not exist in class: " + beanClass.getName(), nsme2);
362             }
363         }
364
365         if (!isValidGetter(method, /*checkName=*/false)) {
366             throw new BeanException("Getter/is for property named: " + property
367                 + " is not a valid Java bean getter");
368         }
369
370         return method;
371     }
372
373     /**
374      * Finds a get method in the class given for the given property.
375      *
376      * @param property The name of the property to find the indexed write method for
377      * @param beanClass The class object for the bean
378      * @return The indexed read Method for the given property name and never null
379      * @throws BeanException If the read method can not be found
380      */

381     public static Method JavaDoc findIndexedReadMethod(String JavaDoc property, Class JavaDoc beanClass)
382             throws BeanException {
383
384         // Trim the string and check if the String is empty
385
property = property.trim();
386         if (property.length() == 0) {
387             throw new BeanException("The property name String is empty or contains " +
388                 "only white space and is not valid");
389         }
390
391         String JavaDoc getter = makeGetter(property);
392         Class JavaDoc [] params = {int.class};
393         Method JavaDoc method;
394
395         try {
396             method = beanClass.getMethod(getter, params);
397         } catch (SecurityException JavaDoc se) {
398             throw new BeanException(se);
399         } catch (NoSuchMethodException JavaDoc nsme) {
400
401             String JavaDoc is = makeIs(property);
402
403             // The getter failed, try the is version
404
try {
405                 method = beanClass.getMethod(is, params);
406             } catch (SecurityException JavaDoc se) {
407                 throw new BeanException(se);
408             } catch (NoSuchMethodException JavaDoc nsme2) {
409                 throw new BeanException("Indexed getter for property named: " +
410                     property + " does not exist in class: " + beanClass.getName(),
411                     nsme);
412             }
413         }
414
415         if (!isValidIndexedGetter(method, /*checkName=*/false)) {
416             throw new BeanException("Indexed getter for property named: " + property
417                 + " is not a valid Java bean getter");
418         }
419
420         return method;
421     }
422
423     /**
424      * Finds a set method for the given property and parameter type
425      *
426      * @param property The name of the property to find
427      * @param beanClass The class object for the bean
428      * @param type The parameter type to use when locating the write method
429      * @return The write Method for the given property name and type and never null
430      * @throws BeanException If the write method can not be found
431      */

432     public static Method JavaDoc findWriteMethod(String JavaDoc property, Class JavaDoc beanClass,
433             Class JavaDoc type)
434     throws BeanException {
435
436         if (type == null || type == Void.TYPE) {
437             throw new BeanException("Setters do not taken void or null parameter types");
438         }
439
440         // Trim the string and check if the String is empty
441
property = property.trim();
442         if (property.length() == 0) {
443             throw new BeanException("The property name String is empty or contains " +
444                 "only white space and is not valid");
445         }
446
447         String JavaDoc setter = makeSetter(property);
448         Method JavaDoc method;
449
450         try {
451             method = beanClass.getMethod(setter, new Class JavaDoc[]{type});
452         } catch (SecurityException JavaDoc se) {
453             throw new BeanException(se.getMessage(), se);
454         } catch (NoSuchMethodException JavaDoc nsme) {
455             throw new BeanException("Setter for property named: " + property
456                 + " does not exist in class: " + beanClass.getName(), nsme);
457         }
458
459         if (!isValidSetter(method, /*checkName=*/false)) {
460             throw new BeanException("Setter for property named: " + property
461                 + " is not a valid Java bean setter");
462         }
463
464         return method;
465     }
466
467     /**
468      * Finds a set indexed method for the given property and parameter type
469      *
470      * @param property The name of the property to find
471      * @param beanClass The class object for the bean
472      * @param type The parameter type to use when locating the write method
473      * @return The indexed write Method for the given property name and type and never null
474      * @throws BeanException If the write method can not be found
475      */

476     public static Method JavaDoc findIndexedWriteMethod(String JavaDoc property, Class JavaDoc beanClass,
477             Class JavaDoc type)
478     throws BeanException {
479
480         if (type == null || type == Void.TYPE) {
481             throw new BeanException("Setters do not taken void or null parameter types");
482         }
483
484         // Trim the string and check if the String is empty
485
property = property.trim();
486         if (property.length() == 0) {
487             throw new BeanException("The property name String is empty or contains " +
488                 "only white space and is not valid");
489         }
490
491         String JavaDoc setter = makeSetter(property);
492         Class JavaDoc [] params = {int.class, type};
493         Method JavaDoc method;
494
495         try {
496             method = beanClass.getMethod(setter, params);
497         } catch (SecurityException JavaDoc se) {
498             throw new BeanException(se.getMessage(), se);
499         } catch (NoSuchMethodException JavaDoc nsme) {
500             throw new BeanException("Indexed setter for property named: " + property
501                 + " does not exist in class: " + beanClass.getName(), nsme);
502         }
503
504         if (!isValidIndexedSetter(method, /*checkName=*/false)) {
505             throw new BeanException("Indexed setter for property named: " + property
506                 + " is not a valid Java bean setter");
507         }
508
509         return method;
510     }
511
512     /**
513      * Another convience method that calls a java bean getter and returns the value.
514      * This version uses the BeanProperty class to determine the property read
515      * method.
516      *
517      * @param prop The BeanProperty object to use
518      * @param bean The java bean object to call it on
519      * @return The return value from calling the getter method for the given property
520      * @throws BeanException If there was a problem calling the getter
521      */

522     public static Object JavaDoc callGetter(BeanProperty prop, Object JavaDoc bean) throws BeanException {
523
524         Method JavaDoc read = prop.getReadMethod();
525         if (read == null) {
526             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(128);
527             buf.append("Getter/is for property named: ").append(prop.getPropertyName());
528             buf.append(" does not exist for class: ").append(bean.getClass().getName());
529             throw new BeanException(buf.toString());
530         }
531
532         return invokeMethod(read, bean, null);
533     }
534
535     /**
536      * Another convience method that calls an indexed java bean getter and returns
537      * the value. This version uses the IndexedBeanProperty class to determine the
538      * property read method.
539      *
540      * @param prop The BeanProperty object to use
541      * @param bean The java bean object to call it on
542      * @param index The indices to be passed to the getter method
543      * @return The return value from calling the indexed getter method for the given
544      * property
545      * @throws BeanException If there was a problem calling the getter
546      */

547     public static Object JavaDoc callIndexedGetter(IndexedBeanProperty prop, Object JavaDoc bean,
548             Integer JavaDoc index) throws BeanException {
549
550         Method JavaDoc read = prop.getReadMethod();
551         if (read == null) {
552             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(128);
553             buf.append("Indexed getter for property named: ").append(prop.getPropertyName());
554             buf.append(" does not exist for class: ").append(bean.getClass().getName());
555             throw new BeanException(buf.toString());
556         }
557
558         // Package up the indices
559
Object JavaDoc [] params = {index};
560
561         return invokeMethod(read, bean, params);
562      }
563
564     /**
565      * Another convience method for calling a setter on a java bean. This method
566      * uses the BeanProperty object to determine the write method
567      *
568      * @param prop The BeanProperty object to use when calling the setter
569      * @param bean The object to call it on
570      * @param param The parameter to the setter (java bean standard)
571      * @throws BeanException If the property a read only property or if the setter
572      * called threw an exception or if the param is the incorrect type for
573      * the setter method
574      */

575     public static void callSetter(BeanProperty prop, Object JavaDoc bean, Object JavaDoc param)
576     throws BeanException {
577
578         Method JavaDoc write = prop.getWriteMethod();
579         if (write == null) {
580             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(128);
581             buf.append("Setter for property named: ").append(prop.getPropertyName());
582             buf.append(" does not exist for class: ").append(bean.getClass().getName());
583             throw new BeanException(buf.toString());
584         }
585
586         invokeMethod(write, bean, new Object JavaDoc[] {param});
587     }
588
589     /**
590      * Another convience method for calling a setter on a java bean. This method
591      * uses the BeanProperty object to determine the write method.
592      *
593      * @param prop The BeanProperty object to use when calling the setter
594      * @param bean The object to call it on
595      * @param index The indices of the property to set
596      * @param param The parameter to the setter (java bean standard)
597      * @throws BeanException If the property a read only property or if the setter
598      * called threw an exception or if the param is the incorrect type for
599      * the setter method
600      */

601     public static void callIndexedSetter(BeanProperty prop, Object JavaDoc bean, Integer JavaDoc index,
602             Object JavaDoc param) throws BeanException {
603
604         Method JavaDoc write = prop.getWriteMethod();
605         if (write == null) {
606             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(128);
607             buf.append("Indexed setter for property named: ").append(prop.getPropertyName());
608             buf.append(" does not exist for class: ").append(bean.getClass().getName());
609             throw new BeanException(buf.toString());
610         }
611
612         Object JavaDoc [] params = {index, param};
613
614         invokeMethod(write, bean, params);
615     }
616
617     /**
618      * Calls the ReflectionTools method but converts any thrown ReflectionExceptions
619      * to BeanExceptions for this package. This is package level because it contains
620      * too much low level concepts (ie the Method object) that it should be protected
621      * to ensure that it in fact only invokes JavaBean methods and only throws
622      * BeanExceptions, etc.
623      *
624      * @param method The method to invoke
625      * @param bean The object to invoke the method on
626      * @param params The params to the method
627      * @return The return value from the method
628      * @throws BeanException If any mishap occurred whilst Reflecting sire.
629      * All the exceptions that could be thrown whilst invoking will be
630      * wrapped inside the ReflectionException
631      */

632     static Object JavaDoc invokeMethod(Method JavaDoc method, Object JavaDoc bean, Object JavaDoc [] params)
633             throws BeanException {
634         try {
635             return ReflectionTools.invokeMethod(method, bean, params);
636         } catch (ReflectionException re) {
637             throw new BeanException(re);
638         }
639     }
640
641     /**
642      * Using the given nested property name, this returns the local property name
643      * and the remainder of the nested property name, if any. This is done by returning
644      * a instance of the top level class NameInfo of this class
645      *
646      * @param propertyName The nested (or local) property name to extract the local
647      * and nested property names from.
648      * @return The NameInfo class for the names
649      */

650     public static NameInfo splitNameFront(String JavaDoc propertyName) {
651         NameInfo nh = new NameInfo();
652         nh.indexOfDot = propertyName.indexOf(".");
653
654         // Determine if the property name describes a local property or a sub-property
655
if (nh.indexOfDot == -1) {
656             nh.localPropertyName = propertyName;
657             nh.nested = false;
658         } else {
659             nh.localPropertyName = propertyName.substring(0, nh.indexOfDot);
660             nh.nestedPropertyName = propertyName.substring(nh.indexOfDot + 1);
661             nh.nested = true;
662         }
663
664         return nh;
665     }
666
667     /**
668      * Using the given nested property name, this returns the nested property
669      * name and the last local property name, if any. This is done by returning
670      * a instance of the top level class NameInfo of this class
671      *
672      * @param propertyName The nested (or local) property name to extract the
673      * local and nested property names from.
674      * @return The NameInfo class for the names
675      */

676     public static NameInfo splitNameBack(String JavaDoc propertyName) {
677         NameInfo nh = new NameInfo();
678         nh.indexOfDot = propertyName.lastIndexOf(".");
679
680         // Determine if the property name describes a local property or a sub-property
681
if (nh.indexOfDot == -1) {
682             nh.localPropertyName = propertyName;
683             nh.nested = false;
684         } else {
685             nh.nestedPropertyName = propertyName.substring(0, nh.indexOfDot);
686             nh.localPropertyName = propertyName.substring(nh.indexOfDot + 1);
687             nh.nested = true;
688         }
689
690         return nh;
691     }
692
693     /**
694      * Using the given nested property name, this returns each of the property
695      * names broken out and stored in a String array.
696      *
697      * @param propertyName The nested (or local) property name to extract the local
698      * and nested property names from.
699      * @return The array of property names
700      */

701     public static String JavaDoc[] splitNameComplete(String JavaDoc propertyName) {
702         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(propertyName, ".");
703         String JavaDoc[] props = new String JavaDoc[st.countTokens()];
704         int i = 0;
705         while (st.hasMoreTokens()) {
706             props[i] = st.nextToken();
707             i++;
708         }
709
710         return props;
711     }
712
713     /**
714      * Given the property name string, the indices and property name are extracted
715      * and returned in the a new PropertyInfo. If the given propertyName string
716      * does not contain an indices, then the indices member of the PropertyInfo
717      * returned will be empty. Inside the IndexHelper, the property name is stored
718      * in the propertyName member and the indices is stored in the indices member.
719      *
720      * @param propertyName The name of the property to search for the indices
721      * @return The given PropertyInfo instance that contains all the new information
722      * @throws BeanException If the property name contains an invalid indices or an
723      * unclosed indices notation (i.e. '[1')
724      */

725     public static PropertyInfo retrievePropertyInfo(String JavaDoc propertyName)
726     throws BeanException {
727
728         // Determine whether or not the property is indexed or not
729
PropertyInfo propertyInfo = new PropertyInfo();
730         int bracet = propertyName.indexOf('[');
731         int firstBracet = bracet;
732         if (bracet == -1) {
733             propertyInfo.indices = null;
734             propertyInfo.propertyName = propertyName;
735             return propertyInfo;
736         }
737
738         while (bracet != -1) {
739             int bracetTwo = propertyName.indexOf(']', bracet);
740             if (bracetTwo == -1) {
741                 throw new BeanException("The bean property name string: " + propertyName
742                     + " contains an invalid indices");
743             }
744
745             String JavaDoc indexStr = propertyName.substring(bracet + 1, bracetTwo);
746             int length = indexStr.length();
747             char ch = indexStr.charAt(0);
748             if (ch == '"' || ch == '\'') {
749                 char lastCh = indexStr.charAt(length - 1);
750                 if (lastCh != '"' && lastCh != '\'') {
751                     throw new BeanException("Invalid indices value: " + indexStr);
752                 }
753
754                 propertyInfo.indices.add(indexStr.substring(1, length - 1));
755             } else {
756                 try {
757                     propertyInfo.indices.add(Integer.valueOf(indexStr));
758                 } catch (NumberFormatException JavaDoc nfe) {
759                     propertyInfo.indices.add(indexStr);
760                 }
761             }
762
763             bracet = propertyName.indexOf('[', bracetTwo);
764         }
765
766         propertyInfo.propertyName = propertyName.substring(0, firstBracet);
767
768         return propertyInfo;
769     }
770
771     /**
772      * Using the given property name, this breaks the property name down into
773      * manageable pieces. These are the individual instances of the PropertyInfo
774      * inner class which store the property name and the indices (which could be
775      * null or any object). This is broken on the '.' character accordiing to
776      * the JavaBean standard.
777      *
778      * @param propertyName The property name strng to break down.
779      * @return A new ArrayList of PropertyInfo objects
780      * @throws BeanException If the property string is invalid
781      */

782     public static List JavaDoc retrieveAllPropertyInfo(String JavaDoc propertyName)
783     throws BeanException {
784         List JavaDoc info = new ArrayList JavaDoc();
785         StringTokenizer JavaDoc ts = new StringTokenizer JavaDoc(propertyName, ".");
786
787         while (ts.hasMoreTokens()) {
788             // Grab the indices from the property
789
PropertyInfo pi = retrievePropertyInfo(ts.nextToken());
790             info.add(pi);
791         }
792
793         return info;
794     }
795
796
797     //-------------------------------------------------------------------------
798
// Inner classes
799
//-------------------------------------------------------------------------
800

801     /**
802      * This class is a small helper class that is used in the beans pacakge for
803      * assisting with indexing operations.
804      */

805     public static class PropertyInfo {
806
807         /**
808          * This stores the list of indices when this class is used to break a
809          * property name apart from an indices
810          */

811         public List JavaDoc indices = new ArrayList JavaDoc();
812
813         /**
814          * This stores the property name that is broken apart from a single indices or
815          * List of indices
816          */

817         public String JavaDoc propertyName;
818     }
819
820     /**
821      * This class is a small helper class that is used in the beans pacakge for
822      * assisting with property names
823      */

824     public static class NameInfo {
825
826         /**
827          * Stores whether or not this property is within a nesting or a single
828          * property
829          */

830         public boolean nested;
831
832         /**
833          * This stores the indices of the . character in the original property name
834          * string. This indices is not valid for either of the Strings in this
835          * class
836          */

837         public int indexOfDot;
838
839         /**
840          * This stores the local property name after a nested property name has
841          * been broken up into pieces
842          */

843         public String JavaDoc localPropertyName;
844
845         /**
846          * This stores the remainder of a nested property name after a nested
847          * it has been broken. This is basically the original minus (the local
848          * property name plus the . character). ie<p>
849          * original - (local + ".")
850          */

851         public String JavaDoc nestedPropertyName;
852     }
853 }
854
Popular Tags