KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > betwixt > io > read > BeanBindAction


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.betwixt.io.read;
17
18 import java.util.Map JavaDoc;
19
20 import org.apache.commons.betwixt.AttributeDescriptor;
21 import org.apache.commons.betwixt.ElementDescriptor;
22 import org.apache.commons.betwixt.TextDescriptor;
23 import org.apache.commons.betwixt.XMLBeanInfo;
24 import org.apache.commons.betwixt.expression.Updater;
25 import org.apache.commons.logging.Log;
26 import org.xml.sax.Attributes JavaDoc;
27
28 /**
29  * Action that creates and binds a new bean instance.
30  *
31  * @author <a HREF='http://jakarta.apache.org/'>Jakarta Commons Team</a>
32  * @version $Revision: 1.2 $
33  */

34 public class BeanBindAction extends MappingAction.Base {
35
36     /** Singleton instance */
37     public static final BeanBindAction INSTANCE = new BeanBindAction();
38
39     /**
40      * Begins a new element which is to be bound to a bean.
41      */

42     public MappingAction begin(
43         String JavaDoc namespace,
44         String JavaDoc name,
45         Attributes JavaDoc attributes,
46         ReadContext context)
47                     throws Exception JavaDoc {
48                         
49         Log log = context.getLog();
50
51         ElementDescriptor computedDescriptor = context.getCurrentDescriptor();
52
53         if (log.isTraceEnabled()) {
54             log.trace("Element Pushed: " + name);
55         }
56
57         // default to ignoring the current element
58
MappingAction action = MappingAction.EMPTY;
59
60         Object JavaDoc instance = null;
61         Class JavaDoc beanClass = null;
62         if (computedDescriptor == null) {
63             log.trace("No Descriptor");
64         } else {
65             beanClass = computedDescriptor.getSingularPropertyType();
66         }
67         // TODO: this is a bit of a workaround
68
// need to come up with a better way of doing maps
69
if (beanClass != null && !Map JavaDoc.class.isAssignableFrom(beanClass)) {
70
71             instance =
72                 createBean(
73                     namespace,
74                     name,
75                     attributes,
76                     computedDescriptor,
77                     context);
78                     
79             if (instance != null) {
80                 action = this;
81                 context.markClassMap(beanClass);
82
83                 if (log.isTraceEnabled()) {
84                     log.trace("Marked: " + beanClass);
85                 }
86
87                 context.pushBean(instance);
88
89                 // if we are a reference to a type we should lookup the original
90
// as this ElementDescriptor will be 'hollow'
91
// and have no child attributes/elements.
92
// XXX: this should probably be done by the NodeDescriptors...
93
ElementDescriptor typeDescriptor =
94                     getElementDescriptor(computedDescriptor, context);
95                 //ElementDescriptor typeDescriptor = descriptor;
96

97                 // iterate through all attributes
98
AttributeDescriptor[] attributeDescriptors =
99                     typeDescriptor.getAttributeDescriptors();
100                 context.populateAttributes(attributeDescriptors, attributes);
101
102                 if (log.isTraceEnabled()) {
103                     log.trace("Created bean " + instance);
104                 }
105
106                 // add bean for ID matching
107
if (context.getMapIDs()) {
108                     // XXX need to support custom ID attribute names
109
// XXX i have a feeling that the current mechanism might need to change
110
// XXX so i'm leaving this till later
111
String JavaDoc id = attributes.getValue("id");
112                     if (id != null) {
113                         context.putBean(id, instance);
114                     }
115                 }
116             }
117         }
118         return action;
119     }
120
121
122     public void body(String JavaDoc text, ReadContext context) throws Exception JavaDoc {
123         Log log = context.getLog();
124         // Take the first content descriptor
125
ElementDescriptor currentDescriptor = context.getCurrentDescriptor();
126         if (currentDescriptor == null) {
127             if (log.isTraceEnabled()) {
128                 log.trace("path descriptor is null:");
129             }
130         } else {
131             TextDescriptor bodyTextdescriptor =
132                 currentDescriptor.getPrimaryBodyTextDescriptor();
133             if (bodyTextdescriptor != null) {
134                 if (log.isTraceEnabled()) {
135                     log.trace("Setting mixed content for:");
136                     log.trace(bodyTextdescriptor);
137                 }
138                 Updater updater = bodyTextdescriptor.getUpdater();
139                 if (log.isTraceEnabled())
140                 {
141                     log.trace("Updating mixed content with:");
142                     log.trace(updater);
143                 }
144                 if (updater != null && text != null) {
145                     updater.update(context, text);
146                 }
147             }
148         }
149     }
150
151     public void end(ReadContext context) throws Exception JavaDoc {
152         // force any setters of the parent bean to be called for this new bean instance
153
Object JavaDoc instance = context.popBean();
154         update(context, instance);
155     }
156
157     private void update(ReadContext context, Object JavaDoc value) throws Exception JavaDoc {
158         Log log = context.getLog();
159
160         Updater updater = context.getCurrentUpdater();
161         
162         if ( updater == null ) {
163             if ( context.getLog().isTraceEnabled() ) {
164                 context.getLog().trace("No updater for " + context.getCurrentElement());
165             }
166         } else {
167             updater.update(context, value);
168         }
169
170         String JavaDoc poppedElement = context.popElement();
171     }
172
173
174
175
176     /**
177     * Factory method to create new bean instances
178     *
179     * @param namespace the namespace for the element
180     * @param name the local name
181     * @param attributes the <code>Attributes</code> used to match <code>ID/IDREF</code>
182     * @return the created bean
183     */

184     protected Object JavaDoc createBean(
185         String JavaDoc namespace,
186         String JavaDoc name,
187         Attributes JavaDoc attributes,
188         ElementDescriptor descriptor,
189         ReadContext context) {
190         // TODO: recycle element mappings
191
// Maybe should move the current mapping into the context
192
ElementMapping mapping = new ElementMapping();
193         Class JavaDoc beanClass = descriptor.getSingularPropertyType();
194         if (beanClass != null && beanClass.isArray()) {
195             beanClass = beanClass.getComponentType();
196         }
197
198         // TODO: beanClass can be deduced from descriptor
199
// so probably
200
mapping.setType(beanClass);
201         mapping.setNamespace(namespace);
202         mapping.setName(name);
203         mapping.setAttributes(attributes);
204         mapping.setDescriptor(descriptor);
205
206         Object JavaDoc newInstance =
207             context.getBeanCreationChain().create(mapping, context);
208
209         return newInstance;
210     }
211
212     /** Allows the navigation from a reference to a property object to the
213     * descriptor defining what the property is. i.e. doing the join from a reference
214     * to a type to lookup its descriptor.
215     * This could be done automatically by the NodeDescriptors.
216     * Refer to TODO.txt for more info.
217     *
218     * @param propertyDescriptor find descriptor for property object
219     * referenced by this descriptor
220     * @return descriptor for the singular property class type referenced.
221     */

222     ElementDescriptor getElementDescriptor(
223         ElementDescriptor propertyDescriptor,
224         ReadContext context) {
225         Log log = context.getLog();
226         Class JavaDoc beanClass = propertyDescriptor.getSingularPropertyType();
227         if (beanClass != null && !Map JavaDoc.class.isAssignableFrom(beanClass)) {
228             if (beanClass.isArray()) {
229                 beanClass = beanClass.getComponentType();
230             }
231             if (log.isTraceEnabled()) {
232                 log.trace("Filling descriptor for: " + beanClass);
233             }
234             try {
235                 XMLBeanInfo xmlInfo =
236                     context.getXMLIntrospector().introspect(beanClass);
237                 return xmlInfo.getElementDescriptor();
238
239             } catch (Exception JavaDoc e) {
240                 log.warn("Could not introspect class: " + beanClass, e);
241             }
242         }
243         // could not find a better descriptor so use the one we've got
244
return propertyDescriptor;
245     }
246
247 }
248
Popular Tags