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