View Javadoc

1   /*
2    * @(#) DSOLIntrospector.java Apr 15, 2004 Copyright (c) 2002-2005 Delft
3    * University of Technology Jaffalaan 5, 2628 BX Delft, the Netherlands. All
4    * rights reserved. This software is proprietary information of Delft University
5    * of Technology The code is published under the Lesser General Public License
6    */
7   package nl.tudelft.simulation.introspection.fields;
8   
9   import java.lang.reflect.Field;
10  import java.util.ArrayList;
11  import java.util.Arrays;
12  import java.util.HashSet;
13  import java.util.List;
14  import java.util.Set;
15  
16  import nl.tudelft.simulation.introspection.Introspector;
17  import nl.tudelft.simulation.introspection.Property;
18  import nl.tudelft.simulation.logger.Logger;
19  
20  /***
21   * The IntrospectionField introspector provides a field manipulation
22   * implementation of the introspection interfaces. Its behavior adhers to the
23   * following:
24   * <ul>
25   * <li>Properties are discovered by searching for an object's fields
26   * (visibility neutral)</li>
27   * <li>Property value are manipulated by setting field values (visibility
28   * neutral)</li>
29   * </ul>
30   * <p>
31   * During construction, one can choose for either deep introspection (i.e.
32   * including fields from all superclasses), or regular introspection (inlude
33   * declared fields only). (c) copyright 2002-2005-2004 <a
34   * href="http://www.simulation.tudelft.nl">Delft University of Technology </a>,
35   * the Netherlands. <br>
36   * See for project information <a
37   * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
38   * License of use: <a href="http://www.gnu.org/copyleft/lesser.html">Lesser
39   * General Public License (LGPL) </a>, no warranty.
40   * 
41   * @author <a
42   *         href="http://web.eur.nl/fbk/dep/dep1/Introduction/Staff/People/Lang">Niels
43   *         Lang </a><a href="http://www.peter-jacobs.com/index.htm">Peter
44   *         Jacobs </a>
45   * @version 1.1 Apr 15, 2004
46   * @since 1.5
47   */
48  
49  public class FieldIntrospector implements Introspector
50  {
51      /*** useDeepIntrospection */
52      private boolean useDeepIntrospection = true;
53  
54      /***
55       * constructs a new FieldIntrospector
56       */
57      public FieldIntrospector()
58      {
59          this(false);
60      }
61  
62      /***
63       * constructs a new FieldIntrospector
64       * 
65       * @param useDeepIntrospection whether to use deep introspection
66       */
67      public FieldIntrospector(final boolean useDeepIntrospection)
68      {
69          this.useDeepIntrospection = useDeepIntrospection;
70      }
71  
72      /***
73       * @see nl.tudelft.simulation.introspection.Introspector#getProperties(Object)
74       */
75      public Property[] getProperties(final Object introspected)
76      {
77          Set<Property> props = new HashSet<Property>();
78          try
79          {
80              Field[] fields = collectFields(introspected.getClass());
81              for (int i = 0; i < fields.length; i++)
82              {
83                  props.add(new FieldProperty(introspected, fields[i]));
84              }
85          } catch (Exception e)
86          {
87              Logger.warning(this, "getProperties", e);
88          }
89          return props.toArray(new Property[props.size()]);
90      }
91  
92      /***
93       * Collect the fields for the given class, taking the preference for deep
94       * introspection into account.
95       * 
96       * @param clasz the class to use
97       * @return Field[] the fields
98       */
99      private Field[] collectFields(final Class clasz)
100     {
101         List<Field> fields = new ArrayList<Field>(10);
102         this.addFields(fields, clasz, this.useDeepIntrospection);
103         return fields.toArray(new Field[fields.size()]);
104     }
105 
106     /***
107      * Add fields of 'clasz' to the fieldList. Optionally iterate over the class
108      * hierarchy.
109      * 
110      * @param fieldList the fieldList
111      * @param clasz the class
112      * @param iterate whether to iterate
113      */
114     private void addFields(final List<Field> fieldList, final Class< ? > clasz,
115             final boolean iterate)
116     {
117         fieldList.addAll(Arrays.asList(clasz.getDeclaredFields()));
118         if (iterate && clasz.getSuperclass() != null)
119         {
120             addFields(fieldList, clasz.getSuperclass(), iterate);
121         }
122     }
123 
124     /***
125      * @see nl.tudelft.simulation.introspection.Introspector#getProperty(Object,
126      *      String)
127      */
128     public Property getProperty(final Object introspected, final String property)
129     {
130         try
131         {
132             Field[] fields = collectFields(introspected.getClass());
133             for (int i = 0; i < fields.length; i++)
134             {
135                 if (fields[i].getName().equals(property))
136                 {
137                     return new FieldProperty(introspected, fields[i]);
138                 }
139             }
140         } catch (Exception e)
141         {
142             Logger.warning(this, "getProperty", e);
143         }
144         throw new IllegalArgumentException("Property '" + property
145                 + "' not found for " + introspected);
146     }
147 
148     /***
149      * @see nl.tudelft.simulation.introspection.Introspector#getPropertyNames(Object)
150      */
151     public String[] getPropertyNames(final Object introspected)
152     {
153         Set<String> props = new HashSet<String>();
154         try
155         {
156             Field[] fields = collectFields(introspected.getClass());
157             for (int i = 0; i < fields.length; i++)
158             {
159                 props.add(fields[i].getName());
160             }
161         } catch (Exception e)
162         {
163             Logger.warning(this, "getPropertyNames", e);
164         }
165         return props.toArray(new String[props.size()]);
166     }
167 }