1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
package org.apache.commons.clazz.bean; |
17 | |
|
18 | |
import java.lang.reflect.Constructor; |
19 | |
import java.util.ArrayList; |
20 | |
import java.util.Collections; |
21 | |
import java.util.HashMap; |
22 | |
import java.util.HashSet; |
23 | |
import java.util.Iterator; |
24 | |
import java.util.List; |
25 | |
import java.util.Map; |
26 | |
import java.util.Set; |
27 | |
|
28 | |
import org.apache.commons.clazz.Clazz; |
29 | |
import org.apache.commons.clazz.ClazzChangeListener; |
30 | |
import org.apache.commons.clazz.ClazzInstanceFactory; |
31 | |
import org.apache.commons.clazz.ClazzLoader; |
32 | |
import org.apache.commons.clazz.ClazzOperation; |
33 | |
import org.apache.commons.clazz.ClazzProperty; |
34 | |
|
35 | |
|
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | 0 | public class BeanClazz extends Clazz { |
45 | |
private Clazz superClazz; |
46 | 0 | private List declaredProperties = new ArrayList(); |
47 | 0 | private List properties = new ArrayList(); |
48 | 0 | private Map propertyMap = new HashMap(); |
49 | 0 | private List declaredOperations = new ArrayList(); |
50 | 0 | private List operations = new ArrayList(); |
51 | 0 | private Map operationMap = new HashMap(); |
52 | |
private List instanceFactories; |
53 | 0 | private Map instanceFactoryMap = new HashMap(); |
54 | |
private Class instanceClass; |
55 | 0 | private List subclasses = new ArrayList(); |
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
|
63 | |
public BeanClazz(ClazzLoader loader, String name, Class instanceClass) { |
64 | 0 | super(loader, name); |
65 | 0 | this.instanceClass = instanceClass; |
66 | 0 | } |
67 | |
|
68 | |
public Class getInstanceClass() { |
69 | 0 | if (instanceClass != null) { |
70 | 0 | return instanceClass; |
71 | |
} |
72 | |
|
73 | 0 | if (superClazz instanceof BeanClazz) { |
74 | 0 | return ((BeanClazz) superClazz).getInstanceClass(); |
75 | |
} |
76 | |
|
77 | 0 | return BasicBean.class; |
78 | |
} |
79 | |
|
80 | |
|
81 | |
|
82 | |
|
83 | |
public Clazz getSuperclazz() { |
84 | 0 | return superClazz; |
85 | |
} |
86 | |
|
87 | |
public void setSuperclazz(Clazz clazz) { |
88 | 0 | if (superClazz != null) { |
89 | 0 | superClazz.removeClazzChangeListener(listener); |
90 | |
} |
91 | 0 | superClazz = clazz; |
92 | 0 | if (clazz != null) { |
93 | 0 | superClazz.addClazzChangeListener(listener); |
94 | |
} |
95 | 0 | refreshAllCaches(); |
96 | 0 | } |
97 | |
|
98 | |
protected void refreshAllCaches() { |
99 | 0 | refreshPropertyCache(); |
100 | 0 | refreshOperationCache(); |
101 | 0 | } |
102 | |
|
103 | |
protected void refreshPropertyCache() { |
104 | 0 | properties = new ArrayList(); |
105 | 0 | propertyMap = new HashMap(); |
106 | |
|
107 | 0 | Set propertyNames = new HashSet(); |
108 | 0 | if (superClazz != null) { |
109 | 0 | List superProperties = superClazz.getProperties(); |
110 | 0 | properties.addAll(superProperties); |
111 | 0 | for (int i = 0; i < superProperties.size(); i++) { |
112 | 0 | ClazzProperty superProperty = |
113 | |
(ClazzProperty) superProperties.get(i); |
114 | 0 | propertyNames.add(superProperty.getName()); |
115 | |
} |
116 | |
} |
117 | 0 | for (int i = 0; i < declaredProperties.size(); i++) { |
118 | 0 | ClazzProperty property = (ClazzProperty) declaredProperties.get(i); |
119 | 0 | String name = property.getName(); |
120 | 0 | if (!propertyNames.contains(name)) { |
121 | 0 | properties.add(property); |
122 | |
} |
123 | |
} |
124 | |
|
125 | 0 | for (Iterator iter = properties.iterator(); iter.hasNext();) { |
126 | 0 | ClazzProperty property = (ClazzProperty) iter.next(); |
127 | 0 | propertyMap.put(property.getName(), property); |
128 | 0 | } |
129 | 0 | } |
130 | |
|
131 | |
protected void refreshOperationCache() { |
132 | 0 | List operations = new ArrayList(); |
133 | 0 | Set signatures = new HashSet(); |
134 | 0 | if (superClazz != null) { |
135 | 0 | List superOperations = superClazz.getOperations(); |
136 | 0 | operations.addAll(superOperations); |
137 | 0 | for (int i = 0; i < superOperations.size(); i++) { |
138 | 0 | ClazzOperation superOperation = |
139 | |
(ClazzOperation) superOperations.get(i); |
140 | 0 | signatures.add(superOperation.getSignature()); |
141 | |
} |
142 | |
} |
143 | 0 | for (int i = 0; i < declaredOperations.size(); i++) { |
144 | 0 | ClazzOperation operation = |
145 | |
(ClazzOperation) declaredOperations.get(i); |
146 | 0 | String signature = operation.getSignature(); |
147 | 0 | if (!signatures.contains(signature)) { |
148 | 0 | operations.add(operation); |
149 | |
} |
150 | |
} |
151 | 0 | } |
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
public List getDeclaredProperties() { |
157 | 0 | return Collections.unmodifiableList(declaredProperties); |
158 | |
} |
159 | |
|
160 | |
public void addDeclaredProperty(ClazzProperty property) { |
161 | 0 | if (property.getDeclaringClazz() != this) { |
162 | 0 | throw new BeanClazzConfigurationException( |
163 | |
"Property belongs to a different clazz: " |
164 | |
+ property.getDeclaringClazz().getName()); |
165 | |
} |
166 | |
|
167 | 0 | ClazzProperty oldProperty = |
168 | |
(ClazzProperty) propertyMap.get(property.getName()); |
169 | 0 | if (oldProperty != null) { |
170 | 0 | removeDeclaredProperty(oldProperty); |
171 | |
} |
172 | |
|
173 | 0 | declaredProperties.add(property); |
174 | |
|
175 | 0 | addProperty(property); |
176 | 0 | } |
177 | |
|
178 | |
|
179 | |
|
180 | |
|
181 | |
protected void addProperty(ClazzProperty property) { |
182 | 0 | properties.add(property); |
183 | 0 | propertyMap.put(property.getName(), property); |
184 | 0 | firePropertyAdded(property); |
185 | 0 | } |
186 | |
|
187 | |
public void removeDeclaredProperty(ClazzProperty property) { |
188 | 0 | String name = property.getName(); |
189 | 0 | property = (ClazzProperty) propertyMap.get(name); |
190 | 0 | if (property != null) { |
191 | 0 | declaredProperties.remove(property); |
192 | 0 | removeProperty(property); |
193 | |
} |
194 | 0 | } |
195 | |
|
196 | |
|
197 | |
|
198 | |
|
199 | |
protected void removeProperty(ClazzProperty property) { |
200 | 0 | String name = property.getName(); |
201 | 0 | properties.remove(property); |
202 | 0 | propertyMap.remove(name); |
203 | 0 | firePropertyRemoved(property); |
204 | |
|
205 | |
|
206 | |
|
207 | 0 | if (superClazz != null) { |
208 | 0 | property = superClazz.getProperty(name); |
209 | 0 | if (property != null) { |
210 | 0 | addProperty(property); |
211 | |
} |
212 | |
} |
213 | 0 | } |
214 | |
|
215 | |
|
216 | |
|
217 | |
|
218 | |
public List getProperties() { |
219 | 0 | return properties; |
220 | |
} |
221 | |
|
222 | |
|
223 | |
|
224 | |
|
225 | |
public ClazzProperty getProperty(String name) { |
226 | 0 | return (ClazzProperty) propertyMap.get(name); |
227 | |
} |
228 | |
|
229 | |
|
230 | |
|
231 | |
|
232 | |
public List getDeclaredOperations() { |
233 | 0 | return Collections.unmodifiableList(declaredOperations); |
234 | |
} |
235 | |
|
236 | |
public void addDeclaredOperation(ClazzOperation operation) { |
237 | 0 | if (operation.getDeclaringClazz() != this) { |
238 | 0 | throw new BeanClazzConfigurationException( |
239 | |
"Operation belongs to a different clazz: " |
240 | |
+ operation.getDeclaringClazz().getName()); |
241 | |
} |
242 | |
|
243 | 0 | ClazzOperation oldOperation = |
244 | |
(ClazzOperation) operationMap.get(operation.getSignature()); |
245 | 0 | if (oldOperation != null) { |
246 | 0 | removeDeclaredOperation(oldOperation); |
247 | |
} |
248 | |
|
249 | 0 | declaredOperations.add(operation); |
250 | |
|
251 | 0 | addOperation(operation); |
252 | 0 | } |
253 | |
|
254 | |
|
255 | |
|
256 | |
|
257 | |
protected void addOperation(ClazzOperation operation) { |
258 | 0 | operations.add(operation); |
259 | 0 | operationMap.put(operation.getSignature(), operation); |
260 | 0 | fireOperationAdded(operation); |
261 | 0 | } |
262 | |
|
263 | |
public void removeDeclaredOperation(ClazzOperation operation) { |
264 | 0 | String signature = operation.getSignature(); |
265 | 0 | operation = (ClazzOperation) operationMap.get(signature); |
266 | 0 | if (operation != null) { |
267 | 0 | declaredOperations.remove(operation); |
268 | 0 | removeOperation(operation); |
269 | |
} |
270 | 0 | } |
271 | |
|
272 | |
|
273 | |
|
274 | |
|
275 | |
protected void removeOperation(ClazzOperation operation) { |
276 | 0 | String signature = operation.getSignature(); |
277 | 0 | operations.remove(operation); |
278 | 0 | operationMap.remove(signature); |
279 | 0 | fireOperationRemoved(operation); |
280 | |
|
281 | |
|
282 | |
|
283 | 0 | if (superClazz != null) { |
284 | 0 | operation = superClazz.getOperation(signature); |
285 | 0 | if (operation != null) { |
286 | 0 | addOperation(operation); |
287 | |
} |
288 | |
} |
289 | 0 | } |
290 | |
|
291 | |
|
292 | |
|
293 | |
|
294 | |
public List getOperations() { |
295 | 0 | return operations; |
296 | |
} |
297 | |
|
298 | |
|
299 | |
|
300 | |
|
301 | |
public ClazzOperation getOperation(String signature) { |
302 | 0 | return (ClazzOperation) operationMap.get(signature); |
303 | |
} |
304 | |
|
305 | |
|
306 | |
|
307 | |
|
308 | |
public List getInstanceFactories() { |
309 | 0 | if (instanceFactories == null) { |
310 | 0 | introspectInstanceFactories(); |
311 | |
} |
312 | 0 | return Collections.unmodifiableList(instanceFactories); |
313 | |
} |
314 | |
|
315 | |
|
316 | |
|
317 | |
|
318 | |
public ClazzInstanceFactory getInstanceFactory(String signature) { |
319 | 0 | if (instanceFactories == null) { |
320 | 0 | introspectInstanceFactories(); |
321 | |
} |
322 | |
|
323 | 0 | return (ClazzInstanceFactory) instanceFactoryMap.get(signature); |
324 | |
} |
325 | |
|
326 | |
public void addInstanceFactory(ClazzInstanceFactory factory) { |
327 | 0 | if (factory.getDeclaringClazz() != this) { |
328 | 0 | throw new BeanClazzConfigurationException( |
329 | |
"Instance factory belongs to a different clazz: " |
330 | |
+ factory.getDeclaringClazz().getName()); |
331 | |
} |
332 | |
|
333 | 0 | if (instanceFactories == null) { |
334 | 0 | introspectInstanceFactories(); |
335 | |
} |
336 | 0 | ClazzInstanceFactory oldFactory = |
337 | |
(ClazzInstanceFactory) instanceFactoryMap.get( |
338 | |
factory.getSignature()); |
339 | 0 | if (oldFactory != null) { |
340 | 0 | removeInstanceFactory(oldFactory); |
341 | |
} |
342 | 0 | instanceFactories.add(factory); |
343 | 0 | instanceFactoryMap.put(factory.getSignature(), factory); |
344 | 0 | fireInstanceFactoryAdded(factory); |
345 | 0 | } |
346 | |
|
347 | |
public void removeInstanceFactory(ClazzInstanceFactory factory) { |
348 | 0 | if (instanceFactories.remove(factory)) { |
349 | 0 | instanceFactoryMap.remove(factory.getSignature()); |
350 | 0 | fireInstanceFactoryRemoved(factory); |
351 | |
} |
352 | 0 | } |
353 | |
|
354 | |
|
355 | |
|
356 | |
|
357 | |
|
358 | |
|
359 | |
|
360 | |
|
361 | |
|
362 | |
private void introspectInstanceFactories() { |
363 | 0 | instanceFactories = new ArrayList(); |
364 | 0 | Class instanceClass = getInstanceClass(); |
365 | 0 | Constructor constructors[] = instanceClass.getConstructors(); |
366 | 0 | for (int i = 0; i < constructors.length; i++) { |
367 | 0 | Class[] parameterTypes = constructors[i].getParameterTypes(); |
368 | 0 | if (parameterTypes != null |
369 | |
&& parameterTypes.length >= 1 |
370 | |
&& Clazz.class.isAssignableFrom(parameterTypes[0])) { |
371 | 0 | addInstanceFactory( |
372 | |
new BeanClazzConstructorInstanceFactory( |
373 | |
this, |
374 | |
constructors[i])); |
375 | |
} |
376 | |
} |
377 | 0 | } |
378 | |
|
379 | 0 | private ClazzChangeListener listener = new ClazzChangeListener() { |
380 | |
public void propertyAdded(Clazz clazz, ClazzProperty property) { |
381 | 0 | if (propertyMap.get(property.getName()) == null) { |
382 | 0 | addProperty(property); |
383 | |
} |
384 | 0 | } |
385 | |
|
386 | |
public void propertyRemoved(Clazz clazz, ClazzProperty property) { |
387 | 0 | ClazzProperty declared = |
388 | |
(ClazzProperty) propertyMap.get(property.getName()); |
389 | 0 | if (declared != null && declared.equals(property)) { |
390 | 0 | removeProperty(property); |
391 | |
} |
392 | 0 | } |
393 | |
|
394 | |
public void operationAdded(Clazz clazz, ClazzOperation operation) { |
395 | 0 | if (operationMap.get(operation.getSignature()) == null) { |
396 | 0 | addOperation(operation); |
397 | |
} |
398 | 0 | } |
399 | |
|
400 | |
public void operationRemoved(Clazz clazz, ClazzOperation operation) { |
401 | 0 | ClazzOperation declared = |
402 | |
(ClazzOperation) operationMap.get(operation.getSignature()); |
403 | 0 | if (declared != null && declared.equals(operation)) { |
404 | 0 | removeOperation(operation); |
405 | |
} |
406 | 0 | } |
407 | |
|
408 | |
public void instanceFactoryAdded( |
409 | |
Clazz clazz, |
410 | |
ClazzInstanceFactory property) |
411 | |
{ |
412 | |
|
413 | 0 | } |
414 | |
|
415 | |
public void instanceFactoryRemoved( |
416 | |
Clazz clazz, |
417 | |
ClazzInstanceFactory property) |
418 | |
{ |
419 | |
|
420 | 0 | } |
421 | |
}; |
422 | |
} |