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 }