View Javadoc

    1   package org.codehaus.xfire.aegis.type.basic;
    2
    3   import java.beans.BeanInfo;
    4   import java.beans.IntrospectionException;
    5   import java.beans.Introspector;
    6   import java.beans.PropertyDescriptor;
    7   import java.util.ArrayList;
    8   import java.util.HashMap;
    9   import java.util.Iterator;
    10  import java.util.List;
    11  import java.util.Map;
    12
    13  import javax.xml.namespace.QName;
    14
    15  import org.codehaus.xfire.XFireRuntimeException;
    16  import org.codehaus.xfire.aegis.type.Type;
    17  import org.codehaus.xfire.aegis.type.TypeMapping;
    18
    19  public class BeanTypeInfo
    20  {
    21      private Map mappedName2typeName = new HashMap();
    22      private Map mappedName2pdName = new HashMap();
    23      private Map mappedName2type = new HashMap();
    24
    25      private Class beanClass;
    26      private List attributes = new ArrayList();
    27      private List elements = new ArrayList();
    28      private PropertyDescriptor[] descriptors;
    29      private TypeMapping typeMapping;
    30      private boolean initialized;
    31
    32      public BeanTypeInfo(Class typeClass)
    33      {
    34          this.beanClass = typeClass;
    35
    36          initializeProperties();
    37      }
    38
    39      /***
    40       * Create a BeanTypeInfo class.
    41       *
    42       * @param typeClass
    43       * @param defaultNamespace
    44       * @param initiallize If true attempt default property/xml mappings.
    45       */
    46      public BeanTypeInfo(Class typeClass, boolean initialize)
    47      {
    48          this.beanClass = typeClass;
    49
    50          initializeProperties();
    51          setInitialized(!initialize);
    52      }
    53
    54      public void initialize()
    55      {
    56          try
    57          {
    58              for (int i = 0; i < descriptors.length; i++)
    59              {
    60                  // Don't map the property unless there is both a read and write property
    61                  if (descriptors[i].getReadMethod() != null &&
    62                          descriptors[i].getWriteMethod() != null)
    63                  {
    64                      mapProperty(descriptors[i]);
    65                  }
    66              }
    67          }
    68          catch (Exception e)
    69          {
    70              if(e instanceof XFireRuntimeException) throw (XFireRuntimeException)e;
    71              throw new XFireRuntimeException("Couldn't create TypeInfo.", e);
    72          }
    73
    74          setInitialized(true);
    75      }
    76
    77      public boolean isInitialized()
    78      {
    79          return initialized;
    80      }
    81
    82      private void setInitialized(boolean initialized)
    83      {
    84          this.initialized = initialized;
    85      }
    86
    87      protected void mapProperty(PropertyDescriptor pd)
    88      {
    89          String name = pd.getName();
    90
    91          if (isAttribute(pd))
    92          {
    93              mapAttribute(name, createMappedName(pd));
    94          }
    95          else if (isElement(pd))
    96          {
    97              mapElement(name, createMappedName(pd));
    98          }
    99      }
    100
    101     protected PropertyDescriptor[] getPropertyDescriptors()
    102     {
    103         return descriptors;
    104     }
    105
    106     protected PropertyDescriptor getPropertyDescriptor(String name)
    107     {
    108         for (int i = 0; i < descriptors.length; i++)
    109         {
    110             if (descriptors[i].getName().equals(name))
    111                 return descriptors[i];
    112         }
    113
    114         return null;
    115     }
    116
    117     /***
    118      * Get the type class for the field with the specified QName.
    119      */
    120     public Type getType(String name)
    121     {
    122         // 1. Try a prexisting mapped type
    123         Type type = (Type) mappedName2type.get(name);
    124
    125         // 2. Try to get the type by its name, if there is one
    126         if (type == null)
    127         {
    128             QName typeName = getMappedTypeName(name);
    129             if (typeName != null)
    130             {
    131                 type = getTypeMapping().getType(typeName);
    132
    133                 if (type != null) mapType(name, type);
    134             }
    135         }
    136
    137         // 3. Create the type from the property descriptor and map it
    138         if (type == null)
    139         {
    140             PropertyDescriptor desc;
    141             try
    142             {
    143                 desc = getPropertyDescriptorFromMappedName(name);
    144             }
    145             catch (Exception e)
    146             {
    147                 if(e instanceof XFireRuntimeException) throw (XFireRuntimeException)e;
    148                 throw new XFireRuntimeException("Couldn't get properties.", e);
    149             }
    150
    151             if (desc == null)
    152             {
    153                 return null;
    154             }
    155
    156             try
    157             {
    158                 type = getTypeMapping().getTypeCreator().createType(desc);
    159             }
    160             catch(XFireRuntimeException e)
    161             {
    162                 e.prepend("Couldn't create type for property " + desc.getName()
    163                           + " on " + getTypeClass());
    164
    165                 throw e;
    166             }
    167
    168             getTypeMapping().register(type);
    169             mapType(name, type);
    170         }
    171
    172         if ( type == null )
    173             throw new XFireRuntimeException( "Couldn't find type for property " + name );
    174
    175         return type;
    176     }
    177
    178     public void mapType(String name, Type type)
    179     {
    180         mappedName2type.put(name, type);
    181     }
    182
    183     private QName getMappedTypeName(String name)
    184     {
    185         return (QName) mappedName2typeName.get(name);
    186     }
    187
    188     public TypeMapping getTypeMapping()
    189     {
    190         return typeMapping;
    191     }
    192
    193     public void setTypeMapping(TypeMapping typeMapping)
    194     {
    195         this.typeMapping = typeMapping;
    196     }
    197
    198     /***
    199      * Specifies the name of the property as it shows up in the xml schema.
    200      * This method just returns <code>propertyDescriptor.getName();</code>
    201      * @param desc
    202      * @return
    203      */
    204     protected String createMappedName(PropertyDescriptor desc)
    205     {
    206         return desc.getName();
    207     }
    208
    209     public void mapAttribute(String property, String mappedName)
    210     {
    211         mappedName2pdName.put(mappedName, property);
    212         attributes.add(mappedName);
    213     }
    214
    215     public void mapElement(String property, String mappedName)
    216     {
    217         mappedName2pdName.put(mappedName, property);
    218         elements.add(mappedName);
    219     }
    220
    221     /***
    222      * Specifies the SchemaType for a particular class.
    223      * @param mappedName
    224      * @param type
    225      */
    226     public void mapTypeName(String mappedName, QName type)
    227     {
    228         mappedName2typeName.put(mappedName, type);
    229     }
    230
    231     private void initializeProperties()
    232     {
    233         BeanInfo beanInfo = null;
    234         try
    235         {
    236             if (beanClass.isInterface() || beanClass.isPrimitive())
    237             {
    238                 beanInfo = Introspector.getBeanInfo(beanClass);
    239             }
    240             else if (beanClass == Object.class)
    241             {
    242             }
    243             else
    244             {
    245                 beanInfo = Introspector.getBeanInfo(beanClass, Object.class);
    246             }
    247         }
    248         catch (IntrospectionException e)
    249         {
    250             throw new XFireRuntimeException("Couldn't introspect interface.", e);
    251         }
    252
    253         if (beanInfo != null)
    254             descriptors = beanInfo.getPropertyDescriptors();
    255
    256         if (descriptors == null)
    257         {
    258             descriptors = new PropertyDescriptor[0];
    259         }
    260     }
    261
    262     public PropertyDescriptor getPropertyDescriptorFromMappedName(String name)
    263     {
    264         return getPropertyDescriptor( getPropertyNameFromMappedName(name) );
    265     }
    266
    267     protected boolean isAttribute(PropertyDescriptor desc)
    268     {
    269         return false;
    270     }
    271
    272     protected boolean isElement(PropertyDescriptor desc)
    273     {
    274         return true;
    275     }
    276
    277     protected boolean isSerializable(PropertyDescriptor desc)
    278     {
    279         return true;
    280     }
    281
    282     protected Class getTypeClass()
    283     {
    284         return beanClass;
    285     }
    286
    287     public boolean isNillable(String name)
    288     {
    289         return getType(name).isNillable();
    290     }
    291
    292     private String getPropertyNameFromMappedName(String name)
    293     {
    294         return (String) mappedName2pdName.get(name);
    295     }
    296
    297     public Iterator getAttributes()
    298     {
    299         return attributes.iterator();
    300     }
    301
    302     public Iterator getElements()
    303     {
    304         return elements.iterator();
    305     }
    306 }