1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package com.unitesk.atp.dynattrs;
33
34 import java.lang.reflect.Array;
35 import java.lang.reflect.Method;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40
41 /***
42 * This is a collection of static methods to work with
43 * different implementations of attributes.
44 *
45 * @author <A href="mailto:demakov@ispras.ru">Alexey Demakov</A>
46 * @author <A href="mailto:monakhov@ispras.ru">Alexander Monakhov</A>
47 * @version $Id: Accessor.java,v 1.8 2006/02/09 06:30:07 all-x Exp $
48 */
49 public class Accessor
50 {
51
52
53
54 /***
55 * Converts the first char of a string to upper case.
56 *
57 * @param s The string to convert.
58 * @return The parameter string with the first character converted
59 * to uppercase if possible.
60 * @throws NullPointerException
61 * when <code>s == null</code>.
62 */
63 public static String capitalize( String s )
64 {
65 if( s.length() == 0 )
66 {
67 return s;
68 }
69
70 char chars[] = s.toCharArray();
71 chars[0] = Character.toUpperCase( chars[0] );
72 return new String( chars );
73 }
74
75 /***
76 * Converts the first char of a string to lower case.
77 *
78 * @param s The string to convert.
79 * @return The parameter string with the first character converted
80 * to lowercase if possible.
81 * @throws NullPointerException
82 * when <code>s == null</code>.
83 */
84 public static String decapitalize( String s )
85 {
86 if( s.length() == 0 )
87 {
88 return s;
89 }
90
91 char chars[] = s.toCharArray();
92 chars[0] = Character.toLowerCase( chars[0] );
93 return new String( chars );
94 }
95
96 /***
97 * Checks existence of bean property of the specified object.
98 *
99 * @param bean The specified object.
100 * @param name The specified bean property name.
101 * @return <code>true</code> if there are bean property read method.
102 * @throws NullPointerException
103 * If <code>bean</code> is <code>null</code>.
104 * @throws AttributeException
105 * Some possible reasons:
106 * <UL>
107 * <LI><CODE>name == null</CODE></LI>
108 * </UL>
109 * (analyze exception parameters).
110 * @see #getBeanPropertyReadMethod(Object,String)
111 */
112 public static boolean hasBeanProperty( Object bean, String name )
113 {
114 return getBeanPropertyReadMethod( bean, name ) != null;
115 }
116
117 /***
118 * Checks writability of bean property of the specified object.
119 *
120 * @param bean The specified object.
121 * @param name The specified bean property name.
122 * @return <code>true</code> if there are bean property write method.
123 * @throws NullPointerException
124 * If <code>bean</code> is <code>null</code>.
125 * @throws AttributeException
126 * Some possible reasons:
127 * <UL>
128 * <LI><CODE>name == null</CODE></LI>
129 * </UL>
130 * (analyze exception parameters).
131 * @see #getBeanPropertyWriteMethod(Object,String)
132 */
133 public static boolean isBeanPropertyWritable( Object bean, String name )
134 {
135 return getBeanPropertyWriteMethod( bean, name ) != null;
136 }
137
138 /***
139 * Returns a value of the specified bean property.
140 *
141 * @param bean The specified object.
142 * @param name The specified bean property name.
143 * @return The value of bean property of specified object.
144 * @throws NullPointerException
145 * If <code>bean</code> is <code>null</code>.
146 * @throws AttributeException
147 * Some possible reasons:
148 * <UL>
149 * <LI><CODE>name == null</CODE></LI>
150 * <LI>there is no attribute with the specified name</LI>
151 * <LI>there was an underlying exception</LI>
152 * </UL>
153 * (analyze exception parameters).
154 * @see #hasBeanProperty(Object,String)
155 */
156 public static Object getBeanProperty( Object bean, String name )
157 {
158 Method method = getBeanPropertyReadMethod( bean, name );
159
160 if( method == null )
161 {
162 throw new AttributeException( bean, name );
163 }
164
165 try
166 {
167 return method.invoke( bean, get_par );
168 }
169 catch( Exception e )
170 {
171 throw new AttributeException( bean, name, null, e );
172 }
173 }
174
175 /***
176 * Checks if a value of the bean property can be indexed.
177 * This method uses {@link #getBeanProperty(Object, String) getBeanProperty(bean,name)}
178 * to get property value.
179 *
180 * @param bean The specified object.
181 * @param name The specified bean property name.
182 * @return <code>true</code> if value of bean property {@link #isIndexed(Object) is indexed}.
183 * @throws NullPointerException
184 * If <code>bean</code> is <code>null</code>.
185 * @throws AttributeException
186 * Some possible reasons:
187 * <UL>
188 * <LI><CODE>name == null</CODE></LI>
189 * <LI>there is no attribute with the specified name</LI>
190 * <LI>attribute value is null</LI>
191 * <LI>there was an underlying exception</LI>
192 * </UL>
193 * (analyze exception parameters).
194 * @throws AttributeException
195 * If bean property with the specified name doesn't exist (cause == null),
196 * or there was an underlying exception (see cause).
197 */
198 public static boolean isBeanPropertyIndexed( Object bean, String name )
199 {
200 Object value = getBeanProperty( bean, name );
201
202 try
203 {
204 return isIndexed( value );
205 }
206 catch( Exception e )
207 {
208 throw new AttributeException( bean, name, value, e );
209 }
210 }
211
212 /***
213 * Sets the new value of the specified bean property.
214 *
215 * @param bean The specified object.
216 * @param name The specified bean property name.
217 * @param value The new value of bean property.
218 * @throws NullPointerException
219 * If <code>bean</code> is <code>null</code>.
220 * @throws AttributeException
221 * Some possible reasons:
222 * <UL>
223 * <LI><CODE>name == null</CODE></LI>
224 * <LI>there is no attribute with the specified name</LI>
225 * <LI>there was an underlying exception</LI>
226 * </UL>
227 * (analyze exception parameters).
228 */
229 public static void setBeanProperty( Object bean, String name, Object value )
230 {
231 Method method = getBeanPropertyWriteMethod( bean, name );
232
233 if( method == null )
234 {
235 throw new AttributeException( bean, name, value );
236 }
237
238 set_par[0] = value;
239 try
240 {
241 method.invoke( bean, set_par );
242 }
243 catch( Exception e )
244 {
245 throw new AttributeException( bean, name, value, e );
246 }
247 }
248
249 /***
250 * Returns the set of names of bean properties of the specified object.
251 * @param bean The specified object.
252 * @return The set that contains names of all object's bean properties.
253 * @throws NullPointerException
254 * If bean is null.
255 */
256 public static Set
257 {
258 return getBeanClassPropertyNames( bean.getClass() );
259 }
260
261 /***
262 * Returns the set of names of bean properties for objects of the specified class.
263 * @param cls The specified class.
264 * @return The set that contains names of bean properties for objects of
265 * the specified class.
266 * @throws NullPointerException
267 * If cls is null.
268 */
269 public static Set
270 {
271 return getBeanClassPropertyDescriptors( cls ).keySet();
272 }
273
274
275
276
277 /***
278 * Checks if value can be indexed.
279 * A value is indexed if it is an array or instance of {@link List}.
280 * <CODE>null</CODE> is not indexed value.
281 *
282 * @param value The specified value.
283 * @return <code>true</code> if the specified value is array
284 * or instance of {@link List}.
285 */
286 public static boolean isIndexed( Object value )
287 {
288 return value != null && (value.getClass().isArray() || value instanceof List);
289 }
290
291 /***
292 * Returns the size of the indexed value.
293 *
294 * @param value The specified indexed value.
295 * @return Size of the specified indexed value.
296 * @throws NullPointerException
297 * If the specified value is <code>null</code>.
298 * @throws ClassCastException
299 * If the specified value {@link #isIndexed(Object) is not indexed}.
300 */
301 public static int sizeIndexed( Object value )
302 {
303 if( value.getClass().isArray() )
304 {
305 return Array.getLength( value );
306 }
307 return ((List)value).size();
308 }
309
310 /***
311 * Returns element of the specified index value.
312 *
313 * @param value The specified indexed value.
314 * @param index The specified index.
315 * @return An element of array or list with the specified index.
316 * @throws NullPointerException
317 * If the specified value is <code>null</code>.
318 * @throws ClassCastException
319 * If the specified value {@link #isIndexed(Object) is not indexed}.
320 * @throws IndexOutOfBoundsException
321 * If the specified index is out of bounds of indexed value.
322 */
323 public static Object getIndexed( Object value, int index )
324 {
325 if( value.getClass().isArray() )
326 {
327 return Array.get( value, index );
328 }
329 return ((List)value).get( index );
330 }
331
332 /***
333 * Sets the new element's value of indexed value.
334 *
335 * @param value The specified indexed value.
336 * @param index The specified index.
337 * @param elem The new value of element.
338 * @throws NullPointerException
339 * If <code>value</code> is <code>null</code>.
340 * @throws ClassCastException
341 * If the specified value {@link #isIndexed(Object) is not indexed}.
342 * @throws IndexOutOfBoundsException
343 * If the specified index is out of bounds of indexed value.
344 */
345 public static void setIndexed( Object value, int index, Object elem )
346 {
347 if( value.getClass().isArray() )
348 {
349 Array.set( value, index, elem );
350 } else {
351 ((List)value).set( index, elem );
352 }
353 }
354
355
356
357
358
359 /***
360 * Checks existence of an attribute with the specified name of the specified object.
361 *
362 * @param obj The specified object.
363 * @param name The specified attribute name.
364 * @return If <code>obj</code> implements {@link Attributed} interface use
365 * {@link Attributed#hasAttribute(String) its method} to get attribute value.
366 * Otherwise {@link #hasBeanProperty(Object,String) check existence of bean property}.
367 * @throws NullPointerException
368 * If <code>obj</code> is <code>null</code>.
369 * @throws AttributeException
370 * Some possible reasons:
371 * <UL>
372 * <LI><CODE>name == null</CODE></LI>
373 * <LI>there was an underlying exception</LI>
374 * </UL>
375 * (analyze exception parameters).
376 * @since 3.6.3
377 */
378 public static boolean hasAttribute( Object obj, String name )
379 {
380 if( obj instanceof Attributed )
381 {
382 return ((Attributed)obj).hasAttribute( name );
383 } else {
384 return hasBeanProperty( obj, name );
385 }
386 }
387
388 /***
389 * Returns value of attribute of the specified object.
390 *
391 * @param obj The specified object.
392 * @param name The specified attribute name.
393 * @return If <code>obj</code> implements {@link Attributed} interface use
394 * {@link Attributed#getAttribute(String) its method} to get attribute value.
395 * Otherwise return {@link #getBeanProperty(Object,String) bean property value}.
396 * @throws NullPointerException
397 * If <code>obj</code> is <code>null</code>.
398 * @throws AttributeException
399 * Some possible reasons:
400 * <UL>
401 * <LI><CODE>name == null</CODE></LI>
402 * <LI>there is no attribute with the specified name</LI>
403 * <LI>there was an underlying exception</LI>
404 * </UL>
405 * (analyze exception parameters).
406 */
407 public static Object getAttribute( Object obj, String name )
408 {
409 if( obj instanceof Attributed )
410 {
411 return ((Attributed)obj).getAttribute( name );
412 } else {
413 return getBeanProperty( obj, name );
414 }
415 }
416
417 /***
418 * Returns size of indexed attribute of the specified object.
419 *
420 * @param obj The specified object.
421 * @param name The specified attribute name.
422 * @return If <code>obj</code> implements {@link Attributed} interface use
423 * {@link Attributed#sizeAttribute(String) its method} to get attribute size.
424 * Otherwise {@link #getAttribute(Object,String) get attribute value}
425 * and return {@link #sizeIndexed(Object) its size}.
426 * @throws NullPointerException
427 * If <code>obj</code> is <code>null</code>.
428 * @throws AttributeException
429 * Some possible reasons:
430 * <UL>
431 * <LI><CODE>name == null</CODE></LI>
432 * <LI>there is no attribute with the specified name</LI>
433 * <LI>attribute value is not indexed</LI>
434 * <LI>there was an underlying exception</LI>
435 * </UL>
436 * (analyze exception parameters).
437 */
438 public static int sizeAttribute( Object obj, String name )
439 {
440 if( obj instanceof Attributed )
441 {
442 return ((Attributed)obj).sizeAttribute( name );
443 } else {
444 Object value = getAttribute( obj, name );
445 try
446 {
447 return sizeIndexed( value );
448 }
449 catch( Exception e )
450 {
451 throw new AttributeException( obj, name, value, e );
452 }
453 }
454 }
455
456 /***
457 * Returns element of indexed attribute by index.
458 *
459 * @param obj The specified object.
460 * @param name The specified attribute name.
461 * @param index The specified index.
462 * @return If <code>obj</code> implements {@link Attributed} interface use
463 * {@link Attributed#getAttribute(String,int) its method} to get
464 * attribute element.
465 * Otherwise {@link #getAttribute(Object,String) get attribute value}
466 * and return {@link #getIndexed(Object,int) its element by index}.
467 * @throws NullPointerException
468 * If <code>obj</code> is <code>null</code>.
469 * @throws AttributeException
470 * Some possible reasons:
471 * <UL>
472 * <LI><CODE>name == null</CODE></LI>
473 * <LI>there is no attribute with the specified name</LI>
474 * <LI>attribute value is not indexed</LI>
475 * <LI>there was an underlying exception</LI>
476 * </UL>
477 * (analyze exception parameters).
478 */
479 public static Object getAttribute( Object obj, String name, int index )
480 {
481 if( obj instanceof Attributed )
482 {
483 return ((Attributed)obj).getAttribute( name, index );
484 } else {
485 Object value = getAttribute( obj, name );
486 try
487 {
488 return getIndexed( value, index );
489 }
490 catch( Exception e )
491 {
492 throw new AttributeException( obj, name, value, e );
493 }
494 }
495 }
496
497 /***
498 * Sets the new value of attribute.
499 * If <code>obj</code> implements {@link Attributed} interface use
500 * {@link Attributed#setAttribute(String,Object) its method} to set
501 * attribute.
502 * Otherwise tries {@link #setBeanProperty(Object, String, Object) to set bean property}
503 *
504 * @param obj The specified object.
505 * @param name The specified attribute name.
506 * @param value The new value of attribute.
507 * @throws AttributeException
508 * Some possible reasons:
509 * <UL>
510 * <LI><CODE>name == null</CODE></LI>
511 * <LI>there is no attribute with the specified name</LI>
512 * <LI>attribute is not writable</LI>
513 * <LI>attribute element type is not compatible with <CODE>elem</CODE></LI>
514 * <LI>there was an underlying exception</LI>
515 * </UL>
516 * (analyze exception parameters).
517 * @since 3.5.3
518 */
519 public static void setAttribute( Object obj
520 , String name
521 , Object value
522 )
523 {
524 if( obj instanceof Attributed )
525 {
526 ((Attributed)obj).setAttribute( name, value);
527 } else {
528 setBeanProperty( obj, name, value );
529 }
530 }
531
532 /***
533 * Sets the new value of element of indexed attribute by index.
534 * If <code>obj</code> implements {@link Attributed} interface use
535 * {@link Attributed#setAttribute(String,int,Object) its method} to set
536 * attribute element.
537 * Otherwise {@link #getAttribute(Object,String) get attribute value}
538 * and {@link #setIndexed(Object,int,Object) set its element by index}.
539 *
540 * @param obj The specified object.
541 * @param name The specified attribute name.
542 * @param index The specified index.
543 * @param elem The new value of element.
544 * @throws AttributeException
545 * Some possible reasons:
546 * <UL>
547 * <LI><CODE>name == null</CODE></LI>
548 * <LI>there is no attribute with the specified name</LI>
549 * <LI>attribute is not writable</LI>
550 * <LI>attribute is not indexed</LI>
551 * <LI>attribute index is out of bounds</LI>
552 * <LI>attribute element type is not compatible with <CODE>elem</CODE></LI>
553 * <LI>there was an underlying exception</LI>
554 * </UL>
555 * (analyze exception parameters).
556 */
557 public static void setAttribute( Object obj
558 , String name
559 , int index
560 , Object elem
561 )
562 {
563 if( obj instanceof Attributed )
564 {
565 ((Attributed)obj).setAttribute( name, index, elem);
566 } else {
567 Object value = getAttribute( obj, name );
568 try
569 {
570 setIndexed( value, index, elem );
571 }
572 catch( Exception e )
573 {
574 throw new AttributeException( obj, name, value, e );
575 }
576 }
577 }
578
579 /***
580 * Returns the set of attribute names the specified object.
581 * @param obj The specified object.
582 * @return If <code>obj</code> implements {@link Attributed} interface use
583 * {@link Attributed#getAttributeNames() its method} to get attribute names.
584 * Otherwise {@link #getBeanPropertyNames(Object) get bean property names}.
585 */
586 public static Set
587 {
588 if( obj instanceof Attributed )
589 {
590 return ((Attributed)obj).getAttributeNames();
591 } else {
592 return getBeanPropertyNames( obj );
593 }
594 }
595
596 /***
597 * Checks whether the given name is a valid identifier.
598 * This method uses {@link Character#isUnicodeIdentifierStart(char)}
599 * and {@link Character#isUnicodeIdentifierPart(char)} methods.
600 *
601 * @param name the name to check
602 * @return <code>true</code> if the given name is a valid identifier,
603 * <code>false</code> otherwise.
604 */
605 public static boolean isID( String name )
606 {
607 int l = name.length();
608
609 if( l == 0 )
610 {
611 return false;
612 }
613
614 char[] chars = name.toCharArray();
615
616 if( !Character.isUnicodeIdentifierStart( chars[0] ) )
617 {
618 return false;
619 }
620
621 for( int i = 1; i < chars.length; i++ )
622 {
623 if( !Character.isUnicodeIdentifierPart( chars[i] ) )
624 {
625 return false;
626 }
627 }
628 return true;
629 }
630
631 /***
632 * Возвращает значение, на которое указывает заданная цепочка атрибутов для данного объекта.
633 * Цепочка атрибутов имеет следующий вид:
634 * <P><BLOCKQUOTE><code>
635 * path ::= attribute ( "." attribute )* ;<BR>
636 * attribute ::= <attr_name:ID> ( "[" index "]" )? ;<BR>
637 * index ::= <index_var:ID> | number ;<BR>
638 * number ::= ( "-" )? ( <DIGIT> )+ ;<BR>
639 * </BLOCKQUOTE></code>
640 * <P>Каждый элемент цепочки является либо именем атрибута, либо именем списочного атрибута
641 * с указанным в скобках индексом элемента. Индекс может быть задан именем переменной
642 * <code>index_var</code>, значение которой берется из <code>variable_map</code> как значение
643 * соответствующего атрибута, или целочисленным литералом <code>number</code>.
644 * Отрицательному индексу -i соответствует элемент списка с индексом L-i, где L - длина списка.
645 * <P>Значение, на которое указывает цепочка атрибутов, определяется рекурсивно:
646 * <UL>
647 * <LI>Для цепочки длины нуль это значение самого объекта.</LI>
648 * <LI>Для цепочки длины k рекурсивно находим объект, на который указывает цепочка длины k-1.
649 * Результатом является значение k-го элемента цепочки, применённого к этого объекту.</LI>
650 * </UL>
651 *
652 * @param obj The specified object.
653 * @param path The chain of attribute names.
654 * @param variableMap Defined variables.
655 * @return The value pointed by path of attributes.
656 * @see #getAttribute(Object,String)
657 * @see #getAttribute(Object, String, int)
658 */
659 public static Object getAttribute( Object obj
660 , String path
661 , Attributed variableMap
662 )
663 {
664 int from = 0;
665 int to = 0;
666
667 Object nextobj;
668 String attrname;
669 int realindex = -1;
670
671 while( true )
672 {
673 to = path.indexOf( '.', from );
674 if( to == -1 )
675 {
676 to = path.length();
677 }
678
679 int bracket = path.indexOf ( '[', from );
680 if( bracket >= 0 && bracket < to )
681 {
682
683 attrname = path.substring( from, bracket );
684 if( path.charAt( to - 1 ) != ']' )
685 {
686 throw new AttributePathException( AttributePathException.NO_CLOSING_BRACKET
687 , obj
688 , path
689 , bracket
690 , null
691 );
692 }
693
694 String index_string = path.substring( bracket + 1, to - 1 );
695
696 if( isID( index_string ) )
697 {
698 Object mapped_index;
699 try
700 {
701 mapped_index = variableMap.getAttribute( index_string );
702 }
703 catch( AttributeException e )
704 {
705 throw new AttributePathException
706 ( AttributePathException.ATTRIBUTED_EXCEPTION
707 , obj
708 , path
709 , bracket + 1
710 , e
711 );
712 }
713 try
714 {
715 realindex = ((Integer)mapped_index).intValue();
716 }
717 catch( ClassCastException e )
718 {
719 throw new AttributePathException( AttributePathException.INDEX_VALUE
720 , obj
721 , path
722 , bracket + 1
723 , e
724 );
725 }
726 } else {
727
728 try
729 {
730 realindex = Integer.parseInt( index_string );
731 }
732 catch ( NumberFormatException e )
733 {
734 throw new AttributePathException( AttributePathException.INDEX_VALUE
735 , obj
736 , path
737 , bracket + 1
738 , e
739 );
740 }
741 if( realindex < 0 )
742 {
743 try
744 {
745 realindex = sizeAttribute( obj, attrname ) + realindex;
746 }
747 catch( AttributeException e )
748 {
749 throw new AttributePathException
750 ( AttributePathException.ATTRIBUTED_EXCEPTION
751 , obj
752 , path
753 , from
754 , e
755 );
756 }
757 }
758 }
759 try
760 {
761 nextobj = getAttribute( obj, attrname, realindex );
762 }
763 catch( AttributeException e )
764 {
765 throw new AttributePathException( AttributePathException.ATTRIBUTED_EXCEPTION
766 , obj
767 , path
768 , from
769 , e
770 );
771 }
772 } else {
773 attrname = path.substring( from, to );
774 try
775 {
776 nextobj = getAttribute( obj, attrname );
777 }
778 catch( AttributeException e )
779 {
780 throw new AttributePathException( AttributePathException.ATTRIBUTED_EXCEPTION
781 , obj
782 , path
783 , from
784 , e
785 );
786 }
787 }
788
789 if( to != path.length() )
790 {
791 from = to + 1;
792 realindex = -1;
793 obj = nextobj;
794 } else {
795 return nextobj;
796 }
797 }
798 }
799
800
801
802
803 private static class PropertyDescriptor
804 {
805 private Method read_method;
806 private Method write_method;
807
808 public PropertyDescriptor( Method read_method, Method write_method )
809 {
810 this.read_method = read_method;
811 this.write_method = write_method;
812 }
813
814 public Method getReadMethod()
815 {
816 return read_method;
817 }
818
819 public Method getWriteMethod()
820 {
821 return write_method;
822 }
823 }
824
825 private static Map
826 getBeanClassPropertyDescriptors( Class cls )
827 {
828 if( class_to_properties_descriptor.containsKey( cls ) )
829 {
830 return (Map
831 class_to_properties_descriptor.get( cls );
832 }
833
834 Method[] methods = cls.getMethods();
835 Map
836 = new HashMap
837
838 for( int i = 0; i < methods.length; i++ )
839 {
840 if( methods[i].getParameterTypes().length == 0
841 && !methods[i].getReturnType().equals( void.class )
842 )
843 {
844 String method_name = methods[i].getName();
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865 if( method_name.startsWith( "get" )
866 && method_name.length() > "get".length()
867 )
868 {
869 String capitalized_property_name
870 = method_name.substring( "get".length() );
871 Method read_method = methods[i];
872 read_method.setAccessible( true );
873
874 res.put( decapitalize( capitalized_property_name )
875 , new PropertyDescriptor
876 ( read_method
877 , findWriteMethod( cls
878 , read_method
879 , capitalized_property_name
880 )
881 )
882 );
883 }
884 }
885 }
886
887 class_to_properties_descriptor.put( cls, res );
888
889 return res;
890 }
891
892 private static Method findWriteMethod( Class cls
893 , Method read_method
894 , String capitalizedPropertyName
895 )
896 {
897 try
898 {
899 set_type[0] = read_method.getReturnType();
900 Method write_method = cls.getMethod( "set" + capitalizedPropertyName
901 , set_type
902 );
903 if( write_method != null ) write_method.setAccessible( true );
904 return write_method;
905 }
906 catch( Exception e )
907 {
908 return null;
909 }
910 }
911
912 /***
913 * Returns read method for the specified property of the specified bean.
914 * @param bean Object to get read method from.
915 * @param name Property name.
916 * @return Read method or <code>null</code> if object has
917 * no property with such name.
918 * @throws NullPointerException
919 * If <code>bean</code> is <code>null</code>.
920 * @throws AttributeException
921 * Some possible reasons:
922 * <UL>
923 * <LI><CODE>name == null</CODE></LI>
924 * </UL>
925 * (analyze exception parameters).
926 */
927 protected static Method getBeanPropertyReadMethod( Object bean
928 , String name
929 )
930 {
931 if( name == null )
932 {
933 throw new AttributeException( bean, name );
934 }
935 PropertyDescriptor pd
936 = (PropertyDescriptor)
937 getBeanClassPropertyDescriptors( bean.getClass() )
938 .get( name );
939
940 return pd != null ? pd.getReadMethod() : null;
941 }
942
943 /***
944 * Returns write method for the specified property of the specified bean.
945 * @param bean Object to get write method from.
946 * @param name Property name.
947 * @return Write method or <code>null</code> if object has
948 * no property with such name.
949 * @throws NullPointerException
950 * If <code>bean</code> is <code>null</code>.
951 * @throws AttributeException
952 * Some possible reasons:
953 * <UL>
954 * <LI><CODE>name == null</CODE></LI>
955 * </UL>
956 * (analyze exception parameters).
957 */
958 protected static Method getBeanPropertyWriteMethod( Object bean
959 , String name
960 )
961 {
962 if( name == null )
963 {
964 throw new AttributeException( bean, name );
965 }
966 PropertyDescriptor pd
967 = (PropertyDescriptor)
968 getBeanClassPropertyDescriptors( bean.getClass() )
969 .get( name );
970
971 return pd != null ? pd.getWriteMethod() : null;
972 }
973
974 private static Class[] set_type = new Class[1];
975
976 private static Object[] get_par = new Object[0];
977 private static Object[] set_par = new Object[1];
978
979 private static Map
980 class_to_properties_descriptor
981 = new HashMap
982 }