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(javaType.isArray())
62          {
63              return createArrayType(info);
64          }
65          else if(isMap(javaType))
66          {
67              return createMapType(info);
68          }
69          else if(isCollection(javaType))
70          {
71              return createCollectionType(info);
72          }
73          else if(isEnum(javaType))
74          {
75              return createEnumType(info);
76          }
77          else
78          {
79              Type type = getTypeMapping().getType(javaType);
80              if (type == null)
81              {
82                  type = createDefaultType(info);
83              }
84              
85              return type;
86          }
87      }
88  
89      protected QName createArrayQName(Class javaType)
90      {
91          return createCollectionQName(javaType, javaType.getComponentType());
92      }
93  
94      protected Type createArrayType(TypeClassInfo info)
95      {
96          ArrayType type = new ArrayType();
97          type.setSchemaType(createArrayQName(info.getTypeClass()));
98          type.setTypeClass(info.getTypeClass());
99  
100         return type;
101     }
102 
103     protected QName createQName(Class javaType)
104     {
105         String clsName = javaType.getName();
106 
107         String ns = NamespaceHelper.makeNamespaceFromClassName(clsName, "http");
108         String localName = ServiceUtils.makeServiceNameFromClassName(javaType);
109 
110         return new QName(ns, localName);
111     }
112 
113     protected boolean isCollection(Class javaType)
114     {
115         return Collection.class.isAssignableFrom(javaType);
116     }
117 
118     protected Type createCollectionType(TypeClassInfo info, Class component)
119     {
120         CollectionType type = new CollectionType(component);
121         type.setTypeMapping(getTypeMapping());
122         
123         QName name = info.getName();
124         if (name == null) name = createCollectionQName(info.getTypeClass(), component);
125         type.setSchemaType(name);
126         
127         type.setTypeClass(info.getTypeClass());
128 
129         return type;
130     }
131 
132     protected Type createMapType(TypeClassInfo info)
133     {
134         Class keyType = (Class) info.getKeyType();
135         Class valueType = (Class) info.getGenericType();
136         
137         String lname = keyType.getSimpleName() + valueType.getSimpleName() + "Pair";
138         
139         QName schemaType = new QName(getTypeMapping().getEncodingStyleURI(), lname);
140         MapType type = new MapType(schemaType, 
141                                    keyType, 
142                                    valueType);
143         type.setTypeMapping(getTypeMapping());
144         type.setTypeClass(info.getTypeClass());
145 
146         return type;
147     }
148 
149     protected boolean isMap(Class javaType)
150     {
151         return Map.class.isAssignableFrom(javaType);
152     }
153     
154     public abstract TypeClassInfo createClassInfo(PropertyDescriptor pd);
155 
156     protected boolean isEnum(Class javaType)
157     {
158         return false;
159     }
160 
161     public Type createEnumType(TypeClassInfo info)
162     {
163         return null;
164     }
165 
166     public abstract Type createCollectionType(TypeClassInfo info);
167 
168     public abstract Type createDefaultType(TypeClassInfo info);
169 
170     protected QName createCollectionQName(Class javaType, Class componentType)
171     {
172         if(componentType == null)
173         {
174             throw new XFireRuntimeException("Cannot create mapping for " + javaType.getName() + ", unspecified component type");
175         }
176         Type type = tm.getType(componentType);
177         if(type == null)
178         {
179             type = createType(componentType);
180             getTypeMapping().register(type);
181         }
182         String ns;
183 
184         if(type.isComplex())
185         {
186             ns = type.getSchemaType().getNamespaceURI();
187         }
188         else
189         {
190             ns = tm.getEncodingStyleURI();
191         }
192 
193         String first = type.getSchemaType().getLocalPart().substring(0, 1);
194         String last = type.getSchemaType().getLocalPart().substring(1);
195         String localName = "ArrayOf" + first.toUpperCase() + last;
196 
197         return new QName(ns, localName);
198     }
199 
200     public abstract TypeClassInfo createClassInfo(Method m, int index);
201 
202     /***
203      * Create a Type for a Method parameter.
204      *
205      * @param m the method to create a type for
206      * @param index The parameter index. If the index is less than zero, the return type is used.
207      */
208     public Type createType(Method m, int index)
209     {
210         TypeClassInfo info = createClassInfo(m, index);
211 
212         return createTypeForClass(info);
213     }
214 
215     /***
216      * Create type information for a PropertyDescriptor.
217      *
218      * @param pd the propertydescriptor
219      */
220     public Type createType(PropertyDescriptor pd)
221     {
222         TypeClassInfo info = createClassInfo(pd);
223 
224         return createTypeForClass(info);
225     }
226 
227     /***
228      * Create type information for a <code>Field</code>.
229      *
230      * @param f the field to create a type from
231      */
232     public Type createType(Field f)
233     {
234         TypeClassInfo info = createClassInfo(f);
235 
236         return createTypeForClass(info);
237     }
238 
239     public Type createType(Class clazz)
240     {
241         TypeClassInfo info = createBasicClassInfo(clazz);
242 
243         return createTypeForClass(info);
244     }
245 
246     public static class TypeClassInfo
247     {
248         Class typeClass;
249         Object[] annotations;
250         Object genericType;
251         Object keyType;
252         QName name;
253         
254         public Object[] getAnnotations()
255         {
256             return annotations;
257         }
258 
259         public void setAnnotations(Object[] annotations)
260         {
261             this.annotations = annotations;
262         }
263 
264         public Object getGenericType()
265         {
266             return genericType;
267         }
268 
269         public void setGenericType(Object genericType)
270         {
271             this.genericType = genericType;
272         }
273 
274         public Object getKeyType()
275         {
276             return keyType;
277         }
278 
279         public void setKeyType(Object keyType)
280         {
281             this.keyType = keyType;
282         }
283 
284         public Class getTypeClass()
285         {
286             return typeClass;
287         }
288 
289         public void setTypeClass(Class typeClass)
290         {
291             this.typeClass = typeClass;
292         }
293 
294         public QName getName()
295         {
296             return name;
297         }
298 
299         public void setName(QName name)
300         {
301             this.name = name;
302         }
303     }
304 }