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 }