KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > yan > xml > nut > NutIntrospector


1 package jfun.yan.xml.nut;
2
3
4 import java.beans.BeanInfo JavaDoc;
5 import java.beans.IndexedPropertyDescriptor JavaDoc;
6 import java.beans.IntrospectionException JavaDoc;
7 import java.beans.Introspector JavaDoc;
8 import java.beans.PropertyDescriptor JavaDoc;
9 import java.lang.reflect.InvocationTargetException JavaDoc;
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.Locale JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import jfun.yan.Binder;
17 import jfun.yan.Component;
18 import jfun.yan.xml.ConfigurationException;
19
20
21
22
23 /**
24  * Utility class to run introspection on a {@link Nut} class
25  * to get NutDescriptor.
26  * <p>
27  * @author Ben Yu
28  * Nov 9, 2005 11:34:52 PM
29  */

30 public class NutIntrospector implements java.io.Serializable JavaDoc {
31   private final HashMap JavaDoc cache = new HashMap JavaDoc();
32   /**
33    * Get a NutDescriptor for a Nut class.
34    * @param type the class.
35    * @return the NutDescriptor object.
36    * @throws IntrospectionException when introspection fails.
37    */

38   public NutDescriptor getNutDescriptor(final Class JavaDoc type)
39   throws IntrospectionException JavaDoc{
40     NutDescriptor desc = (NutDescriptor)cache.get(type);
41     if(desc == null){
42       if(!Nut.class.isAssignableFrom(type)){
43         throw new IllegalArgumentException JavaDoc("only Nut class is introspectable.");
44       }
45       /*
46       try{
47         type.getConstructor(null);
48       }
49       catch(NoSuchMethodException e){
50         throw new IllegalArgumentException("default constructor not present in class "+type);
51       }*/

52       desc = new NutDescriptor(type);
53       cache.put(type, desc);
54       final Evaluator evaluator = getEvaluator(type);
55       desc.setEvaluator(evaluator);
56       desc.setPropertyDescriptors(getProperties(type));
57       populateSub(type, desc);
58     }
59     return desc;
60   }
61   private Evaluator getEvaluator(final Class JavaDoc type){
62     if(ComponentNut.class.isAssignableFrom(type)){
63       return new Evaluator(){
64         public Object JavaDoc eval(Object JavaDoc obj)
65         throws Exception JavaDoc{
66           final ComponentNut nut = (ComponentNut)obj;
67           return nut.eval();
68         }
69         public Class JavaDoc getType(){
70           return Component.class;
71         }
72       };
73     }
74     else if(BinderNut.class.isAssignableFrom(type)){
75       return new Evaluator(){
76         public Object JavaDoc eval(Object JavaDoc obj) {
77           final BinderNut nut = (BinderNut)obj;
78           try{
79             return nut.eval();
80           }
81           catch(Exception JavaDoc e){
82             throw new ConfigurationException(e, nut.getTagLocation());
83           }
84         }
85         public Class JavaDoc getType(){
86           return Binder.class;
87         }
88       };
89     }
90     else{
91       try{
92         final Method JavaDoc mtd = type.getMethod("eval", null);
93         final Class JavaDoc rtype = mtd.getReturnType();
94         return new Evaluator(){
95           public Object JavaDoc eval(Object JavaDoc obj){
96             final Nut nut = (Nut)obj;
97             try{
98               final Object JavaDoc r = mtd.invoke(nut, null);
99               if(void.class.equals(rtype)){
100                 return nut;
101               }
102               else return r;
103             }
104             catch(InvocationTargetException JavaDoc e){
105               throw new ConfigurationException(e.getTargetException(), nut.getTagLocation());
106             }
107             catch(Exception JavaDoc e){
108               throw new ConfigurationException(e, nut.getTagLocation());
109             }
110           }
111           public Class JavaDoc getType(){
112             return (void.class.equals(rtype)?type:rtype);
113           }
114         };
115       }
116       catch(NoSuchMethodException JavaDoc e){
117         return new Evaluator(){
118           public Object JavaDoc eval(Object JavaDoc nut){
119             return nut;
120           }
121           public Class JavaDoc getType(){
122             return type;
123           }
124         };
125       }
126     }
127   }
128   
129   private Map JavaDoc getProperties(Class JavaDoc type)
130   throws IntrospectionException JavaDoc{
131     final BeanInfo JavaDoc info = Introspector.getBeanInfo(type);
132     final PropertyDescriptor JavaDoc[] pdescs = info.getPropertyDescriptors();
133     final HashMap JavaDoc ret = new HashMap JavaDoc();
134     for(int i=0; i<pdescs.length; i++){
135       final PropertyDescriptor JavaDoc desc = pdescs[i];
136       if(desc.getWriteMethod()!=null && !(desc instanceof IndexedPropertyDescriptor JavaDoc)){
137         ret.put(desc.getName(), desc);
138       }
139     }
140     return ret;
141   }
142   //gets the only "set" method with one array parameter.
143
//if more than one is found, use the most restrictive one.
144
private final void populateSub(Class JavaDoc type, NutDescriptor desc)
145   throws IntrospectionException JavaDoc{
146     final HashMap JavaDoc subs= new HashMap JavaDoc();
147     final Method JavaDoc[] mtds = type.getMethods();
148     final ArrayList JavaDoc anonymous_adders = new ArrayList JavaDoc();
149     Class JavaDoc etype = null;
150     Method JavaDoc r = null;
151     for(int i=0; i<mtds.length; i++){
152       final Method JavaDoc mtd = mtds[i];
153       final String JavaDoc mname = mtd.getName();
154       if(mname.equals("set")){
155         final Class JavaDoc[] ptypes = mtd.getParameterTypes();
156         if(ptypes.length != 1){
157           continue;
158         }
159         final Class JavaDoc ptype = ptypes[0];
160         if(!ptype.isArray()){
161           continue;
162         }
163         final Class JavaDoc etype2 = ptype.getComponentType();
164         if(etype != null){
165           if(etype.isAssignableFrom(etype2)){
166             //we find a more restrictive version
167
etype = etype2;
168             r = mtd;
169           }
170         }
171         else{
172           r = mtd;
173           etype = etype2;
174         }
175       }
176       else if(mname.startsWith(ADDER)){
177         final Class JavaDoc[] ptypes = mtd.getParameterTypes();
178         if(ptypes.length!=1){
179           continue;
180         }
181         Class JavaDoc ptype = ptypes[0];
182         final String JavaDoc elem_name = mname.substring(3).toLowerCase(Locale.US);
183         if(subs.containsKey(elem_name)){
184           throw new IllegalArgumentException JavaDoc("duplicate adder: "+mname);
185         }
186         if(elem_name.length()==0){
187           /*
188           if(!ptype.isAssignableFrom(String.class)){
189             //add() with non-string parameter.
190             continue;
191           }*/

192           anonymous_adders.add(new Method1(mtd, ptype));
193         }
194         else{
195           if(!Nut.class.isAssignableFrom(ptype))
196             continue;
197           desc.putAdder(elem_name, mtd);
198           if(elem_name.length()>0){
199             subs.put(elem_name, getNutDescriptor(ptype));
200           }
201         }
202       }
203     }
204     if(r!=null){
205       desc.setCollectionDescriptor(
206           new NutDescriptor.CollectionDescriptor(etype, r)
207       );
208     }
209     else{
210       desc.setRegularDescriptor(
211           new NutDescriptor.RegularDescriptor(subs)
212       );
213     }
214     final Method1[] anonymous = new Method1[anonymous_adders.size()];
215     anonymous_adders.toArray(anonymous);
216     desc.setAdderSuite(new MethodSuite(ADDER, anonymous));
217   }
218   private static final String JavaDoc ADDER = "add";
219 }
220
Popular Tags