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 }