KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > beans > info > plugins > AbstractBeanInfoFactory


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.beans.info.plugins;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.WeakHashMap JavaDoc;
32
33 import org.jboss.beans.info.spi.BeanInfo;
34 import org.jboss.beans.info.spi.BeanInfoFactory;
35 import org.jboss.beans.info.spi.EventInfo;
36 import org.jboss.beans.info.spi.PropertyInfo;
37 import org.jboss.classadapter.spi.ClassAdapter;
38 import org.jboss.reflect.spi.ClassInfo;
39 import org.jboss.reflect.spi.ConstructorInfo;
40 import org.jboss.reflect.spi.MethodInfo;
41 import org.jboss.reflect.spi.PrimitiveInfo;
42 import org.jboss.reflect.spi.TypeInfo;
43 import org.jboss.util.JBossStringBuilder;
44 import org.jboss.util.collection.WeakValueHashMap;
45
46 /**
47  * A bean info factory.
48  *
49  * @author <a HREF="adrian@jboss.com">Adrian Brock</a>
50  * @version $Revision: 57133 $
51  */

52 public class AbstractBeanInfoFactory implements BeanInfoFactory
53 {
54    /** The cache */
55    protected Map JavaDoc<ClassLoader JavaDoc, Map JavaDoc<String JavaDoc, BeanInfo>> cache = new WeakHashMap JavaDoc<ClassLoader JavaDoc, Map JavaDoc<String JavaDoc, BeanInfo>>();
56    
57    protected static boolean isGetter(MethodInfo minfo)
58    {
59       String JavaDoc name = minfo.getName();
60       TypeInfo returnType = minfo.getReturnType();
61       TypeInfo[] parameters = minfo.getParameterTypes();
62       if ((name.length() > 3 && name.startsWith("get")) || (name.length() > 2 && name.startsWith("is")))
63       {
64          if (parameters.length == 0 && PrimitiveInfo.VOID.equals(returnType) == false)
65             return true;
66       }
67       return false;
68    }
69    
70    protected static boolean isSetter(MethodInfo minfo)
71    {
72       String JavaDoc name = minfo.getName();
73       TypeInfo returnType = minfo.getReturnType();
74       TypeInfo[] parameters = minfo.getParameterTypes();
75       if ((name.length() > 3 && name.startsWith("set")))
76       {
77          if (parameters.length == 1 && PrimitiveInfo.VOID.equals(returnType))
78             return true;
79       }
80       return false;
81    }
82    
83    protected static String JavaDoc getUpperPropertyName(String JavaDoc name)
84    {
85       int start = 3;
86       if (name.startsWith("is"))
87          start = 2;
88       
89       return name.substring(start);
90    }
91    
92    protected static String JavaDoc getLowerPropertyName(String JavaDoc name)
93    {
94       // If the second character is upper case then we don't make
95
// the first character lower case
96
if (name.length() > 1)
97       {
98          if (Character.isUpperCase(name.charAt(1)))
99             return name;
100       }
101
102       JBossStringBuilder buffer = new JBossStringBuilder(name.length());
103       buffer.append(Character.toLowerCase(name.charAt(0)));
104       if (name.length() > 1)
105          buffer.append(name.substring(1));
106       return buffer.toString();
107    }
108
109    /**
110     * Create a new bean info factory
111     */

112    public AbstractBeanInfoFactory()
113    {
114    }
115
116    public BeanInfo getBeanInfo(ClassAdapter classAdapter)
117    {
118       synchronized (cache)
119       {
120          ClassLoader JavaDoc cl = classAdapter.getClassLoader();
121          ClassInfo classInfo = classAdapter.getClassInfo();
122          String JavaDoc className = classInfo.getName();
123          Map JavaDoc<String JavaDoc, BeanInfo> map = cache.get(cl);
124          if (map != null)
125          {
126             BeanInfo info = map.get(className);
127             if (info != null)
128                return info;
129          }
130
131          if (classInfo.isInterface())
132             throw new IllegalArgumentException JavaDoc(classInfo.getName() + " is an interface");
133
134          Set JavaDoc<ConstructorInfo> constructors = getConstructors(classInfo);
135          Set JavaDoc<MethodInfo> methods = getMethods(classInfo);
136          Set JavaDoc<PropertyInfo> properties = getProperties(methods);
137          Set JavaDoc<EventInfo> events = getEvents(classInfo);
138          
139          BeanInfo result = createBeanInfo(classAdapter, properties, constructors, methods, events);
140          if (map == null)
141          {
142             map = new WeakValueHashMap();
143             cache.put(cl, map);
144          }
145          map.put(className, result);
146          return result;
147       }
148    }
149    
150    /**
151     * Create the bean info
152     *
153     * @param classAdapter the class adapter
154     * @param properties the properties
155     * @param constructors the constructors
156     * @param methods the methods
157     * @param events the events
158     * @return the bean info
159     */

160    protected BeanInfo createBeanInfo(ClassAdapter classAdapter, Set JavaDoc<PropertyInfo> properties, Set JavaDoc<ConstructorInfo> constructors, Set JavaDoc<MethodInfo> methods, Set JavaDoc<EventInfo> events)
161    {
162       return new AbstractBeanInfo(this, classAdapter, properties, constructors, methods, events);
163    }
164    
165    /**
166     * Get the constructors
167     *
168     * @param classInfo the class info
169     * @return the constructors
170     */

171    protected Set JavaDoc<ConstructorInfo> getConstructors(ClassInfo classInfo)
172    {
173       ConstructorInfo[] cinfos = classInfo.getDeclaredConstructors();
174       if (cinfos == null || cinfos.length == 0)
175          return null;
176
177       HashSet JavaDoc<ConstructorInfo> result = new HashSet JavaDoc<ConstructorInfo>();
178       for (int i = 0; i < cinfos.length; ++i)
179          result.add(cinfos[i]);
180       return result;
181    }
182    
183    /**
184     * Get the methods
185     *
186     * @param classInfo the class info
187     * @return the methods
188     */

189    protected Set JavaDoc<MethodInfo> getMethods(ClassInfo classInfo)
190    {
191       HashSet JavaDoc<MethodInfo> result = new HashSet JavaDoc<MethodInfo>();
192       while (classInfo != null)
193       {
194          MethodInfo[] minfos = classInfo.getDeclaredMethods();
195          if (minfos != null && minfos.length > 0)
196          {
197             for (int i = 0; i < minfos.length; ++i)
198             {
199                if (result.contains(minfos[i]) == false)
200                   result.add(minfos[i]);
201             }
202          }
203          
204          classInfo = classInfo.getSuperclass();
205       }
206       return result;
207    }
208    
209    /**
210     * Get the properties
211     *
212     * @param methods the methods
213     * @return the properties
214     */

215    protected Set JavaDoc<PropertyInfo> getProperties(Set JavaDoc methods)
216    {
217       HashMap JavaDoc<String JavaDoc, MethodInfo> getters = new HashMap JavaDoc<String JavaDoc, MethodInfo>();
218       HashMap JavaDoc<String JavaDoc, List JavaDoc<MethodInfo>> setters = new HashMap JavaDoc<String JavaDoc, List JavaDoc<MethodInfo>>();
219       if (methods.isEmpty() == false)
220       {
221          for (Iterator JavaDoc i = methods.iterator(); i.hasNext();)
222          {
223             MethodInfo methodInfo = (MethodInfo) i.next();
224             if (methodInfo.isPublic() && methodInfo.isStatic() == false)
225             {
226                String JavaDoc name = methodInfo.getName();
227                String JavaDoc upperName = getUpperPropertyName(name);
228                if (isGetter(methodInfo))
229                {
230                   getters.put(upperName, methodInfo);
231                }
232                else if (isSetter(methodInfo))
233                {
234                   ArrayList JavaDoc<MethodInfo> list = (ArrayList JavaDoc<MethodInfo>) setters.get(upperName);
235                   if (list == null)
236                   {
237                      list = new ArrayList JavaDoc<MethodInfo>();
238                      setters.put(upperName, list);
239                   }
240                   list.add(methodInfo);
241                }
242             }
243          }
244       }
245
246       HashSet JavaDoc<PropertyInfo> properties = new HashSet JavaDoc<PropertyInfo>();
247       if (getters.isEmpty() == false)
248       {
249          for (Iterator JavaDoc i = getters.entrySet().iterator(); i.hasNext();)
250          {
251             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
252             String JavaDoc name = (String JavaDoc) entry.getKey();
253             MethodInfo getter = (MethodInfo) entry.getValue();
254             MethodInfo setter = null;
255             ArrayList JavaDoc setterList = (ArrayList JavaDoc) setters.remove(name);
256             if (setterList != null && setterList.size() != 0)
257             {
258                for (int j = 0; j < setterList.size(); ++j)
259                {
260                   MethodInfo thisSetter = (MethodInfo) setterList.get(j);
261                   TypeInfo pinfo = thisSetter.getParameterTypes()[0];
262                   if (getter.getReturnType().equals(pinfo) == true)
263                   {
264                      setter = thisSetter;
265                      break;
266                   }
267                }
268             }
269             String JavaDoc lowerName = getLowerPropertyName(name);
270             properties.add(new AbstractPropertyInfo(lowerName, name, getter.getReturnType(), getter, setter));
271          }
272       }
273       if (setters.isEmpty() == false)
274       {
275          for (Iterator JavaDoc i = setters.entrySet().iterator(); i.hasNext();)
276          {
277             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
278             String JavaDoc name = (String JavaDoc) entry.getKey();
279             ArrayList JavaDoc setterList = (ArrayList JavaDoc) entry.getValue();
280             // Review: Maybe should just create duplicate propertyInfo and let the configurator guess?
281
if (setterList.size() == 1)
282             {
283                MethodInfo setter = (MethodInfo) setterList.get(0);
284                TypeInfo pinfo = setter.getParameterTypes()[0];
285                String JavaDoc lowerName = getLowerPropertyName(name);
286                properties.add(new AbstractPropertyInfo(lowerName, name, pinfo, null, setter));
287             }
288          }
289       }
290       return properties;
291    }
292    
293    /**
294     * Get the events
295     *
296     * @param classInfo the class info
297     * @return the events
298     */

299    protected Set JavaDoc<EventInfo> getEvents(ClassInfo classInfo)
300    {
301       return null;
302    }
303 }
304
Popular Tags