1:
43:
44: package ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57:
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66:
67:
71: public final class ModelBuilder {
72:
73:
74: private static ModelBuilder instance;
75:
76:
81: public static ModelBuilder getInstance() {
82: if (instance == null) {
83: instance = new ModelBuilder();
84: }
85: return instance;
86: }
87:
88:
89: private Properties handlerMapping;
90:
91:
94: private ModelBuilder() {
95: this.handlerMapping = new Properties();
96: }
97:
98:
103: public void addAttributeHandlers(final Properties p) {
104: this.handlerMapping.putAll(p);
105: }
106:
107:
117: public DescriptionModel buildModel(final SourceCollector c, DescriptionModel model) {
118:
119: Class[] classes = c.getClasses();
120:
121: if (model == null) {
122: model = new DescriptionModel();
123: }
124:
125: while (classes.length != 0) {
126: classes = fillModel(classes, model);
127: }
128:
129: fillSuperClasses(model);
130:
131:
132:
133:
134: final Class[] baseClasses = findElementTypes(model);
135:
136: final HashNMap classMap = new HashNMap();
137: for (int i = 0; i < baseClasses.length; i++) {
138:
139: final Class base = baseClasses[i];
140:
141: for (int j = 0; j < baseClasses.length; j++) {
142:
143: final Class child = baseClasses[j];
144: if (Modifier.isAbstract(child.getModifiers())) {
145: continue;
146: }
147: if (base.isAssignableFrom(child)) {
148: classMap.add(base, child);
149: }
150: }
151: }
152:
153:
154:
155:
156: final Iterator keys = classMap.keys();
157: while (keys.hasNext()) {
158: final Class base = (Class) keys.next();
159: final Class[] childs = (Class[]) classMap.toArray(base, new Class[0]);
160: if (childs.length < 2) {
161: continue;
162: }
163:
164: boolean isNew = false;
165: MultiplexMappingInfo mmi = model.getMappingModel().lookupMultiplexMapping(base);
166: final ArrayList typeInfoList;
167: if (mmi == null) {
168: mmi = new MultiplexMappingInfo(base);
169: typeInfoList = new ArrayList();
170: isNew = true;
171: }
172: else {
173: typeInfoList = new ArrayList(Arrays.asList(mmi.getChildClasses()));
174: }
175:
176: for (int i = 0; i < childs.length; i++) {
177:
178:
179: final TypeInfo typeInfo = new TypeInfo(childs[i].getName(), childs[i]);
180: if (!typeInfoList.contains(typeInfo)) {
181: typeInfoList.add(typeInfo);
182: }
183: }
184:
185: mmi.setChildClasses((TypeInfo[]) typeInfoList.toArray(new TypeInfo[0]));
186: if (isNew) {
187: model.getMappingModel().addMultiplexMapping(mmi);
188: }
189: }
190:
191:
192:
193:
194:
195: return model;
196: }
197:
198: private Class[] findElementTypes(final DescriptionModel model) {
199: final ArrayList baseClasses = new ArrayList();
200:
201: for (int i = 0; i < model.size(); i++) {
202: final ClassDescription cd = model.get(i);
203: if (!baseClasses.contains(cd.getObjectClass())) {
204: baseClasses.add(cd.getObjectClass());
205: }
206:
207: final PropertyInfo[] properties = cd.getProperties();
208: for (int p = 0; p < properties.length; p++) {
209:
210:
211: if (!properties[p].getPropertyType().equals(PropertyType.ELEMENT)) {
212: continue;
213: }
214: final Class type = properties[p].getType();
215: if (baseClasses.contains(type)) {
216: continue;
217: }
218:
219: if (Modifier.isFinal(type.getModifiers())) {
220: continue;
221: }
222: baseClasses.add(type);
223: }
224: }
225: return (Class[]) baseClasses.toArray(new Class[baseClasses.size()]);
226: }
227:
228:
235: private void fillSuperClasses(final DescriptionModel model) {
236:
237: for (int i = 0; i < model.size(); i++) {
238: final ClassDescription cd = model.get(i);
239: final Class parent = cd.getObjectClass().getSuperclass();
240: if (parent == null) {
241: continue;
242: }
243: final ClassDescription superCD = model.get(parent);
244: if (superCD != null) {
245: cd.setSuperClass(superCD.getObjectClass());
246: }
247: }
248: }
249:
250:
258: private Class[] fillModel(final Class[] classes, final DescriptionModel model) {
259:
260:
261:
262: final ArrayList superClasses = new ArrayList();
263: for (int i = 0; i < classes.length; i++) {
264:
265: Class superClass = classes[i].getSuperclass();
266: if (superClass != null) {
267: if (!Object.class.equals(superClass)
268: && !contains(classes, superClass)
269: && !superClasses.contains(superClass)) {
270: superClasses.add(superClass);
271: }
272: }
273: else {
274: superClass = Object.class;
275: }
276:
277: try {
278: final BeanInfo bi = Introspector.getBeanInfo(classes[i], superClass);
279: final ClassDescription parent = model.get(classes[i]);
280: final ClassDescription cd = createClassDescription(bi, parent);
281: if (cd != null) {
282: model.addClassDescription(cd);
283: }
284: }
285: catch (IntrospectionException ie) {
286:
287: }
288: }
289: return (Class[]) superClasses.toArray(new Class[0]);
290: }
291:
292:
300: private ClassDescription createClassDescription (final BeanInfo beanInfo, final ClassDescription parent) {
301: final PropertyDescriptor[] props = beanInfo.getPropertyDescriptors();
302: final ArrayList properties = new ArrayList();
303: for (int i = 0; i < props.length; i++) {
304: final PropertyDescriptor propertyDescriptor = props[i];
305: PropertyInfo pi;
306: if (parent != null) {
307: pi = parent.getProperty(propertyDescriptor.getName());
308: if (pi != null) {
309:
310:
311:
312: properties.add(pi);
313: continue;
314: }
315: }
316:
317: if (props[i] instanceof IndexedPropertyDescriptor) {
318:
319:
320:
321:
322:
323:
324:
325: }
326: else {
327: pi = createSimplePropertyInfo(props[i]);
328: if (pi != null) {
329: properties.add(pi);
330: }
331: }
332: }
333:
334: final PropertyInfo[] propArray = (PropertyInfo[])
335: properties.toArray(new PropertyInfo[properties.size()]);
336:
337: final ClassDescription cd;
338: if (parent != null) {
339: cd = parent;
340: }
341: else {
342: cd = new ClassDescription(beanInfo.getBeanDescriptor().getBeanClass());
343: cd.setDescription(beanInfo.getBeanDescriptor().getShortDescription());
344: }
345:
346: cd.setProperties(propArray);
347: return cd;
348: }
349:
350:
356: public static boolean isValidMethod(final Method method) {
357: if (method == null) {
358: return false;
359: }
360: if (!Modifier.isPublic(method.getModifiers())) {
361: return false;
362: }
363: return true;
364: }
365:
366:
373: public PropertyInfo createSimplePropertyInfo(final PropertyDescriptor pd) {
374:
375: final boolean readMethod = isValidMethod(pd.getReadMethod());
376: final boolean writeMethod = isValidMethod(pd.getWriteMethod());
377: if (!writeMethod || !readMethod) {
378:
379: return null;
380: }
381:
382: final PropertyInfo pi = new PropertyInfo(pd.getName(), pd.getPropertyType());
383: pi.setConstrained(pd.isConstrained());
384: pi.setDescription(pd.getShortDescription());
385: pi.setNullable(true);
386: pi.setPreserve(false);
387: pi.setReadMethodAvailable(readMethod);
388: pi.setWriteMethodAvailable(writeMethod);
389: pi.setXmlName(pd.getName());
390: if (isAttributeProperty(pd.getPropertyType())) {
391: pi.setPropertyType(PropertyType.ATTRIBUTE);
392: pi.setXmlHandler(getHandlerClass(pd.getPropertyType()));
393: }
394: else {
395: pi.setPropertyType(PropertyType.ELEMENT);
396: }
397: return pi;
398: }
399:
400:
408: private boolean isAttributeProperty(final Class c) {
409: if (BasicTypeSupport.isBasicDataType(c)) {
410: return true;
411: }
412: return this.handlerMapping.containsKey(c.getName());
413: }
414:
415:
422: private String getHandlerClass(final Class c) {
423: if (BasicTypeSupport.isBasicDataType(c)) {
424: final String handler = BasicTypeSupport.getHandlerClass(c);
425: if (handler != null) {
426: return handler;
427: }
428: }
429: return this.handlerMapping.getProperty(c.getName());
430: }
431:
432:
440: private boolean contains(final Class[] cAll, final Class c) {
441: for (int i = 0; i < cAll.length; i++) {
442: if (cAll[i].equals(c)) {
443: return true;
444: }
445: }
446: return false;
447: }
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459:
460:
461:
462:
463:
464:
465:
466:
467:
468:
469:
470:
471:
472:
473:
474:
475:
476:
477: }