KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > beans > factory > xml > AbstractSimpleBeanDefinitionParser


1 /*
2  * Copyright 2002-2007 the original author or authors.
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
17 package org.springframework.beans.factory.xml;
18
19 import org.w3c.dom.Attr JavaDoc;
20 import org.w3c.dom.Element JavaDoc;
21 import org.w3c.dom.NamedNodeMap JavaDoc;
22
23 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
24 import org.springframework.core.Conventions;
25 import org.springframework.util.Assert;
26 import org.springframework.util.StringUtils;
27
28 /**
29  * Convenient base class for when there exists a one-to-one mapping
30  * between attribute names on the element that is to be parsed and
31  * the property names on the {@link Class} being configured.
32  *
33  * <p>Extend this parser class when you want to create a single
34  * bean definition from a relatively simple custom XML element. The
35  * resulting <code>BeanDefinition</code> will be automatically
36  * registered with the relevant
37  * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}.
38  *
39  * <p>An example will hopefully make the use of this particular parser
40  * class immediately clear. Consider the following class definition:
41  *
42  * <pre class="code">public class SimpleCache implements Cache {
43  *
44  * public void setName(String name) {...}
45  * public void setTimeout(int timeout) {...}
46  * public void setEvictionPolicy(EvictionPolicy policy) {...}
47  *
48  * // remaining class definition elided for clarity...
49  * }</pre>
50  *
51  * <p>Then let us assume the following XML tag has been defined to
52  * permit the easy configuration of instances of the above class;
53  *
54  * <pre class="code">&lt;caching:cache name="..." timeout="..." eviction-policy="..."/&gt;</pre>
55  *
56  * <p>All that is required of the Java developer tasked with writing
57  * the parser to parse the above XML tag into an actual
58  * <code>SimpleCache</code> bean definition is the following:
59  *
60  * <pre class="code">public class SimpleCacheBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {
61  *
62  * protected Class getBeanClass(Element element) {
63  * return SimpleCache.class;
64  * }
65  * }</pre>
66  *
67  * <p>Please note that the <code>AbstractSimpleBeanDefinitionParser</code>
68  * is limited to populating the created bean definition with property values.
69  * if you want to parse constructor arguments and nested elements from the
70  * supplied XML element, then you will have to implement the
71  * {@link #postProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.w3c.dom.Element)}
72  * method and do such parsing yourself, or (more likely) subclass the
73  * {@link AbstractSingleBeanDefinitionParser} or {@link AbstractBeanDefinitionParser}
74  * classes directly.
75  *
76  * <p>The process of actually registering the
77  * <code>SimpleCacheBeanDefinitionParser</code> with the Spring XML parsing
78  * infrastructure is described in the Spring Framework reference documentation
79  * (in one of the appendices).
80  *
81  * <p>For an example of this parser in action (so to speak), do look at
82  * the source code for the
83  * {@link org.springframework.beans.factory.xml.UtilNamespaceHandler.PropertiesBeanDefinitionParser};
84  * the observant (and even not so observant) reader will immediately notice that
85  * there is next to no code in the implementation. The
86  * <code>PropertiesBeanDefinitionParser</code> populates a
87  * {@link org.springframework.beans.factory.config.PropertiesFactoryBean}
88  * from an XML element that looks like this:
89  *
90  * <pre class="code">&lt;util:properties location="jdbc.properties"/&gt;</pre>
91  *
92  * <p>The observant reader will notice that the sole attribute on the
93  * <code>&lt;util:properties/&gt;</code> element matches the
94  * {@link org.springframework.beans.factory.config.PropertiesFactoryBean#setLocation(org.springframework.core.io.Resource)}
95  * method name on the <code>PropertiesFactoryBean</code> (the general
96  * usage thus illustrated holds true for any number of attributes).
97  * All that the <code>PropertiesBeanDefinitionParser</code> needs
98  * actually do is supply an implementation of the
99  * {@link #getBeanClass(org.w3c.dom.Element)} method to return the
100  * <code>PropertiesFactoryBean</code> type.
101  *
102  * @author Rob Harrop
103  * @author Rick Evans
104  * @author Juergen Hoeller
105  * @since 2.0
106  * @see Conventions#attributeNameToPropertyName(String)
107  */

108 public abstract class AbstractSimpleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
109
110     /**
111      * Parse the supplied {@link Element} and populate the supplied
112      * {@link BeanDefinitionBuilder} as required.
113      * <p>This implementation maps any attributes present on the
114      * supplied element to {@link org.springframework.beans.PropertyValue}
115      * instances, and
116      * {@link BeanDefinitionBuilder#addPropertyValue(String, Object) adds them}
117      * to the
118      * {@link org.springframework.beans.factory.config.BeanDefinition builder}.
119      * <p>The {@link #extractPropertyName(String)} method is used to
120      * reconcile the name of an attribute with the name of a JavaBean
121      * property.
122      * @param element the XML element being parsed
123      * @param builder used to define the <code>BeanDefinition</code>
124      * @see #extractPropertyName(String)
125      */

126     protected final void doParse(Element JavaDoc element, BeanDefinitionBuilder builder) {
127         NamedNodeMap JavaDoc attributes = element.getAttributes();
128         for (int x = 0; x < attributes.getLength(); x++) {
129             Attr JavaDoc attribute = (Attr JavaDoc) attributes.item(x);
130             String JavaDoc name = attribute.getLocalName();
131             if (isEligibleAttribute(name)) {
132                 String JavaDoc propertyName = extractPropertyName(name);
133                 Assert.state(StringUtils.hasText(propertyName),
134                         "Illegal property name returned from 'extractPropertyName(String)': cannot be null or empty.");
135                 builder.addPropertyValue(propertyName, attribute.getValue());
136             }
137         }
138         postProcess(builder, element);
139     }
140
141     /**
142      * Determine whether the given attribute is eligible for being
143      * turned into a corresponding bean property value.
144      * <p>The default implementation considers any attribute as eligible,
145      * except for the "id" attribute.
146      * @param attributeName the attribute name taken straight from the
147      * XML element being parsed (never <code>null</code>)
148      */

149     protected boolean isEligibleAttribute(String JavaDoc attributeName) {
150         return !ID_ATTRIBUTE.equals(attributeName);
151     }
152
153     /**
154      * Extract a JavaBean property name from the supplied attribute name.
155      * <p>The default implementation uses the
156      * {@link Conventions#attributeNameToPropertyName(String)}
157      * method to perform the extraction.
158      * <p>The name returned must obey the standard JavaBean property name
159      * conventions. For example for a class with a setter method
160      * '<code>setBingoHallFavourite(String)</code>', the name returned had
161      * better be '<code>bingoHallFavourite</code>' (with that exact casing).
162      * @param attributeName the attribute name taken straight from the
163      * XML element being parsed (never <code>null</code>)
164      * @return the extracted JavaBean property name (must never be <code>null</code>)
165      */

166     protected String JavaDoc extractPropertyName(String JavaDoc attributeName) {
167         return Conventions.attributeNameToPropertyName(attributeName);
168     }
169
170     /**
171      * Hook method that derived classes can implement to inspect/change a
172      * bean definition after parsing is complete.
173      * <p>The default implementation does nothing.
174      * @param beanDefinition the parsed (and probably totally defined) bean definition being built
175      * @param element the XML element that was the source of the bean definition's metadata
176      */

177     protected void postProcess(BeanDefinitionBuilder beanDefinition, Element JavaDoc element) {
178     }
179
180 }
181
Popular Tags