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         QName schemaType = new QName(getTypeMapping().getEncodingStyleURI(), "map");
135         MapType type = new MapType(schemaType, 
136                                    (Class) info.getKeyType(), 
137                                    (Class) info.getGenericType());
138         type.setTypeMapping(getTypeMapping());
139         type.setTypeClass(info.getTypeClass());
140 
141         return type;
142     }
143 
144     protected boolean isMap(Class javaType)
145     {
146         return Map.class.isAssignableFrom(javaType);
147     }
148     
149     public abstract TypeClassInfo createClassInfo(PropertyDescriptor pd);
150 
151     protected boolean isEnum(Class javaType)
152     {
153         return false;
154     }
155 
156     public Type createEnumType(TypeClassInfo info)
157     {
158         return null;
159     }
160 
161     public abstract Type createCollectionType(TypeClassInfo info);
162 
163     public abstract Type createDefaultType(TypeClassInfo info);
164 
165     protected QName createCollectionQName(Class javaType, Class componentType)
166     {
167         if(componentType == null)
168         {
169             throw new XFireRuntimeException("Cannot create mapping for " + javaType.getName() + ", unspecified component type");
170         }
171         Type type = tm.getType(componentType);
172         if(type == null)
173         {
174             type = createType(componentType);
175             getTypeMapping().register(type);
176         }
177         String ns;
178 
179         if(type.isComplex())
180         {
181             ns = type.getSchemaType().getNamespaceURI();
182         }
183         else
184         {
185             ns = tm.getEncodingStyleURI();
186         }
187 
188         String first = type.getSchemaType().getLocalPart().substring(0, 1);
189         String last = type.getSchemaType().getLocalPart().substring(1);
190         String localName = "ArrayOf" + first.toUpperCase() + last;
191 
192         return new QName(ns, localName);
193     }
194 
195     public abstract TypeClassInfo createClassInfo(Method m, int index);
196 
197     /***
198      * Create a Type for a Method parameter.
199      *
200      * @param m the method to create a type for
201      * @param index The parameter index. If the index is less than zero, the return type is used.
202      */
203     public Type createType(Method m, int index)
204     {
205         TypeClassInfo info = createClassInfo(m, index);
206 
207         return createTypeForClass(info);
208     }
209 
210     /***
211      * Create type information for a PropertyDescriptor.
212      *
213      * @param pd the propertydescriptor
214      */
215     public Type createType(PropertyDescriptor pd)
216     {
217         TypeClassInfo info = createClassInfo(pd);
218 
219         return createTypeForClass(info);
220     }
221 
222     /***
223      * Create type information for a <code>Field</code>.
224      *
225      * @param f the field to create a type from
226      */
227     public Type createType(Field f)
228     {
229         TypeClassInfo info = createClassInfo(f);
230 
231         return createTypeForClass(info);
232     }
233 
234     public Type createType(Class clazz)
235     {
236         TypeClassInfo info = createBasicClassInfo(clazz);
237 
238         return createTypeForClass(info);
239     }
240 
241     public static class TypeClassInfo
242     {
243         Class typeClass;
244         Object[] annotations;
245         Object genericType;
246         Object keyType;
247         QName name;
248         
249         public Object[] getAnnotations()
250         {
251             return annotations;
252         }
253 
254         public void setAnnotations(Object[] annotations)
255         {
256             this.annotations = annotations;
257         }
258 
259         public Object getGenericType()
260         {
261             return genericType;
262         }
263 
264         public void setGenericType(Object genericType)
265         {
266             this.genericType = genericType;
267         }
268 
269         public Object getKeyType()
270         {
271             return keyType;
272         }
273 
274         public void setKeyType(Object keyType)
275         {
276             this.keyType = keyType;
277         }
278 
279         public Class getTypeClass()
280         {
281             return typeClass;
282         }
283 
284         public void setTypeClass(Class typeClass)
285         {
286             this.typeClass = typeClass;
287         }
288 
289         public QName getName()
290         {
291             return name;
292         }
293 
294         public void setName(QName name)
295         {
296             this.name = name;
297         }
298     }
299 }