KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > groovy > inspect > Inspector


1 package groovy.inspect;
2
3 import groovy.lang.GroovyObject;
4 import groovy.lang.MetaClass;
5 import groovy.lang.MetaMethod;
6 import groovy.lang.PropertyValue;
7
8 import java.lang.reflect.Modifier JavaDoc;
9 import java.lang.reflect.Method JavaDoc;
10 import java.lang.reflect.Field JavaDoc;
11 import java.lang.reflect.Constructor JavaDoc;
12 import java.util.*;
13
14 import org.codehaus.groovy.runtime.InvokerHelper;
15 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
16
17 /**
18  * The Inspector provides a unified access to an object's
19  * information that can be determined by introspection.
20  *
21  * @author Dierk Koenig
22  */

23 public class Inspector {
24     protected Object JavaDoc objectUnderInspection = null;
25
26     // Indexes to retrieve Class Property information
27
public static final int CLASS_PACKAGE_IDX = 0;
28     public static final int CLASS_CLASS_IDX = 1;
29     public static final int CLASS_INTERFACE_IDX = 2;
30     public static final int CLASS_SUPERCLASS_IDX = 3;
31     public static final int CLASS_OTHER_IDX = 4;
32
33     // Indexes to retrieve field and method information
34
public static final int MEMBER_ORIGIN_IDX = 0;
35     public static final int MEMBER_MODIFIER_IDX = 1;
36     public static final int MEMBER_DECLARER_IDX = 2;
37     public static final int MEMBER_TYPE_IDX = 3;
38     public static final int MEMBER_NAME_IDX = 4;
39     public static final int MEMBER_PARAMS_IDX = 5;
40     public static final int MEMBER_VALUE_IDX = 5;
41     public static final int MEMBER_EXCEPTIONS_IDX = 6;
42
43     public static final String JavaDoc NOT_APPLICABLE = "n/a";
44     public static final String JavaDoc GROOVY = "GROOVY";
45     public static final String JavaDoc JAVA = "JAVA";
46
47     /**
48      * @param objectUnderInspection must not be null
49      */

50     public Inspector(Object JavaDoc objectUnderInspection) {
51         if (null == objectUnderInspection){
52             throw new IllegalArgumentException JavaDoc("argument must not be null");
53         }
54         this.objectUnderInspection = objectUnderInspection;
55     }
56
57     /**
58      * Get the Class Properties of the object under inspection.
59      * @return String array to be indexed by the CLASS_xxx_IDX constants
60      */

61     public String JavaDoc[] getClassProps() {
62         String JavaDoc[] result = new String JavaDoc[CLASS_OTHER_IDX+1];
63         result[CLASS_PACKAGE_IDX] = "package "+ getClassUnderInspection().getPackage().getName();
64         String JavaDoc modifiers = Modifier.toString(getClassUnderInspection().getModifiers());
65         String JavaDoc classOrInterface = "class";
66         if (getClassUnderInspection().isInterface()){
67             classOrInterface = "interface";
68         }
69         result[CLASS_CLASS_IDX] = modifiers + " "+ classOrInterface+" "+ shortName(getClassUnderInspection());
70         result[CLASS_INTERFACE_IDX] = "implements ";
71         Class JavaDoc[] interfaces = getClassUnderInspection().getInterfaces();
72         for (int i = 0; i < interfaces.length; i++) {
73             result[CLASS_INTERFACE_IDX] += shortName(interfaces[i])+ " ";
74         }
75         result[CLASS_SUPERCLASS_IDX] = "extends " + shortName(getClassUnderInspection().getSuperclass());
76         result[CLASS_OTHER_IDX] = "is Primitive: "+getClassUnderInspection().isPrimitive()
77                   +", is Array: " +getClassUnderInspection().isArray()
78                   +", is Groovy: " + isGroovy();
79         return result;
80     }
81
82     public boolean isGroovy() {
83         return getClassUnderInspection().isAssignableFrom(GroovyObject.class);
84     }
85
86     /**
87      * Get info about usual Java instance and class Methods as well as Constructors.
88      * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
89      */

90     public Object JavaDoc[] getMethods(){
91         Method[] methods = getClassUnderInspection().getMethods();
92         Constructor JavaDoc[] ctors = getClassUnderInspection().getConstructors();
93         Object JavaDoc[] result = new Object JavaDoc[methods.length + ctors.length];
94         int resultIndex = 0;
95         for (; resultIndex < methods.length; resultIndex++) {
96             Method method = methods[resultIndex];
97             result[resultIndex] = methodInfo(method);
98         }
99         for (int i = 0; i < ctors.length; i++, resultIndex++) {
100             Constructor JavaDoc ctor = ctors[i];
101             result[resultIndex] = methodInfo(ctor);
102         }
103         return result;
104     }
105      /**
106      * Get info about instance and class Methods that are dynamically added through Groovy.
107      * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
108      */

109     public Object JavaDoc[] getMetaMethods(){
110         MetaClass metaClass = InvokerHelper.getMetaClass(objectUnderInspection);
111         List metaMethods = metaClass.getMetaMethods();
112         Object JavaDoc[] result = new Object JavaDoc[metaMethods.size()];
113         int i=0;
114         for (Iterator iter = metaMethods.iterator(); iter.hasNext(); i++) {
115             MetaMethod metaMethod = (MetaMethod) iter.next();
116             result[i] = methodInfo(metaMethod);
117         }
118         return result;
119     }
120     /**
121      * Get info about usual Java public fields incl. constants.
122      * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
123      */

124     public Object JavaDoc[] getPublicFields(){
125         Field JavaDoc[] fields = getClassUnderInspection().getFields();
126         Object JavaDoc[] result = new Object JavaDoc[fields.length];
127         for (int i = 0; i < fields.length; i++) {
128             Field JavaDoc field = fields[i];
129             result[i] = fieldInfo(field);
130         }
131         return result;
132     }
133     /**
134      * Get info about Properties (Java and Groovy alike).
135      * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
136      */

137     public Object JavaDoc[] getProperties(){
138         List props = DefaultGroovyMethods.allProperties(objectUnderInspection);
139         Object JavaDoc[] result = new Object JavaDoc[props.size()];
140         int i=0;
141         for (Iterator iter = props.iterator(); iter.hasNext(); i++) {
142             PropertyValue pv = (PropertyValue) iter.next();
143             result[i] = fieldInfo(pv);
144         }
145         return result;
146     }
147
148     protected String JavaDoc[] fieldInfo(Field JavaDoc field) {
149         String JavaDoc[] result = new String JavaDoc[MEMBER_VALUE_IDX+1];
150         result[MEMBER_ORIGIN_IDX] = JAVA;
151         result[MEMBER_MODIFIER_IDX] = Modifier.toString(field.getModifiers());
152         result[MEMBER_DECLARER_IDX] = shortName(field.getDeclaringClass());
153         result[MEMBER_TYPE_IDX] = shortName(field.getType());
154         result[MEMBER_NAME_IDX] = field.getName();
155         try {
156             result[MEMBER_VALUE_IDX] = field.get(objectUnderInspection).toString();
157         } catch (IllegalAccessException JavaDoc e) {
158             result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
159         }
160         return withoutNulls(result);
161     }
162     protected String JavaDoc[] fieldInfo(PropertyValue pv) {
163         String JavaDoc[] result = new String JavaDoc[MEMBER_VALUE_IDX+1];
164         result[MEMBER_ORIGIN_IDX] = GROOVY;
165         result[MEMBER_MODIFIER_IDX] = "public";
166         result[MEMBER_DECLARER_IDX] = NOT_APPLICABLE;
167         result[MEMBER_TYPE_IDX] = shortName(pv.getType());
168         result[MEMBER_NAME_IDX] = pv.getName();
169         try {
170             result[MEMBER_VALUE_IDX] = pv.getValue().toString();
171         } catch (Exception JavaDoc e) {
172             result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
173         }
174         return withoutNulls(result);
175     }
176
177     protected Class JavaDoc getClassUnderInspection() {
178         return objectUnderInspection.getClass();
179     }
180
181     public static String JavaDoc shortName(Class JavaDoc clazz){
182         if (null == clazz) return NOT_APPLICABLE;
183         String JavaDoc className = clazz.getName();
184         if (null == clazz.getPackage()) return className;
185         String JavaDoc packageName = clazz.getPackage().getName();
186         int offset = packageName.length();
187         if (offset > 0) offset++;
188         className = className.substring(offset);
189         return className;
190     }
191
192     protected String JavaDoc[] methodInfo(Method method){
193         String JavaDoc[] result = new String JavaDoc[MEMBER_EXCEPTIONS_IDX+1];
194         int mod = method.getModifiers();
195         result[MEMBER_ORIGIN_IDX] = JAVA;
196         result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
197         result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass());
198         result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
199         result[MEMBER_NAME_IDX] = method.getName();
200         Class JavaDoc[] params = method.getParameterTypes();
201         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
202         for (int j = 0; j < params.length; j++) {
203             sb.append(shortName(params[j]));
204             if (j < (params.length - 1)) sb.append(", ");
205         }
206         result[MEMBER_PARAMS_IDX] = sb.toString();
207         sb.setLength(0);
208         Class JavaDoc[] exceptions = method.getExceptionTypes();
209         for (int k = 0; k < exceptions.length; k++) {
210             sb.append(shortName(exceptions[k]));
211             if (k < (exceptions.length - 1)) sb.append(", ");
212         }
213         result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
214         return withoutNulls(result);
215     }
216     protected String JavaDoc[] methodInfo(Constructor JavaDoc ctor){
217         String JavaDoc[] result = new String JavaDoc[MEMBER_EXCEPTIONS_IDX+1];
218         int mod = ctor.getModifiers();
219         result[MEMBER_ORIGIN_IDX] = JAVA;
220         result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
221         result[MEMBER_DECLARER_IDX] = shortName(ctor.getDeclaringClass());
222         result[MEMBER_TYPE_IDX] = shortName(ctor.getDeclaringClass());
223         result[MEMBER_NAME_IDX] = ctor.getName();
224         Class JavaDoc[] params = ctor.getParameterTypes();
225         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
226         for (int j = 0; j < params.length; j++) {
227             sb.append(shortName(params[j]));
228             if (j < (params.length - 1)) sb.append(", ");
229         }
230         result[MEMBER_PARAMS_IDX] = sb.toString();
231         sb.setLength(0);
232         Class JavaDoc[] exceptions = ctor.getExceptionTypes();
233         for (int k = 0; k < exceptions.length; k++) {
234             sb.append(shortName(exceptions[k]));
235             if (k < (exceptions.length - 1)) sb.append(", ");
236         }
237         result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
238         return withoutNulls(result);
239     }
240     protected String JavaDoc[] methodInfo(MetaMethod method){
241         String JavaDoc[] result = new String JavaDoc[MEMBER_EXCEPTIONS_IDX+1];
242         int mod = method.getModifiers();
243         result[MEMBER_ORIGIN_IDX] = GROOVY;
244         result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
245         result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass());
246         result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
247         result[MEMBER_NAME_IDX] = method.getName();
248         Class JavaDoc[] params = method.getParameterTypes();
249         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
250         for (int j = 0; j < params.length; j++) {
251             sb.append(shortName(params[j]));
252             if (j < (params.length - 1)) sb.append(", ");
253         }
254         result[MEMBER_PARAMS_IDX] = sb.toString();
255         result[MEMBER_EXCEPTIONS_IDX] = NOT_APPLICABLE; // no exception info for Groovy MetaMethods
256
return withoutNulls(result);
257     }
258
259     protected String JavaDoc[] withoutNulls(String JavaDoc[] toNormalize){
260         for (int i = 0; i < toNormalize.length; i++) {
261             String JavaDoc s = toNormalize[i];
262             if (null == s) toNormalize[i] = NOT_APPLICABLE;
263         }
264         return toNormalize;
265     }
266
267     public static void print(Object JavaDoc[] memberInfo) {
268         for (int i = 0; i < memberInfo.length; i++) {
269             String JavaDoc[] metaMethod = (String JavaDoc[]) memberInfo[i];
270             System.out.print(i+":\t");
271             for (int j = 0; j < metaMethod.length; j++) {
272                 String JavaDoc s = metaMethod[j];
273                 System.out.print(s+" ");
274             }
275             System.out.println("");
276         }
277     }
278     public static Object JavaDoc[] sort(Object JavaDoc[] memberInfo) {
279         Arrays.sort(memberInfo, new MemberComparator());
280         return memberInfo;
281     }
282
283     public static class MemberComparator implements Comparator {
284         public int compare(Object JavaDoc a, Object JavaDoc b) {
285             String JavaDoc[] aStr = (String JavaDoc[]) a;
286             String JavaDoc[] bStr = (String JavaDoc[]) b;
287             int result = aStr[Inspector.MEMBER_NAME_IDX].compareTo(bStr[Inspector.MEMBER_NAME_IDX]);
288             if (0 != result) return result;
289             result = aStr[Inspector.MEMBER_TYPE_IDX].compareTo(bStr[Inspector.MEMBER_TYPE_IDX]);
290             if (0 != result) return result;
291             result = aStr[Inspector.MEMBER_PARAMS_IDX].compareTo(bStr[Inspector.MEMBER_PARAMS_IDX]);
292             if (0 != result) return result;
293             result = aStr[Inspector.MEMBER_DECLARER_IDX].compareTo(bStr[Inspector.MEMBER_DECLARER_IDX]);
294             if (0 != result) return result;
295             result = aStr[Inspector.MEMBER_MODIFIER_IDX].compareTo(bStr[Inspector.MEMBER_MODIFIER_IDX]);
296             if (0 != result) return result;
297             result = aStr[Inspector.MEMBER_ORIGIN_IDX].compareTo(bStr[Inspector.MEMBER_ORIGIN_IDX]);
298             return result;
299         }
300     }
301 }
302
Popular Tags