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(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 }