View Javadoc

1    /****************************************************************************
2    * Copyright (c) 2005, 2006, 2007, 2008, 2009 Imola Informatica.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the LGPL License v2.1
5    * which accompanies this distribution, and is available at
6    * http://www.gnu.org/licenses/lgpl.html
7    ****************************************************************************/
8   package it.imolinfo.jbi4corba.webservice.generator;
9   
10  import it.imolinfo.jbi4corba.Logger;
11  import it.imolinfo.jbi4corba.LoggerFactory;
12  
13  import java.lang.reflect.Constructor;
14  import java.lang.reflect.Field;
15  import java.lang.reflect.Method;
16  import java.util.ArrayList;
17  import java.util.List;
18  import java.util.Set;
19  
20  /**
21   * Provides the methods used to visit a class and collect all the data types
22   * used as field, method parameter, exception and return type.
23   */
24  class UtilClassCollector {
25  
26    /**
27     * Logger for the class.
28     */
29    private static final Logger LOG
30      = LoggerFactory.getLogger(UtilClassCollector.class);
31  
32    /**
33     * Default constructor.
34     */
35    public UtilClassCollector () {
36  	// NOP
37    }
38  
39    /**
40     * Provides the methods used to visit a class and collect all the data types
41     * used as field, method parameter, exception and return type.
42     *
43     * @param        result       The container for the class collected.
44     * @param        clazz        The new class to visit.
45     *
46     * @return    The updated class collection.
47     */
48    static Set<Class> visitClassCollector(
49      Set<Class> result, Class clazz) {
50  
51      if (skipClassColletor(result, clazz)) {
52  
53        LOG.debug("DON'T Collect[" + clazz + "]");
54  
55      } else {
56  
57        List<Class> types = null;
58  
59        // multi dimensional array ?
60        if (clazz.isArray()) {
61          LOG.debug("Found an array:" + clazz);
62  
63          result = visitClassCollector(result, clazz.getComponentType());
64  
65        } else  {
66          result.add(clazz);
67          LOG.debug("Collect[" + clazz + "]");
68  
69          types = extractTypes(clazz);
70  
71          for (Class currentType : types) {
72              result = visitClassCollector(result, currentType);
73          }
74        }
75  
76      }
77  
78      return result;
79    }
80  
81    /**
82     * This method decides if a class must be visited or not.
83     *
84     * @param    result    The container for the class collection.
85     * @param    clazz   The class to visit.
86     *
87     * @return    true: if clazz is null
88     *                  or clazz is already visited
89     *                  or clazz is in java.*, javax.*, org.omg.*
90     *                  or clazz is a java primitives data types
91     *                  or an array.
92     */
93    protected static boolean skipClassColletor(Set<Class> result, Class clazz) {
94      if (clazz == null) {
95        return true;
96      }
97      // else
98      //if (result.contains(clazz)) { // THIS CHECK FAILS
99      if (contains(result, clazz)) {
100       return true;
101     }
102     // else
103     String name = clazz.getCanonicalName();
104     if (name.startsWith("java.") || name.startsWith("javax.")
105                                  || name.startsWith("org.omg.")) {
106       return true;
107     }
108     // else
109     if (clazz.isPrimitive()) {
110       return true;
111     }
112     // else
113     return false;
114   }
115 
116   /**
117    * 
118    * @param result  The result
119    * @param clazz   The clazz
120    * @return        The return
121    */
122   protected static boolean contains(Set<Class> result, Class clazz) {
123     if (result == null) {
124         return false;
125     }
126     // else
127     String className = (clazz == null) ? null : clazz.getCanonicalName();
128 
129     for (Class item : result) {
130       String itemClassName = item.getCanonicalName();
131 
132       if (itemClassName.equals(className)) {
133         return true;
134       }
135     }
136 
137     return false;
138   }
139 
140   /**
141    * This method extracts all the data types used in the class.
142    * (Fields and parameter, Excecption, return for each method).
143    *
144    * @param    clazz    The class inspected.
145    *
146    * @return    The list of class cllected. (never null).
147    */
148   public static List<Class> extractTypes(Class clazz) {
149     List<Class> types = new ArrayList<Class>();
150 
151     //types = exctraxtTypesFromConstructor(clazz, types);
152     types = extractTypesFromMethods(clazz, types);
153     types = extractTypesFromFields(clazz, types);
154 
155     return types;
156   }
157 
158   /**
159    * 
160    * @param clazz  The clazz
161    * @param types  The types
162    * @return       The return
163    */
164   private static List<Class> exctraxtTypesFromConstructor(Class clazz,
165     List<Class> types) {
166 
167     Constructor [] constructors = clazz.getConstructors();
168     if (constructors == null) {
169       return types;
170     }
171     // else
172     for (Constructor currConstructor : constructors) {
173       types = extractFromArray(currConstructor.getParameterTypes(), types);
174     }
175 
176     return types;
177   }
178 
179   /**
180    * This method extracts the type of each public field of the class.
181    * (protected and private field are ignored.)
182    *
183    * @param        clazz    The class to visit.
184    * @param        types    The data types already collected.
185    *
186    * @return    The data types collection updated.
187    */
188   private static List<Class> extractTypesFromFields(Class clazz,
189     List<Class> types) {
190 
191     Field [] fields = clazz.getFields();
192     if (fields == null) {
193       return types;
194     }
195     // else
196     for (Field currField : fields) {
197       Class ft = currField.getType();
198       if (! types.contains(ft)) {
199         types.add(ft);
200       }
201     }
202 
203     return types;
204   }
205 
206  /**
207   * 
208   * @param clazz  The clazz
209   * @param types  The types
210   * @return       The return
211   */
212   private static List<Class> extractTypesFromMethods(Class clazz,
213     List<Class> types) {
214 
215     Method [] methods = clazz.getMethods();
216     if (methods == null) {
217       return types;
218     }
219 
220     // else
221 
222     for (Method currentMethod : methods) {
223       // ===== PARAMS
224       Class [] paramTypes = currentMethod.getParameterTypes();
225       types = extractFromArray(paramTypes, types);
226 
227       // ===== EXCEPTIONS
228       Class [] exTypes = currentMethod.getExceptionTypes();
229       types = extractFromArray(exTypes, types);
230 
231       // ===== RETURNS
232       Class ret = currentMethod.getReturnType();
233       if ((ret != null) && (! types.contains(ret))) {
234         types.add(ret);
235       }
236     }
237 
238     return types;
239   }
240 
241   /**
242    * 
243    * @param array  The array
244    * @param types  The types
245    * @return       The return
246    */
247   private static List<Class> extractFromArray(Class [] array,
248     List<Class> types) {
249 
250     if (array == null) {
251       return types;
252     }
253     // else
254     for (Class currentType : array) {
255       if (! types.contains(currentType)) {
256         types.add(currentType);
257       }
258     }
259     return types;
260   }
261 
262 }