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 qname2name = new HashMap();
22      private Class typeClass;
23      private List attributes = new ArrayList();
24      private List elements = new ArrayList();
25      private String defaultNamespace;
26      private PropertyDescriptor[] descriptors;
27      private TypeMapping typeMapping;
28      private boolean initialized;
29      
30      public BeanTypeInfo(Class typeClass, String defaultNamespace)
31      {
32          this.typeClass = typeClass;
33          this.defaultNamespace = defaultNamespace;
34          
35          initializeProperties();
36      }
37  
38      /***
39       * Create a BeanTypeInfo class.
40       * 
41       * @param typeClass
42       * @param defaultNamespace
43       * @param initiallize If true attempt default property/xml mappings.
44       */
45      public BeanTypeInfo(Class typeClass, String defaultNamespace, boolean initialize)
46      {
47          this.typeClass = typeClass;
48          this.defaultNamespace = defaultNamespace;
49          
50          initializeProperties();
51          setInitialized(!initialize);
52      }
53      
54      protected BeanTypeInfo(Class typeClass)
55      {
56          this.typeClass = typeClass;
57  
58          initializeProperties();
59      }
60      
61      public void initialize()
62      {
63          try
64          {
65              for (int i = 0; i < descriptors.length; i++)
66              {
67                  // Don't map the property unless there is both a read and write property
68                  if (descriptors[i].getReadMethod() != null &&
69                          descriptors[i].getWriteMethod() != null)
70                  {
71                      mapProperty(descriptors[i]);
72                  }
73              }
74          }
75          catch (Exception e)
76          {
77              if(e instanceof XFireRuntimeException) throw (XFireRuntimeException)e;
78              throw new XFireRuntimeException("Couldn't create TypeInfo.", e);
79          }
80          
81          setInitialized(true);
82      }
83  
84      public boolean isInitialized()
85      {
86          return initialized;
87      }
88  
89      private void setInitialized(boolean initialized)
90      {
91          this.initialized = initialized;
92      }
93  
94      protected void mapProperty(PropertyDescriptor pd)
95      {
96          String name = pd.getName();
97     
98          if (isAttribute(pd))
99          {
100             mapAttribute(name, createQName(pd));
101         }
102         else if (isElement(pd))
103         {
104             mapElement(name, createQName(pd));
105         }
106     }
107     
108     protected PropertyDescriptor[] getPropertyDescriptors()
109     {
110         return descriptors;
111     }
112 
113     protected PropertyDescriptor getPropertyDescriptor(String name)
114     {
115         for (int i = 0; i < descriptors.length; i++)
116         {
117             if (descriptors[i].getName().equals(name))
118                 return descriptors[i];
119         }
120         
121         return null;
122     }
123 
124     /***
125      * Get the type class for the field with the specified QName.
126      */
127     public Type getType(QName name) 
128     {
129         Type type = getTypeMapping().getType(name);
130         
131         if (type == null)
132         {
133             PropertyDescriptor desc;
134             try
135             {
136                 desc = getPropertyDescriptor(name);
137             }
138             catch (Exception e)
139             {
140                 if(e instanceof XFireRuntimeException) throw (XFireRuntimeException)e;
141                 throw new XFireRuntimeException("Couldn't get properties.", e);
142             }
143             
144             if (desc == null)
145             {
146                 return null;
147             }
148 
149             if (getTypeMapping().isRegistered(desc.getPropertyType()))
150             {
151                 type = getTypeMapping().getType(desc.getPropertyType());
152             }
153             else
154             {
155                 try
156                 {
157                     type = getTypeMapping().getTypeCreator().createType(desc);
158                 }
159                 catch(XFireRuntimeException e)
160                 {
161                     e.prepend("Couldn't create type for property " + desc.getName() 
162                               + " on " + getTypeClass());
163                     
164                     throw e;
165                 }
166                 
167                 getTypeMapping().register(type);
168             }
169         }
170         
171         if ( type == null )
172             throw new XFireRuntimeException( "Couldn't find type for property " + name );
173         
174         return type;
175     }
176 
177     public TypeMapping getTypeMapping()
178     {
179         return typeMapping;
180     }
181 
182     public void setTypeMapping(TypeMapping typeMapping)
183     {
184         this.typeMapping = typeMapping;
185     }
186 
187     protected QName createQName(PropertyDescriptor desc)
188     {
189         return new QName(defaultNamespace, desc.getName());
190     }
191 
192     public void mapAttribute(String property, QName type)
193     {
194         qname2name.put(type, property);
195         attributes.add(type);
196     }
197 
198     public void mapElement(String property, QName type)
199     {
200         qname2name.put(type, property);
201         elements.add(type);
202     }
203     
204     private void initializeProperties()
205     {
206         BeanInfo beanInfo = null;
207         try
208         {
209             if (typeClass.isInterface() || typeClass.isPrimitive())
210             {
211                 beanInfo = Introspector.getBeanInfo(typeClass);
212             }
213             else if (typeClass == Object.class)
214             {
215             }
216             else
217             {
218                 beanInfo = Introspector.getBeanInfo(typeClass, Object.class);
219             }
220         }
221         catch (IntrospectionException e)
222         {
223             throw new XFireRuntimeException("Couldn't introspect interface.", e);
224         }
225         
226         if (beanInfo != null)
227             descriptors = beanInfo.getPropertyDescriptors();
228         
229         if (descriptors == null)
230         {
231             descriptors = new PropertyDescriptor[0];
232         }
233     }
234 
235     public PropertyDescriptor getPropertyDescriptor(QName name)
236     {
237         return getPropertyDescriptor( getPropertyName(name) );
238     }
239     
240     protected boolean isAttribute(PropertyDescriptor desc)
241     {
242         return false;
243     }
244     
245     protected boolean isElement(PropertyDescriptor desc)
246     {
247         return true;
248     }
249 
250     protected boolean isSerializable(PropertyDescriptor desc)
251     {
252         return true;
253     }
254 
255     protected Class getTypeClass()
256     {
257         return typeClass;
258     }
259 
260     public boolean isNillable(QName name)
261     {
262         return true;
263     }
264     
265     private String getPropertyName(QName name)
266     {
267         return (String) qname2name.get(name);
268     }
269     
270     public Iterator getAttributes()
271     {
272         return attributes.iterator();
273     }
274 
275     public Iterator getElements()
276     {
277         return elements.iterator();
278     }
279 }