KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > oddjob > designer > arooa > DesignIH


1 package org.oddjob.designer.arooa;
2
3 import java.lang.reflect.Method JavaDoc;
4 import java.util.ArrayList JavaDoc;
5 import java.util.Hashtable JavaDoc;
6 import java.util.Iterator JavaDoc;
7 import java.util.LinkedHashMap JavaDoc;
8 import java.util.List JavaDoc;
9 import java.util.Map JavaDoc;
10
11 import org.oddjob.arooa.reflect.IntrospectionHelper;
12 import org.oddjob.designer.model.DesignAttribute;
13 import org.oddjob.designer.model.DesignElement;
14 import org.xml.sax.Attributes JavaDoc;
15 import org.xml.sax.helpers.AttributesImpl JavaDoc;
16
17 /**
18  * An introspection helper for parsing the design object tree. The following
19  * methods are recognized:
20  * <ul>
21  * <li><code>String text()</code> for an object to provide text data.</li>
22  * <li><code>String unknown()</code> for an object to provide it's
23  * definition as raw XML.</li>
24  * <li><code>void unknown(String xml)</code> to set an objects definition
25  * as raw XML.</li>
26  * <li><code>Object getXYZ()</code> to return properties which depending
27  * on their type will either be anattribute XYZ or an element XYZ.</li>
28  * <li><code>Object elementXYZ()</code> to return an object which will generate
29  * an element of name XYZ.</li>
30  * <li><code>ElementWrapper[] elements()</code> To provide all the elements in one
31  * go. This overrides the other methods of getting elements.</li>
32  * </ul>
33  *
34  */

35 public final class DesignIH {
36
37     private final List JavaDoc getterMethods = new ArrayList JavaDoc();
38     private final Map JavaDoc attributeTypes = new LinkedHashMap JavaDoc();
39     private Method JavaDoc elementsMethod;
40     private final Map JavaDoc elementsMethods = new LinkedHashMap JavaDoc();
41     private final Map JavaDoc elementMethods = new LinkedHashMap JavaDoc();
42     private Method JavaDoc textMethod = null;
43     private Method JavaDoc unknownInMethod = null;
44     private Method JavaDoc unknownOutMethod = null;
45
46     /**
47      * The class introspected by this instance.
48      */

49     private Class JavaDoc bean;
50
51     /**
52      * Helper instances we've already created (Class to IntrospectionHelper).
53      */

54     private static Hashtable JavaDoc helpers = new Hashtable JavaDoc();
55
56     private DesignIH(final Class JavaDoc bean) {
57         this.bean = bean;
58         
59         Method JavaDoc[] methods = bean.getMethods();
60         for (int i = 0; i < methods.length; i++) {
61             final Method JavaDoc m = methods[i];
62             String JavaDoc name = m.getName();
63             Class JavaDoc returnType = m.getReturnType();
64             Class JavaDoc[] args = m.getParameterTypes();
65             
66             if ("text".equals(name)
67                     && String JavaDoc.class.equals(returnType)
68                     && args.length == 0) {
69                 textMethod = m;
70             }
71             else if ("unknown".equals(name)
72                     && String JavaDoc.class.equals(returnType)
73                     && args.length == 0) {
74                 unknownOutMethod = m;
75             }
76             else if ("unknown".equals(name)
77                     && java.lang.Void.TYPE.equals(returnType)
78                     && args.length == 1
79                     && String JavaDoc.class.equals(args[0])) {
80                 unknownInMethod = m;
81             }
82             else if (name.startsWith("get")
83                     && args.length == 0) {
84                 String JavaDoc rest = getPropertyName(name, "get");
85                 if ("class".equals(rest)) {
86                     continue;
87                 }
88                 attributeTypes.put(rest, returnType);
89                 getterMethods.add(m);
90             }
91             else if (name.startsWith("elements")
92                     && returnType.isArray()
93                     && args.length == 0) {
94                 String JavaDoc rest = getPropertyName(name, "elements");
95                 if (rest.length() > 0) {
96                     elementsMethods.put(rest, m);
97                 }
98                 else {
99                     elementsMethod = m;
100                 }
101             }
102             else if (name.startsWith("element")
103                     && !java.lang.Void.TYPE.equals(returnType)
104                     && args.length == 0) {
105                 String JavaDoc rest = getPropertyName(name, "element");
106                 if (rest.length() > 0) {
107                     elementMethods.put(rest, m);
108                 }
109             }
110         } // for methods
111
}
112
113         
114     /**
115      * Returns a helper for the given class, either from the cache or by
116      * creating a new instance.
117      *
118      * @param c
119      * The class for which a helper is required. Must not be
120      * <code>null</code>.
121      *
122      * @return a helper for the specified class
123      */

124     public static synchronized DesignIH getHelper(Class JavaDoc c) {
125         DesignIH ih = (DesignIH) helpers.get(c);
126         if (ih == null) {
127             ih = new DesignIH(c);
128             helpers.put(c, ih);
129         }
130         return ih;
131     }
132
133     /**
134      * Return the attributes for an objec.
135      *
136      */

137     public Attributes JavaDoc attributes(Object JavaDoc object) {
138         AttributesImpl JavaDoc atts = new AttributesImpl JavaDoc();
139         for (Iterator JavaDoc it = getterMethods.iterator(); it.hasNext(); ) {
140             Method JavaDoc m = (Method JavaDoc) it.next();
141             String JavaDoc propName = getPropertyName(m.getName(), "get");
142             Class JavaDoc type = (Class JavaDoc) attributeTypes.get(propName);
143             Object JavaDoc value = null;
144             try {
145                 value = m.invoke(object, new Object JavaDoc[0]);
146             }
147             catch (Exception JavaDoc e) {
148                 e.printStackTrace();
149             }
150             if (value != null) {
151                 if (DesignAttribute.class.isAssignableFrom(type)) {
152                     if (((DesignAttribute)value).attribute() != null) {
153                         atts.addAttribute("", propName, propName, null, ((DesignAttribute)value).attribute());
154                     }
155                 }
156                 else {
157                     if (value.toString().length() > 0) {
158                         atts.addAttribute("", propName, propName, null, value.toString());
159                     }
160                 }
161             }
162         }
163         return atts;
164     }
165
166     /**
167      * Get the text associated with a object.
168      */

169     public String JavaDoc text(Object JavaDoc object) {
170         if (textMethod == null) {
171             return null;
172         }
173         try {
174             return (String JavaDoc) textMethod.invoke(object, new Object JavaDoc[0]);
175         }
176         catch (Exception JavaDoc e) {
177             e.printStackTrace();
178         }
179         return null;
180     }
181
182     /**
183      */

184     public String JavaDoc unknown(Object JavaDoc object) {
185         if (unknownOutMethod == null) {
186             return null;
187         }
188         try {
189             return (String JavaDoc) unknownOutMethod.invoke(object, new Object JavaDoc[0]);
190         }
191         catch (Exception JavaDoc e) {
192             e.printStackTrace();
193         }
194         return null;
195     }
196     
197     /**
198      */

199     public void unknown(Object JavaDoc object, String JavaDoc text) {
200         if (unknownInMethod == null) {
201             throw new NullPointerException JavaDoc("No unkown");
202         }
203         try {
204             unknownInMethod.invoke(object, new Object JavaDoc[] { text });
205         }
206         catch (Exception JavaDoc e) {
207             e.printStackTrace();
208         }
209     }
210       
211     protected ElementWrapper elementWrapperFor(String JavaDoc name, Object JavaDoc object) {
212         if (object == null) {
213             return null;
214         }
215         if (object instanceof DesignElement) {
216             DesignIH elementDIH = DesignIH.getHelper(object.getClass());
217             if (!elementDIH.hasDetailData((DesignElement) object)) {
218                 return null;
219             }
220         }
221         return new ElementWrapper(name, object);
222     }
223     
224     public ElementWrapper[] elements(Object JavaDoc object) {
225         try {
226             if (elementsMethod == null) {
227                 List JavaDoc ews = new ArrayList JavaDoc();
228                 for (Iterator JavaDoc it = elementMethods.entrySet().iterator(); it.hasNext(); ) {
229                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
230                     Object JavaDoc obj = (Object JavaDoc) ((Method JavaDoc) entry.getValue()).invoke(object, new Object JavaDoc[0]);
231                     ElementWrapper wrapper = elementWrapperFor((String JavaDoc)entry.getKey(), obj);
232                     if (wrapper != null) {
233                         ews.add(new ElementWrapper((String JavaDoc)entry.getKey(), obj));
234                     }
235                 }
236                 for (Iterator JavaDoc it = elementsMethods.entrySet().iterator(); it.hasNext(); ) {
237                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
238                     Object JavaDoc[] objs = (Object JavaDoc[]) ((Method JavaDoc) entry.getValue()).invoke(object, new Object JavaDoc[0]);
239                     if (objs != null) {
240                         for (int i = 0; i < objs.length; ++i) {
241                             ElementWrapper wrapper = elementWrapperFor((String JavaDoc) entry.getKey(), objs[i]);
242                             if (wrapper != null) {
243                                 ews.add(new ElementWrapper((String JavaDoc) entry.getKey(), objs[i]));
244                             }
245                         }
246                     }
247                 }
248                 for (Iterator JavaDoc it = getterMethods.iterator(); it.hasNext(); ) {
249                     Method JavaDoc m = (Method JavaDoc) it.next();
250                     String JavaDoc propName = getPropertyName(m.getName(), "get");
251                     Class JavaDoc type = (Class JavaDoc) attributeTypes.get(propName);
252                     if (DesignElement.class.isAssignableFrom(type)) {
253                         DesignElement value = null;
254                         try {
255                             value = (DesignElement) m.invoke(object, new Object JavaDoc[0]);
256                         }
257                         catch (Exception JavaDoc e) {
258                             e.printStackTrace();
259                         }
260                         if (value == null) {
261                             continue;
262                         }
263                         ElementWrapper wrapper = elementWrapperFor(propName, value);
264                         if (wrapper != null) {
265                             ews.add(wrapper);
266                         }
267                     }
268                 }
269                 return (ElementWrapper[]) ews.toArray(new ElementWrapper[0]);
270             } else {
271                 return (ElementWrapper[]) elementsMethod.invoke(object, new Object JavaDoc[0]);
272             }
273         }
274         catch (Exception JavaDoc e) {
275             e.printStackTrace();
276         }
277         return null;
278     }
279
280     /**
281      * Does the element have nested data. An element has any nested elements.
282      *
283      * @param object The element.
284      * @return true if it does.
285      */

286     public boolean hasDetailData(DesignElement object) {
287         // if this element is an attribute it can't have
288
// nested data!
289
if (object instanceof DesignAttribute
290                 && ((DesignAttribute) object).attribute() != null) {
291             return false;
292         }
293         ElementWrapper[] elements = elements(object);
294         if (elements.length > 0) {
295             return true;
296         }
297         Attributes JavaDoc attributes = attributes(object);
298         if (attributes.getLength() > 0) {
299             return true;
300         }
301         if (text(object) != null) {
302             return true;
303         }
304         return false;
305     }
306     
307     /**
308      * Extracts the name of a property from a method name by subtracting
309      * a given prefix and converting into lower case. It is up to calling
310      * code to make sure the method name does actually begin with the
311      * specified prefix - no checking is done in this method.
312      *
313      * @param methodName The name of the method in question.
314      * Must not be <code>null</code>.
315      * @param prefix The prefix to remove.
316      * Must not be <code>null</code>.
317      *
318      * @return the lower-cased method name with the prefix removed.
319      */

320     private String JavaDoc getPropertyName(String JavaDoc methodName, String JavaDoc prefix) {
321         return IntrospectionHelper.getPropertyName(methodName, prefix);
322     }
323
324 }
325
Popular Tags