KickJava   Java API By Example, From Geeks To Geeks.

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


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.Element JavaDoc;
20
21 import org.springframework.beans.factory.BeanDefinitionStoreException;
22 import org.springframework.beans.factory.config.BeanDefinition;
23 import org.springframework.beans.factory.config.BeanDefinitionHolder;
24 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
25 import org.springframework.beans.factory.support.AbstractBeanDefinition;
26 import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
27 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
28 import org.springframework.util.StringUtils;
29
30 /**
31  * Abstract {@link BeanDefinitionParser} implementation providing
32  * a number of convenience methods and a
33  * {@link AbstractBeanDefinitionParser#parseInternal template method}
34  * that subclasses must override to provide the actual parsing logic.
35  *
36  * <p>Use this {@link BeanDefinitionParser} implementation when you want
37  * to parse some arbitrarily complex XML into one or more
38  * {@link BeanDefinition BeanDefinitions}. If you just want to parse some
39  * XML into a single <code>BeanDefinition</code>, you may wish to consider
40  * the simpler convenience extensions of this class, namely
41  * {@link AbstractSingleBeanDefinitionParser} and
42  * {@link AbstractSimpleBeanDefinitionParser}.
43  *
44  * @author Rob Harrop
45  * @author Juergen Hoeller
46  * @author Rick Evans
47  * @since 2.0
48  */

49 public abstract class AbstractBeanDefinitionParser implements BeanDefinitionParser {
50
51     /** Constant for the id attribute */
52     public static final String JavaDoc ID_ATTRIBUTE = "id";
53
54
55     public final BeanDefinition parse(Element JavaDoc element, ParserContext parserContext) {
56         AbstractBeanDefinition definition = parseInternal(element, parserContext);
57         if (!parserContext.isNested()) {
58             try {
59                 String JavaDoc id = resolveId(element, definition, parserContext);
60                 if (!StringUtils.hasText(id)) {
61                     parserContext.getReaderContext().error(
62                             "Id is required for element '" + element.getLocalName() + "' when used as a top-level tag", element);
63                 }
64                 BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id);
65                 registerBeanDefinition(holder, parserContext.getRegistry());
66                 if (shouldFireEvents()) {
67                     BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
68                     postProcessComponentDefinition(componentDefinition);
69                     parserContext.registerComponent(componentDefinition);
70                 }
71             }
72             catch (BeanDefinitionStoreException ex) {
73                 parserContext.getReaderContext().error(ex.getMessage(), element);
74                 return null;
75             }
76         }
77         return definition;
78     }
79
80     /**
81      * Resolve the ID for the supplied {@link BeanDefinition}.
82      * <p>When using {@link #shouldGenerateId generation}, a name is generated automatically.
83      * Otherwise, the ID is extracted from the "id" attribute, potentially with a
84      * {@link #shouldGenerateIdAsFallback() fallback} to a generated id.
85      * @param element the element that the bean definition has been built from
86      * @param definition the bean definition to be registered
87      * @param parserContext the object encapsulating the current state of the parsing process;
88      * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
89      * @return the resolved id
90      * @throws BeanDefinitionStoreException if no unique name could be generated
91      * for the given bean definition
92      */

93     protected String JavaDoc resolveId(Element JavaDoc element, AbstractBeanDefinition definition, ParserContext parserContext)
94             throws BeanDefinitionStoreException {
95
96         if (shouldGenerateId()) {
97             return parserContext.getReaderContext().generateBeanName(definition);
98         }
99         else {
100             String JavaDoc id = element.getAttribute(ID_ATTRIBUTE);
101             if (!StringUtils.hasText(id) && shouldGenerateIdAsFallback()) {
102                 id = parserContext.getReaderContext().generateBeanName(definition);
103             }
104             return id;
105         }
106     }
107
108     /**
109      * Register the supplied {@link BeanDefinitionHolder bean} with the supplied
110      * {@link BeanDefinitionRegistry registry}.
111      * <p>Subclasses can override this method to control whether or not the supplied
112      * {@link BeanDefinitionHolder bean} is actually even registered, or to
113      * register even more beans.
114      * <p>The default implementation registers the supplied {@link BeanDefinitionHolder bean}
115      * with the supplied {@link BeanDefinitionRegistry registry} only if the <code>isNested</code>
116      * parameter is <code>false</code>, because one typically does not want inner beans
117      * to be registered as top level beans.
118      * @param definition the bean definition to be registered
119      * @param registry the registry that the bean is to be registered with
120      * @see BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry)
121      */

122     protected void registerBeanDefinition(BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
123         BeanDefinitionReaderUtils.registerBeanDefinition(definition, registry);
124     }
125
126
127     /**
128      * Central template method to actually parse the supplied {@link Element}
129      * into one or more {@link BeanDefinition BeanDefinitions}.
130      * @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions}
131      * @param parserContext the object encapsulating the current state of the parsing process;
132      * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
133      * @return the primary {@link BeanDefinition} resulting from the parsing of the supplied {@link Element}
134      * @see #parse(org.w3c.dom.Element, ParserContext)
135      * @see #postProcessComponentDefinition(org.springframework.beans.factory.parsing.BeanComponentDefinition)
136      */

137     protected abstract AbstractBeanDefinition parseInternal(Element JavaDoc element, ParserContext parserContext);
138
139     /**
140      * Should an ID be generated instead of read from the passed in {@link Element}?
141      * <p>Disabled by default; subclasses can override this to enable ID generation.
142      * Note that this flag is about <i>always</i> generating an ID; the parser
143      * won't even check for an "id" attribute in this case.
144      * @return whether the parser should always generate an id
145      */

146     protected boolean shouldGenerateId() {
147         return false;
148     }
149
150     /**
151      * Should an ID be generated instead if the passed in {@link Element} does not
152      * specify an "id" attribute explicitly?
153      * <p>Disabled by default; subclasses can override this to enable ID generation
154      * as fallback: The parser will first check for an "id" attribute in this case,
155      * only falling back to a generated ID if no value was specified.
156      * @return whether the parser should generate an id if no id was specified
157      */

158     protected boolean shouldGenerateIdAsFallback() {
159         return false;
160     }
161
162     /**
163      * Controls whether this parser is supposed to fire a
164      * {@link org.springframework.beans.factory.parsing.BeanComponentDefinition}
165      * event after parsing the bean definition.
166      * <p>This implementation returns <code>true</code> by default; that is,
167      * an event will be fired when a bean definition has been completely parsed.
168      * Override this to return <code>false</code> in order to suppress the event.
169      * @return <code>true</code> in order to fire a component registration event
170      * after parsing the bean definition; <code>false</code> to suppress the event
171      * @see #postProcessComponentDefinition
172      * @see org.springframework.beans.factory.parsing.ReaderContext#fireComponentRegistered
173      */

174     protected boolean shouldFireEvents() {
175         return true;
176     }
177
178     /**
179      * Hook method called after the primary parsing of a
180      * {@link BeanComponentDefinition} but before the
181      * {@link BeanComponentDefinition} has been registered with a
182      * {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}.
183      * <p>Derived classes can override this method to supply any custom logic that
184      * is to be executed after all the parsing is finished.
185      * <p>The default implementation is a no-op.
186      * @param componentDefinition the {@link BeanComponentDefinition} that is to be processed
187      */

188     protected void postProcessComponentDefinition(BeanComponentDefinition componentDefinition) {
189     }
190
191 }
192
Popular Tags