001    package com.sptci;
002    
003    import java.beans.BeanInfo;
004    import java.beans.Introspector;
005    import java.beans.IntrospectionException;
006    import java.beans.PropertyDescriptor;
007    
008    import java.lang.reflect.Field;
009    import java.lang.reflect.Method;
010    import java.lang.reflect.Modifier;
011    
012    import java.util.Map;
013    import java.util.HashMap;
014    
015    /**
016     * A utility class to handle common reflection tasks.
017     *
018     * <p>Copyright 2006 Sans Pareil Technologies, Inc.</p>
019     * @author Rakesh Vidyadharan 2006-02-07
020     * @version $Id: ReflectionUtility.java,v 1.3 2006/02/09 16:09:58 rakesh Exp $
021     */
022    public final class ReflectionUtility
023    {
024      /**
025       * Default constructor.  Cannot be instantiated.
026       */
027      private ReflectionUtility() {}
028    
029      /**
030       * Return the <code>Field</code> instance with the specified name
031       * from the <code>object</code>.  Sets the field accessible if
032       * it is not accessible.
033       *
034       * @param name The name of the field to look up.
035       * @param object The object from which the field is to be retrieved.
036       * @throws NoSuchFieldException If no field with the specified name
037       *   exists in <code>object</code>.
038       */
039      public static final Field fetchField( String name, Object object ) 
040        throws NoSuchFieldException
041      {
042        Field field = object.getClass().getDeclaredField( name );
043    
044        if ( ! Modifier.isPublic( field.getModifiers() ) )
045        {
046          field.setAccessible( true );
047        }
048    
049        return field;
050      }
051    
052      /**
053       * Return the <code>Object</code> instance represented by the 
054       * specified name from <code>object</code>.
055       *
056       * @see #fetchField
057       * @param name The name of the object to fetch.
058       * @param object The object from which the field is to be retrieved.
059       * @return Object The object instance for the specified field.
060       * @throws NoSuchFieldException If no field with the specified name
061       *   exists in <code>object</code>.
062       * @throws IllegalAccessException If the field cannot be accessed
063       *   due to custom security policies.
064       */
065      public static final Object fetchObject( String name, Object object ) 
066        throws NoSuchFieldException, IllegalAccessException
067      {
068        return fetchField( name, object ).get( object );
069      }
070    
071      /**
072       * Return the declared fields for the specified <code>object</code>.
073       *
074       * @see #fetchFields( Class )
075       * @param object The object whose declared fields are to be
076       *   retrieved.
077       * @return Map A map with the field names as <code>key</code> and
078       *   the field as <code>value</code>
079       */
080      public static final Map<String, Field> fetchFields( Object object )
081      {
082        return fetchFields( object.getClass() );
083      }
084    
085      /**
086       * Return the declared fields for the specified <code>Class</code>.
087       *
088       * @param cls The class whose declared fields are to be
089       *   retrieved.
090       * @return Map A map with the field names as <code>key</code> and
091       *   the field as <code>value</code>
092       */
093      public static final Map<String, Field> fetchFields( Class cls )
094      {
095        Map<String, Field> map = new HashMap<String, Field>();
096    
097        for ( Field field : cls.getDeclaredFields() ) 
098        {
099          if ( ! Modifier.isPublic( field.getModifiers() ) )
100          {
101            field.setAccessible( true );
102          }
103    
104          map.put( field.getName(), field );
105        }
106    
107        return map;
108      }
109    
110      /**
111       * Return the <code>Object</code> instances representing the declared 
112       * fields for the specified <code>object</code>.
113       *
114       * @see #fetchFields
115       * @param object The object for which objects for the declared fields 
116       *   are to be retrieved.
117       * @return Map A map with the field names as <code>key</code> and
118       *   the object as <code>value</code>
119       * @throws IllegalAccessException If a custom security policy prevents
120       *   access to the fields.
121       */
122      public static final Map<String, Object> fetchObjects( Object object )
123        throws IllegalAccessException
124      {
125        Map<String, Object> map = new HashMap<String, Object>();
126    
127        for ( Map.Entry<String, Field> entry : fetchFields( object ).entrySet() )
128        {
129          Object obj = entry.getValue().get( object );
130          map.put( entry.getKey(), obj );
131        }
132    
133        return map;
134      }
135    
136      /**
137       * Fetch the <code>Method</code> defined in the specified field with
138       * the specified <code>name</code> that accepts the specified
139       * parameters.
140       *
141       * @see #fetchMethod( Class, String, Class[] )
142       * @param field The field whose method is to be retrieved.
143       * @param name The name of the method to retrieve.
144       * @param parameters The parameters accepted by the method.
145       */
146      public static final Method fetchMethod( Field field, String name, 
147          Class[] parameters )
148      {
149        return fetchMethod( field.getType(), name, parameters );
150      }
151    
152      /**
153       * Fetch the <code>Method</code> defined in the specified object with
154       * the specified <code>name</code> that accepts the specified
155       * parameters.
156       *
157       * @see #fetchMethod( Class, String, Class[] )
158       * @param object The object whose method is to be retrieved.
159       * @param name The name of the method to retrieve.
160       * @param parameters The parameters accepted by the method.
161       */
162      public static final Method fetchMethod( Object object, String name, 
163          Class[] parameters )
164      {
165        return fetchMethod( object.getClass(), name, parameters );
166      }
167    
168      /**
169       * Fetch the <code>Method</code> defined in the specified class with
170       * the specified <code>name</code> that accepts the specified
171       * parameters.
172       *
173       * @param cls The cls whose method is to be retrieved.
174       * @param name The name of the method to retrieve.
175       * @param parameters The parameters accepted by the method.
176       */
177      public static final Method fetchMethod( Class cls, String name, 
178          Class[] parameters )
179      {
180        Method method = null;
181        while ( method == null && cls != null )
182        {
183          try
184          {
185            method = cls.getDeclaredMethod( name, parameters );
186          }
187          catch ( NoSuchMethodException nsme ) {}
188    
189          cls = cls.getSuperclass();
190        }
191    
192        return method;
193      }
194    
195      /**
196       * Fetches the accessor method for the specified property in
197       * the specified object.
198       *
199       * @see #fetchAccessor( String, Class )
200       * @param property The property whose accessor is to be fetched.
201       * @param object The object to which the property belongs.
202       * @return Method The accessor method for the property.
203       * @throws IntrospectionException If errors are encountered while
204       *   introspecting the specified class.
205       */
206      public static final Method fetchAccessor( String property, 
207          Object object ) throws IntrospectionException
208      {
209        return fetchAccessor( property, object.getClass() );
210      }
211    
212      /**
213       * Fetches the accessor method for the specified property in
214       * the specified class.
215       *
216       * @param property The property whose accessor is to be fetched.
217       * @param cls The class to which the property belongs.
218       * @return Method The accessor method for the property.
219       * @throws IntrospectionException If errors are encountered while
220       *   introspecting the specified class.
221       */
222      public static final Method fetchAccessor( String property, Class cls )
223        throws IntrospectionException
224      {
225        Method method = null;
226        BeanInfo beanInfo = Introspector.getBeanInfo( cls );
227        for ( PropertyDescriptor descriptor : 
228            beanInfo.getPropertyDescriptors() )
229        {
230          if ( descriptor.getName().equals( property ) )
231          {
232            method = descriptor.getReadMethod();
233          }
234        }
235    
236        return method;
237      }
238    
239      /**
240       * Fetches the mutator method for the specified property in
241       * the specified object.
242       *
243       * @see #fetchMutator( String, Class )
244       * @param property The property whose mutator is to be fetched.
245       * @param object The object to which the property belongs.
246       * @return Method The mutator method for the property.
247       * @throws IntrospectionException If errors are encountered while
248       *   introspecting the specified class.
249       */
250      public static final Method fetchMutator( String property, 
251          Object object ) throws IntrospectionException
252      {
253        return fetchMutator( property, object.getClass() );
254      }
255    
256      /**
257       * Fetches the mutator method for the specified property in
258       * the specified class.
259       *
260       * @param property The property whose mutator is to be fetched.
261       * @param cls The class to which the property belongs.
262       * @return Method The mutator method for the property.
263       * @throws IntrospectionException If errors are encountered while
264       *   introspecting the specified class.
265       */
266      public static final Method fetchMutator( String property, Class cls )
267        throws IntrospectionException
268      {
269        Method method = null;
270        BeanInfo beanInfo = Introspector.getBeanInfo( cls );
271        for ( PropertyDescriptor descriptor : 
272            beanInfo.getPropertyDescriptors() )
273        {
274          if ( descriptor.getName().equals( property ) )
275          {
276            method = descriptor.getWriteMethod();
277          }
278        }
279    
280        return method;
281      }
282    }