1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.betwixt.io.read;
17
18 import org.apache.commons.betwixt.ElementDescriptor;
19 import org.apache.commons.betwixt.registry.PolymorphicReferenceResolver;
20 import org.apache.commons.logging.Log;
21
22 /***
23 * Group of factory methods for <code>ChainedBeanCreator</code>'s.
24 * The standard implementations used by Betwixt are present here.
25 *
26 * @author Robert Burrell Donkin
27 * @since 0.5
28 */
29 public class ChainedBeanCreatorFactory {
30
31 /*** Singleton instance for creating derived beans */
32 private static final ChainedBeanCreator derivedBeanCreator
33 = new ChainedBeanCreator() {
34 public Object create(
35 ElementMapping elementMapping,
36 ReadContext context,
37 BeanCreationChain chain) {
38
39 String className
40 = elementMapping
41 .getAttributes().getValue( context.getClassNameAttribute() );
42 if ( className != null ) {
43 try {
44
45 ClassLoader classLoader = context.getClassLoader();
46 if ( classLoader == null ) {
47 context.getLog().warn(
48 "Could not create derived instance: read context classloader not set." );
49 }
50 Class clazz = classLoader.loadClass( className );
51 return clazz.newInstance();
52
53 } catch (Exception e) {
54
55 context.getLog().warn( "Could not create instance of type: " + className );
56 context.getLog().debug( "Create new instance failed: ", e );
57 return null;
58 }
59
60 } else {
61
62 return chain.create( elementMapping, context );
63 }
64 }
65 };
66
67 /***
68 * Creates a <code>ChainedBeanCreator</code> that constructs derived beans.
69 * These have their classname set by an xml attribute.
70 * @return <code>ChainedBeanCreator</code> that implements Derived beans logic, not null
71 */
72 public static final ChainedBeanCreator createDerivedBeanCreator() {
73 return derivedBeanCreator;
74 }
75
76 /*** Singleton instance that creates beans based on type */
77 private static final ChainedBeanCreator elementTypeBeanCreator
78 = new ChainedBeanCreator() {
79 public Object create(
80 ElementMapping element,
81 ReadContext context,
82 BeanCreationChain chain) {
83
84 Log log = context.getLog();
85 Class theClass = null;
86
87 ElementDescriptor descriptor = element.getDescriptor();
88 if ( descriptor != null ) {
89
90 if (descriptor.isPolymorphic()) {
91 theClass = context.getXMLIntrospector().getPolymorphicReferenceResolver()
92 .resolveType(element, context);
93 }
94
95 if (theClass == null)
96 {
97
98 theClass = descriptor.getImplementationClass();
99 }
100 }
101
102 if ( theClass == null ) {
103
104 theClass = element.getType();
105 }
106
107 if ( log.isTraceEnabled() ) {
108 log.trace(
109 "Creating instance of class " + theClass.getName()
110 + " for element " + element.getName());
111 }
112
113 try {
114
115 return theClass.newInstance();
116
117 } catch (Exception e) {
118
119 context.getLog().warn(
120 "Could not create instance of type: " + theClass.getName() );
121 context.getLog().debug( "Create new instance failed: ", e );
122 return null;
123 }
124 }
125 };
126
127 /***
128 * Creates a <code>ChainedBeanCreator</code> that constructs beans based on element type.
129 * @return <code>ChainedBeanCreator</code> that implements load by type beans logic, not null
130 */
131 public static final ChainedBeanCreator createElementTypeBeanCreator() {
132 return elementTypeBeanCreator;
133 }
134
135 /*** Singleton instance that creates beans based on IDREF */
136 private static final ChainedBeanCreator idRefBeanCreator
137 = new ChainedBeanCreator() {
138 public Object create(
139 ElementMapping elementMapping,
140 ReadContext context,
141 BeanCreationChain chain) {
142 if ( context.getMapIDs() ) {
143 String idref = elementMapping.getAttributes().getValue( "idref" );
144 if ( idref != null ) {
145
146
147
148
149 context.getLog().trace( "Found IDREF" );
150 Object bean = context.getBean( idref );
151 if ( bean != null ) {
152 if ( context.getLog().isTraceEnabled() ) {
153 context.getLog().trace( "Matched bean " + bean );
154 }
155 return bean;
156 }
157 context.getLog().trace( "No match found" );
158 }
159 }
160 return chain.create( elementMapping, context );
161 }
162 };
163
164 /***
165 * Creates a <code>ChainedBeanCreator</code> that finds existing beans based on their IDREF.
166 * @return <code>ChainedBeanCreator</code> that implements IDREF beans logic, not null
167 */
168 public static final ChainedBeanCreator createIDREFBeanCreator() {
169 return idRefBeanCreator;
170 }
171 }