View Javadoc

1   package org.codehaus.xfire.aegis.type;
2   
3   import java.beans.PropertyDescriptor;
4   import java.lang.reflect.Field;
5   import java.lang.reflect.Method;
6   import java.util.Collection;
7   import java.util.Map;
8   
9   import javax.xml.namespace.QName;
10  
11  import org.codehaus.xfire.XFireRuntimeException;
12  import org.codehaus.xfire.aegis.type.basic.ArrayType;
13  import org.codehaus.xfire.aegis.type.collection.CollectionType;
14  import org.codehaus.xfire.aegis.type.collection.MapType;
15  import org.codehaus.xfire.util.NamespaceHelper;
16  import org.codehaus.xfire.util.ServiceUtils;
17  
18  /***
19   * @author Hani Suleiman
20   *         Date: Jun 14, 2005
21   *         Time: 11:59:57 PM
22   */
23  public abstract class AbstractTypeCreator implements TypeCreator
24  {
25      protected TypeMapping tm;
26      protected AbstractTypeCreator nextCreator;
27  
28      public TypeMapping getTypeMapping()
29      {
30          return tm;
31      }
32  
33      public void setTypeMapping(TypeMapping typeMapping)
34      {
35          this.tm = typeMapping;
36      }
37  
38      public void setNextCreator(AbstractTypeCreator creator)
39      {
40          this.nextCreator = creator;
41      }
42  
43      protected TypeClassInfo createClassInfo(Field f)
44      {
45          return createBasicClassInfo(f.getType());
46      }
47  
48      protected TypeClassInfo createBasicClassInfo(Class typeClass)
49      {
50          TypeClassInfo info = new TypeClassInfo();
51  
52          info.setTypeClass(typeClass);
53  
54          return info;
55      }
56  
57      protected Type createTypeForClass(TypeClassInfo info)
58      {
59          Class javaType = info.getTypeClass();
60  
61          if (info.getType() != null)
62          {
63              return createUserType(info);
64          }
65          if(javaType.isArray())
66          {
67              return createArrayType(info);
68          }
69          else if(isMap(javaType))
70          {
71              return createMapType(info);
72          }
73          else if(isCollection(javaType))
74          {
75              return createCollectionType(info);
76          }
77          else if(isEnum(javaType))
78          {
79              return createEnumType(info);
80          }
81          else
82          {
83              Type type = getTypeMapping().getType(javaType);
84              if (type == null)
85              {
86                  type = createDefaultType(info);
87              }
88              
89              return type;
90          }
91      }
92  
93      protected Type createUserType(TypeClassInfo info)
94      {
95          try
96          {
97              Type type = (Type) info.getType().newInstance();
98              
99              type.setSchemaType(createQName(info.getTypeClass()));
100             type.setTypeClass(info.getTypeClass());
101             type.setTypeMapping(getTypeMapping());
102             
103             return type;
104         }
105         catch (InstantiationException e)
106         {
107             throw new XFireRuntimeException("Couldn't instantiate type classs " + 
108                                             info.getType().getName(), e);
109         }
110         catch (IllegalAccessException e)
111         {
112             throw new XFireRuntimeException("Couldn't access type classs " + 
113                                             info.getType().getName(), e);
114         }
115     }
116     
117     protected QName createArrayQName(Class javaType)
118     {
119         return createCollectionQName(javaType, javaType.getComponentType());
120     }
121 
122     protected Type createArrayType(TypeClassInfo info)
123     {
124         ArrayType type = new ArrayType();
125         type.setSchemaType(createArrayQName(info.getTypeClass()));
126         type.setTypeClass(info.getTypeClass());
127 
128         return type;
129     }
130 
131     protected QName createQName(Class javaType)
132     {
133         String clsName = javaType.getName();
134 
135         String ns = NamespaceHelper.makeNamespaceFromClassName(clsName, "http");
136         String localName = ServiceUtils.makeServiceNameFromClassName(javaType);
137 
138         return new QName(ns, localName);
139     }
140 
141     protected boolean isCollection(Class javaType)
142     {
143         return Collection.class.isAssignableFrom(javaType);
144     }
145 
146     protected Type createCollectionType(TypeClassInfo info, Class component)
147     {
148         CollectionType type = new CollectionType(component);
149         type.setTypeMapping(getTypeMapping());
150         
151         QName name = info.getTypeName();
152         if (name == null) name = createCollectionQName(info.getTypeClass(), component);
153         type.setSchemaType(name);
154         
155         type.setTypeClass(info.getTypeClass());
156 
157         return type;
158     }
159 
160     protected Type createMapType(TypeClassInfo info)
161     {
162         Class keyType = (Class) info.getKeyType();
163         Class valueType = (Class) info.getGenericType();
164 
165         QName schemaType = createMapQName(keyType, valueType);
166         MapType type = new MapType(schemaType, 
167                                    keyType, 
168                                    valueType);
169         type.setTypeMapping(getTypeMapping());
170         type.setTypeClass(info.getTypeClass());
171 
172         return type;
173     }
174 
175     protected QName createMapQName(Class keyClass, Class componentClass)
176     {
177         if(keyClass == null)
178         {
179            throw new XFireRuntimeException("Cannot create mapping for map, unspecified key type");
180         }
181         
182         if(componentClass == null)
183         {
184             throw new XFireRuntimeException("Cannot create mapping for map, unspecified component type");
185         }
186         
187         Type keyType = tm.getType(keyClass);
188         if(keyType == null)
189         {
190             keyType = createType(keyClass);
191             getTypeMapping().register(keyType);
192         }
193         
194         Type componentType = tm.getType(componentClass);
195         if(componentType == null)
196         {
197             componentType = createType(componentClass);
198             getTypeMapping().register(componentType);
199         }
200         
201         String name = keyType.getSchemaType().getLocalPart()
202                       + "2"
203                       + componentType.getSchemaType().getLocalPart()
204                       + "Map";
205          
206         // TODO: Get namespace from XML?
207         return new QName(tm.getEncodingStyleURI(), name);
208     }
209     
210     protected boolean isMap(Class javaType)
211     {
212         return Map.class.isAssignableFrom(javaType);
213     }
214     
215     public abstract TypeClassInfo createClassInfo(PropertyDescriptor pd);
216 
217     protected boolean isEnum(Class javaType)
218     {
219         return false;
220     }
221 
222     public Type createEnumType(TypeClassInfo info)
223     {
224         return null;
225     }
226 
227     public abstract Type createCollectionType(TypeClassInfo info);
228 
229     public abstract Type createDefaultType(TypeClassInfo info);
230 
231     protected QName createCollectionQName(Class javaType, Class componentType)
232     {
233         if(componentType == null)
234         {
235             throw new XFireRuntimeException("Cannot create mapping for " + javaType.getName() + ", unspecified component type");
236         }
237         Type type = tm.getType(componentType);
238         if(type == null)
239         {
240             type = createType(componentType);
241             getTypeMapping().register(type);
242         }
243         String ns;
244 
245         if(type.isComplex())
246         {
247             ns = type.getSchemaType().getNamespaceURI();
248         }
249         else
250         {
251             ns = tm.getEncodingStyleURI();
252         }
253 
254         String first = type.getSchemaType().getLocalPart().substring(0, 1);
255         String last = type.getSchemaType().getLocalPart().substring(1);
256         String localName = "ArrayOf" + first.toUpperCase() + last;
257 
258         return new QName(ns, localName);
259     }
260 
261     public abstract TypeClassInfo createClassInfo(Method m, int index);
262 
263     /***
264      * Create a Type for a Method parameter.
265      *
266      * @param m the method to create a type for
267      * @param index The parameter index. If the index is less than zero, the return type is used.
268      */
269     public Type createType(Method m, int index)
270     {
271         TypeClassInfo info = createClassInfo(m, index);
272 
273         return createTypeForClass(info);
274     }
275 
276     /***
277      * Create type information for a PropertyDescriptor.
278      *
279      * @param pd the propertydescriptor
280      */
281     public Type createType(PropertyDescriptor pd)
282     {
283         TypeClassInfo info = createClassInfo(pd);
284 
285         return createTypeForClass(info);
286     }
287 
288     /***
289      * Create type information for a <code>Field</code>.
290      *
291      * @param f the field to create a type from
292      */
293     public Type createType(Field f)
294     {
295         TypeClassInfo info = createClassInfo(f);
296 
297         return createTypeForClass(info);
298     }
299 
300     public Type createType(Class clazz)
301     {
302         TypeClassInfo info = createBasicClassInfo(clazz);
303 
304         return createTypeForClass(info);
305     }
306 
307     public static class TypeClassInfo
308     {
309         Class typeClass;
310         Object[] annotations;
311         Object genericType;
312         Object keyType;
313         String mappedName;
314         QName typeName;
315         Class type;
316         
317         public Object[] getAnnotations()
318         {
319             return annotations;
320         }
321 
322         public void setAnnotations(Object[] annotations)
323         {
324             this.annotations = annotations;
325         }
326 
327         public Object getGenericType()
328         {
329             return genericType;
330         }
331 
332         public void setGenericType(Object genericType)
333         {
334             this.genericType = genericType;
335         }
336 
337         public Object getKeyType()
338         {
339             return keyType;
340         }
341 
342         public void setKeyType(Object keyType)
343         {
344             this.keyType = keyType;
345         }
346 
347         public Class getTypeClass()
348         {
349             return typeClass;
350         }
351 
352         public void setTypeClass(Class typeClass)
353         {
354             this.typeClass = typeClass;
355         }
356 
357         public QName getTypeName()
358         {
359             return typeName;
360         }
361 
362         public void setTypeName(QName name)
363         {
364             this.typeName = name;
365         }
366 
367         public String getMappedName()
368         {
369             return mappedName;
370         }
371 
372         public void setMappedName(String mappedName)
373         {
374             this.mappedName = mappedName;
375         }
376 
377         public Class getType()
378         {
379             return type;
380         }
381 
382         public void setType(Class type)
383         {
384             this.type = type;
385         }
386     }
387 }