KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > yan > etc > Beans


1 /*****************************************************************************
2  * Copyright (C) Codehaus.org. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  *****************************************************************************/

8
9 /*
10  * Created on Apr 7, 2005
11  *
12  * Author Michelle Lei
13  * ZBS
14  */

15 package jfun.yan.etc;
16
17 import java.beans.IntrospectionException JavaDoc;
18 import java.beans.Introspector JavaDoc;
19 import java.beans.PropertyDescriptor JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import jfun.yan.Component;
22 import jfun.yan.Components;
23 import jfun.yan.Creator;
24 import jfun.yan.PropertyBinder;
25
26 /**
27  * Helper functions for bean component including customizations
28  * of bean property resolution strategy.
29  * The default strategy is byType.
30  * byName, byDisplayName and byQualifiedName are provided in this class directly.
31  * More flexible policies can be implemented by
32  * using the {@link Beans#resolveBy(jfun.yan.Component, FromProperty)} method.
33  * <p>
34  * Codehaus.org.
35  *
36  * @author Michelle Lei
37  *
38  */

39 public class Beans {
40   private static PropertyDescriptor JavaDoc[] getBeanProperties(Class JavaDoc c){
41     try{
42       return Introspector.getBeanInfo(c).getPropertyDescriptors();
43     }
44     catch(IntrospectionException JavaDoc e){
45       throw new IllegalArgumentException JavaDoc(e.getMessage());
46     }
47   }
48   /**
49    * Customize the resolution mechanism for java bean properties
50    * using the result from a FromProperty object.
51    *
52    * @param cc the component.
53    * @param type the type of the java bean.
54    * @param pn the FromProperty object.
55    * @return the new Component.
56    */

57   public static Component resolveBy(final Component cc, final Class JavaDoc type,
58       final FromProperty pn){
59     final PropertyDescriptor JavaDoc[] props = getBeanProperties(type);
60     //Component r = cc;
61
final java.util.HashMap JavaDoc hmap = new java.util.HashMap JavaDoc();
62     for(int i=0; i<props.length; i++){
63       final PropertyDescriptor JavaDoc prop = props[i];
64       if(prop.getWriteMethod() == null) continue;
65       final String JavaDoc name = prop.getName();
66       hmap.put(name, Components.useKey(pn.fromProperty(type, prop)));
67       //r = r.withProperty(name, Components.useKey(pn.fromProperty(type, prop)))
68

69         //;
70
}
71     return cc.withProperties(hmap);
72     //return r;
73
}
74   /**
75    * Customize the resolution mechanism for java bean properties
76    * using the result from a FromProperty object.
77    *
78    * @param cc the component.
79    * @param pn the FromProperty object.
80    * @return the new Component.
81    */

82   public static Component resolveBy(final Component cc, final FromProperty pn){
83     final Class JavaDoc type = cc.getType();
84     if(type==null || !cc.isConcrete()){
85       return cc.bind(new jfun.yan.Binder(){
86         public Creator bind(Object JavaDoc obj)
87         throws Exception JavaDoc{
88           if(obj==null) return Components.value(null);
89           else return resolveBy(Components.value(obj), obj.getClass(), pn);
90         }
91       });
92     }
93     else{
94       return resolveBy(cc, type, pn);
95     }
96   }
97   /**
98    * resolve java bean properties by name instead of the default "byType"
99    * policy.
100    *
101    * @param cc the component.
102    * @return the new Component.
103    */

104   public static Component byName(final Component cc){
105     /*return resolveBy(cc, new FromProperty(){
106       public Object fromProperty(Class c, PropertyDescriptor prop){
107         return prop.getName();
108       }
109     });*/

110     //we use withProperties because it is easier.
111
//and we get more testing coverage.
112
return cc.bindProperties(new jfun.yan.PropertyBinder(){
113       public Creator bind(Class JavaDoc component_type, Object JavaDoc key, Class JavaDoc type){
114         return Components.useKey(key);
115       }
116     });
117   }
118   /**
119    * resolve java bean properties by type.
120    *
121    * @param cc the component.
122    * @return the new Component.
123    */

124   public static Component byType(final Component cc){
125     return cc.bindProperties(new jfun.yan.PropertyBinder(){
126       public Creator bind(Class JavaDoc component_type, Object JavaDoc key, Class JavaDoc type){
127         return Components.useType(type);
128       }
129     });
130   }
131   /**
132    * resolve java bean properties by display name instead of the default "byType"
133    * policy.
134    *
135    * @param cc the component.
136    * @return the new Component.
137    */

138   public static Component byDisplayName(final Component cc){
139     return resolveBy(cc, new FromProperty(){
140       public Object JavaDoc fromProperty(Class JavaDoc c, PropertyDescriptor JavaDoc prop){
141         return prop.getDisplayName();
142       }
143     });
144   }
145   /**
146    * resolve java bean properties by fully qualified name
147    * (class_name.property_name) instead of the default "byType"
148    * policy.
149    *
150    * @param cc the component.
151    * @return the new Component.
152    */

153   public static Component byQualifiedName(final Component cc){
154     return resolveBy(cc, new FromProperty(){
155       public Object JavaDoc fromProperty(Class JavaDoc c, PropertyDescriptor JavaDoc prop){
156         return jfun.util.Misc.getTypeName(c)+'.'+prop.getName();
157       }
158     });
159   }
160   
161   /**
162    * Create a Component that makes the parameters mandatory properties
163    * and all java bean setters optional.
164    * <br>
165    * For a class whose constructor has two parameters,
166    * the two parameters will be made two mandatory properties under the provided
167    * property names; all the java bean setters will be made optional properties.
168    * <br>
169    * This way, mandatory properties can be expressed as parameters and optional
170    * properties can be represented as bean properties.
171    * Yet, configuration consistently uses named properties, avoiding confusion
172    * caused by position based parameters.
173    * @param cc the component that expects some mandatory parameters
174    * (such as a constructor or a static factory method)
175    * @param mandatory_params the property names to name the parameters.
176    * @return the new Component object that expects mandatory properties for the
177    * parameters and optioinal properties for the java bean properties.
178    * @throws IntrospectionException
179    * When Java Bean Introspection fails.
180    */

181   public static Component beanComponent(final Component cc,
182       final String JavaDoc[] mandatory_params)
183   throws IntrospectionException JavaDoc{
184     if(mandatory_params==null || mandatory_params.length==0)
185       return cc.bean().optionalProperties();
186     final HashMap JavaDoc params = new HashMap JavaDoc();
187     for(int i=0;i<mandatory_params.length;i++){
188       final String JavaDoc name = mandatory_params[i];
189       params.put(name, name);
190     }
191     return cc.fromProperties(mandatory_params).bean()
192       .bindProperties(new PropertyBinder(){
193         public Creator bind(Class JavaDoc component_type, Object JavaDoc key, Class JavaDoc type){
194           final Component p = Components.useProperty(component_type, key, type);
195           if(params.containsKey(key)){
196             return p;
197           }
198           else return p.optional();
199         }
200       });
201   }
202   
203
204 }
205
Popular Tags