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 (info.getType() != null)
    62          {
    63              return createUserType(info);
    64          }
    65          if(javaType.isArray())
    66          {
    67              return createArrayType(info);
    68          }
    69          else if(isMap(javaType))
    70          {
    71              return createMapType(info);
    72          }
    73          else if(isCollection(javaType))
    74          {
    75              return createCollectionType(info);
    76          }
    77          else if(isEnum(javaType))
    78          {
    79              return createEnumType(info);
    80          }
    81          else
    82          {
    83              Type type = getTypeMapping().getType(javaType);
    84              if (type == null)
    85              {
    86                  type = createDefaultType(info);
    87              }
    88
    89              return type;
    90          }
    91      }
    92
    93      protected Type createUserType(TypeClassInfo info)
    94      {
    95          try
    96          {
    97              Type type = (Type) info.getType().newInstance();
    98
    99              type.setSchemaType(createQName(info.getTypeClass()));
    100             type.setTypeClass(info.getTypeClass());
    101             type.setTypeMapping(getTypeMapping());
    102
    103             return type;
    104         }
    105         catch (InstantiationException e)
    106         {
    107             throw new XFireRuntimeException("Couldn't instantiate type classs " +
    108                                             info.getType().getName(), e);
    109         }
    110         catch (IllegalAccessException e)
    111         {
    112             throw new XFireRuntimeException("Couldn't access type classs " +
    113                                             info.getType().getName(), e);
    114         }
    115     }
    116
    117     protected QName createArrayQName(Class javaType)
    118     {
    119         return createCollectionQName(javaType, javaType.getComponentType());
    120     }
    121
    122     protected Type createArrayType(TypeClassInfo info)
    123     {
    124         ArrayType type = new ArrayType();
    125         type.setSchemaType(createArrayQName(info.getTypeClass()));
    126         type.setTypeClass(info.getTypeClass());
    127
    128         return type;
    129     }
    130
    131     protected QName createQName(Class javaType)
    132     {
    133         String clsName = javaType.getName();
    134
    135         String ns = NamespaceHelper.makeNamespaceFromClassName(clsName, "http");
    136         String localName = ServiceUtils.makeServiceNameFromClassName(javaType);
    137
    138         return new QName(ns, localName);
    139     }
    140
    141     protected boolean isCollection(Class javaType)
    142     {
    143         return Collection.class.isAssignableFrom(javaType);
    144     }
    145
    146     protected Type createCollectionType(TypeClassInfo info, Class component)
    147     {
    148         CollectionType type = new CollectionType(component);
    149         type.setTypeMapping(getTypeMapping());
    150
    151         QName name = info.getTypeName();
    152         if (name == null) name = createCollectionQName(info.getTypeClass(), component);
    153         type.setSchemaType(name);
    154
    155         type.setTypeClass(info.getTypeClass());
    156
    157         return type;
    158     }
    159
    160     protected Type createMapType(TypeClassInfo info)
    161     {
    162         Class keyType = (Class) info.getKeyType();
    163         Class valueType = (Class) info.getGenericType();
    164
    165         QName schemaType = createMapQName(keyType, valueType);
    166         MapType type = new MapType(schemaType,
    167                                    keyType,
    168                                    valueType);
    169         type.setTypeMapping(getTypeMapping());
    170         type.setTypeClass(info.getTypeClass());
    171
    172         return type;
    173     }
    174
    175     protected QName createMapQName(Class keyClass, Class componentClass)
    176     {
    177         if(keyClass == null)
    178         {
    179            throw new XFireRuntimeException("Cannot create mapping for map, unspecified key type");
    180         }
    181
    182         if(componentClass == null)
    183         {
    184             throw new XFireRuntimeException("Cannot create mapping for map, unspecified component type");
    185         }
    186
    187         Type keyType = tm.getType(keyClass);
    188         if(keyType == null)
    189         {
    190             keyType = createType(keyClass);
    191             getTypeMapping().register(keyType);
    192         }
    193
    194         Type componentType = tm.getType(componentClass);
    195         if(componentType == null)
    196         {
    197             componentType = createType(componentClass);
    198             getTypeMapping().register(componentType);
    199         }
    200
    201         String name = keyType.getSchemaType().getLocalPart()
    202                       + "2"
    203                       + componentType.getSchemaType().getLocalPart()
    204                       + "Map";
    205
    206         // TODO: Get namespace from XML?
    207         return new QName(tm.getEncodingStyleURI(), name);
    208     }
    209
    210     protected boolean isMap(Class javaType)
    211     {
    212         return Map.class.isAssignableFrom(javaType);
    213     }
    214
    215     public abstract TypeClassInfo createClassInfo(PropertyDescriptor pd);
    216
    217     protected boolean isEnum(Class javaType)
    218     {
    219         return false;
    220     }
    221
    222     public Type createEnumType(TypeClassInfo info)
    223     {
    224         return null;
    225     }
    226
    227     public abstract Type createCollectionType(TypeClassInfo info);
    228
    229     public abstract Type createDefaultType(TypeClassInfo info);
    230
    231     protected QName createCollectionQName(Class javaType, Class componentType)
    232     {
    233         if(componentType == null)
    234         {
    235             throw new XFireRuntimeException("Cannot create mapping for " + javaType.getName() + ", unspecified component type");
    236         }
    237         Type type = tm.getType(componentType);
    238         if(type == null)
    239         {
    240             type = createType(componentType);
    241             getTypeMapping().register(type);
    242         }
    243         String ns;
    244
    245         if(type.isComplex())
    246         {
    247             ns = type.getSchemaType().getNamespaceURI();
    248         }
    249         else
    250         {
    251             ns = tm.getEncodingStyleURI();
    252         }
    253
    254         String first = type.getSchemaType().getLocalPart().substring(0, 1);
    255         String last = type.getSchemaType().getLocalPart().substring(1);
    256         String localName = "ArrayOf" + first.toUpperCase() + last;
    257
    258         return new QName(ns, localName);
    259     }
    260
    261     public abstract TypeClassInfo createClassInfo(Method m, int index);
    262
    263     /***
    264      * Create a Type for a Method parameter.
    265      *
    266      * @param m the method to create a type for
    267      * @param index The parameter index. If the index is less than zero, the return type is used.
    268      */
    269     public Type createType(Method m, int index)
    270     {
    271         TypeClassInfo info = createClassInfo(m, index);
    272
    273         return createTypeForClass(info);
    274     }
    275
    276     /***
    277      * Create type information for a PropertyDescriptor.
    278      *
    279      * @param pd the propertydescriptor
    280      */
    281     public Type createType(PropertyDescriptor pd)
    282     {
    283         TypeClassInfo info = createClassInfo(pd);
    284
    285         return createTypeForClass(info);
    286     }
    287
    288     /***
    289      * Create type information for a <code>Field</code>.
    290      *
    291      * @param f the field to create a type from
    292      */
    293     public Type createType(Field f)
    294     {
    295         TypeClassInfo info = createClassInfo(f);
    296
    297         return createTypeForClass(info);
    298     }
    299
    300     public Type createType(Class clazz)
    301     {
    302         TypeClassInfo info = createBasicClassInfo(clazz);
    303
    304         return createTypeForClass(info);
    305     }
    306
    307     public static class TypeClassInfo
    308     {
    309         Class typeClass;
    310         Object[] annotations;
    311         Object genericType;
    312         Object keyType;
    313         String mappedName;
    314         QName typeName;
    315         Class type;
    316
    317         public Object[] getAnnotations()
    318         {
    319             return annotations;
    320         }
    321
    322         public void setAnnotations(Object[] annotations)
    323         {
    324             this.annotations = annotations;
    325         }
    326
    327         public Object getGenericType()
    328         {
    329             return genericType;
    330         }
    331
    332         public void setGenericType(Object genericType)
    333         {
    334             this.genericType = genericType;
    335         }
    336
    337         public Object getKeyType()
    338         {
    339             return keyType;
    340         }
    341
    342         public void setKeyType(Object keyType)
    343         {
    344             this.keyType = keyType;
    345         }
    346
    347         public Class getTypeClass()
    348         {
    349             return typeClass;
    350         }
    351
    352         public void setTypeClass(Class typeClass)
    353         {
    354             this.typeClass = typeClass;
    355         }
    356
    357         public QName getTypeName()
    358         {
    359             return typeName;
    360         }
    361
    362         public void setTypeName(QName name)
    363         {
    364             this.typeName = name;
    365         }
    366
    367         public String getMappedName()
    368         {
    369             return mappedName;
    370         }
    371
    372         public void setMappedName(String mappedName)
    373         {
    374             this.mappedName = mappedName;
    375         }
    376
    377         public Class getType()
    378         {
    379             return type;
    380         }
    381
    382         public void setType(Class type)
    383         {
    384             this.type = type;
    385         }
    386     }
    387 }