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 }