1:
42:
43: package ;
44:
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52:
53:
57: public final class GenericObjectFactory {
58:
59:
60: private final ConstructorDefinition[] constructorDefinitions;
61:
62:
63: private final PropertyDefinition[] propertyDefinitions;
64:
65:
66: private final LookupDefinition[] lookupDefinitions;
67:
68:
69: private final AttributeDefinition[] attributeDefinitions;
70:
71:
72: private final String[] orderedPropertyNames;
73:
74:
75: private final HashMap propertyInfos;
76:
77:
78: private final HashMap propertyValues;
79:
80:
81: private final Class baseClass;
82:
83:
84: private final String registerName;
85:
86:
100: public GenericObjectFactory(final Class c,
101: final String registerName,
102: final ConstructorDefinition[] constructors,
103: final PropertyDefinition[] propertyDefinitions,
104: final LookupDefinition[] lookupDefinitions,
105: final AttributeDefinition[] attributeDefinitions,
106: final String[] orderedPropertyNames)
107: throws ObjectDescriptionException {
108:
109: if (c == null) {
110: throw new NullPointerException("BaseClass cannot be null.");
111: }
112: this.baseClass = c;
113: this.registerName = registerName;
114:
115: this.propertyInfos = new HashMap();
116: this.propertyValues = new HashMap();
117:
118: this.constructorDefinitions = constructors;
119: this.propertyDefinitions = propertyDefinitions;
120: this.lookupDefinitions = lookupDefinitions;
121: this.attributeDefinitions = attributeDefinitions;
122: this.orderedPropertyNames = orderedPropertyNames;
123:
124: try {
125: final BeanInfo chartBeaninfo = Introspector.getBeanInfo(c, Object.class);
126: final PropertyDescriptor[] pd = chartBeaninfo.getPropertyDescriptors();
127: for (int i = 0; i < pd.length; i++) {
128: this.propertyInfos.put(pd[i].getName(), pd[i]);
129: }
130: }
131: catch (IntrospectionException ioe) {
132: throw new ObjectDescriptionException(
133: "This is an ugly solution right now ... dirty hack attack"
134: );
135: }
136: }
137:
138:
143: private GenericObjectFactory (final GenericObjectFactory factory) {
144: this.baseClass = factory.baseClass;
145: this.propertyValues = new HashMap();
146: this.orderedPropertyNames = factory.orderedPropertyNames;
147: this.constructorDefinitions = factory.constructorDefinitions;
148: this.propertyDefinitions = factory.propertyDefinitions;
149: this.attributeDefinitions = factory.attributeDefinitions;
150: this.propertyInfos = factory.propertyInfos;
151: this.registerName = factory.registerName;
152: this.lookupDefinitions = factory.lookupDefinitions;
153: }
154:
155:
160: public GenericObjectFactory getInstance () {
161: return new GenericObjectFactory(this);
162: }
163:
164:
169: public String getRegisterName() {
170: return this.registerName;
171: }
172:
173:
180: private PropertyDescriptor getPropertyDescriptor(final String propertyName) {
181: return (PropertyDescriptor) this.propertyInfos.get(propertyName);
182: }
183:
184:
193: public Class getTypeForTagName(final String tagName) throws ObjectDescriptionException {
194: final PropertyDefinition pdef = getPropertyDefinitionByTagName(tagName);
195: final PropertyDescriptor pdescr = getPropertyDescriptor(pdef.getPropertyName());
196: if (pdescr == null) {
197: throw new ObjectDescriptionException("Invalid Definition: " + pdef.getPropertyName());
198: }
199: return pdescr.getPropertyType();
200: }
201:
202:
209: public boolean isPropertyDefinition (final String propertyName) {
210: for (int i = 0; i < this.propertyDefinitions.length; i++) {
211: final PropertyDefinition pdef = this.propertyDefinitions[i];
212: if (pdef.getPropertyName().equals(propertyName)) {
213: return true;
214: }
215: }
216: return false;
217: }
218:
219:
228: public PropertyDefinition getPropertyDefinitionByPropertyName(final String propertyName)
229: throws ObjectDescriptionException {
230: for (int i = 0; i < this.propertyDefinitions.length; i++) {
231: final PropertyDefinition pdef = this.propertyDefinitions[i];
232: if (pdef.getPropertyName().equals(propertyName)) {
233: return pdef;
234: }
235: }
236: throw new ObjectDescriptionException(
237: "This property is not defined for this kind of object. : " + propertyName
238: );
239: }
240:
241:
250: public PropertyDefinition getPropertyDefinitionByTagName(final String tagName)
251: throws ObjectDescriptionException {
252: for (int i = 0; i < this.propertyDefinitions.length; i++) {
253: final PropertyDefinition pdef = this.propertyDefinitions[i];
254: if (pdef.getElementName().equals(tagName)) {
255: return pdef;
256: }
257: }
258: throw new ObjectDescriptionException(
259: "This tag is not defined for this kind of object. : " + tagName
260: );
261: }
262:
263:
268: public ConstructorDefinition[] getConstructorDefinitions() {
269: return this.constructorDefinitions;
270: }
271:
272:
277: public AttributeDefinition[] getAttributeDefinitions() {
278: return this.attributeDefinitions;
279: }
280:
281:
286: public PropertyDefinition[] getPropertyDefinitions() {
287: return this.propertyDefinitions;
288: }
289:
290:
295: public String[] getOrderedPropertyNames() {
296: return this.orderedPropertyNames;
297: }
298:
299:
304: public LookupDefinition[] getLookupDefinitions() {
305: return this.lookupDefinitions;
306: }
307:
308:
315: public Object getProperty(final String name) {
316: return this.propertyValues.get(name);
317: }
318:
319:
326: public Object createObject() throws ObjectDescriptionException {
327: final Class[] cArgs = new Class[this.constructorDefinitions.length];
328: final Object[] oArgs = new Object[this.constructorDefinitions.length];
329: for (int i = 0; i < cArgs.length; i++) {
330: final ConstructorDefinition cDef = this.constructorDefinitions[i];
331: cArgs[i] = cDef.getType();
332: if (cDef.isNull()) {
333: oArgs[i] = null;
334: }
335: else {
336: oArgs[i] = getProperty(cDef.getPropertyName());
337: }
338: }
339:
340: try {
341: final Constructor constr = this.baseClass.getConstructor(cArgs);
342: final Object o = constr.newInstance(oArgs);
343: return o;
344: }
345: catch (Exception e) {
346: throw new ObjectDescriptionException("Ugh! Constructor made a buuuh!", e);
347: }
348: }
349:
350:
358: public void setProperty(final String propertyName, final Object value)
359: throws ObjectDescriptionException {
360: final PropertyDescriptor pdesc = getPropertyDescriptor(propertyName);
361: if (pdesc == null) {
362: throw new ObjectDescriptionException("Unknown property " + propertyName);
363: }
364:
365: if (!isAssignableOrPrimitive(pdesc.getPropertyType(), value.getClass())) {
366: throw new ObjectDescriptionException(
367: "Invalid value: " + pdesc.getPropertyType() + " vs. " + value.getClass()
368: );
369: }
370:
371: this.propertyValues.put(propertyName, value);
372: }
373:
374:
382: private boolean isAssignableOrPrimitive(final Class baseType, final Class valueType) {
383: if (BasicTypeSupport.isBasicDataType(baseType)) {
384: return true;
385: }
386:
387: return baseType.isAssignableFrom(valueType);
388: }
389:
390:
397: private boolean isConstructorProperty(final String propertyName) {
398: for (int i = 0; i < this.constructorDefinitions.length; i++) {
399: final ConstructorDefinition cDef = this.constructorDefinitions[i];
400: if (propertyName.equals(cDef.getPropertyName())) {
401: return true;
402: }
403: }
404: return false;
405: }
406:
407:
414: public void writeObjectProperties(final Object object) throws ObjectDescriptionException {
415:
416: for (int i = 0; i < this.orderedPropertyNames.length; i++) {
417: try {
418: final String name = this.orderedPropertyNames[i];
419: if (isConstructorProperty(name)) {
420: continue;
421: }
422: final Object value = getProperty(name);
423: if (value == null) {
424:
425: continue;
426: }
427: final PropertyDescriptor pdescr = getPropertyDescriptor(name);
428: final Method setter = pdescr.getWriteMethod();
429: setter.invoke(object, new Object[]{value});
430: }
431: catch (Exception e) {
432: throw new ObjectDescriptionException(
433: "Failed to set properties." + getBaseClass(), e
434: );
435: }
436: }
437: }
438:
439:
446: public void readProperties(final Object object) throws ObjectDescriptionException {
447:
448: for (int i = 0; i < this.orderedPropertyNames.length; i++) {
449: try {
450: final String name = this.orderedPropertyNames[i];
451: final PropertyDescriptor pdescr = getPropertyDescriptor(name);
452: if (pdescr == null) {
453: throw new IllegalStateException("No property defined: " + name);
454: }
455: final Method setter = pdescr.getReadMethod();
456: final Object value = setter.invoke(object, new Object[0]);
457: if (value == null) {
458:
459: continue;
460: }
461: setProperty(name, value);
462: }
463: catch (Exception e) {
464: throw new ObjectDescriptionException("Failed to set properties.", e);
465: }
466: }
467: }
468:
469:
474: public Class getBaseClass() {
475: return this.baseClass;
476: }
477:
478: }