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 }