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