001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.beans.factory.xml;
018:
019: import org.w3c.dom.Element;
020:
021: import org.springframework.beans.factory.support.AbstractBeanDefinition;
022: import org.springframework.beans.factory.support.BeanDefinitionBuilder;
023: import org.springframework.util.Assert;
024:
025: /**
026: * Base class for those {@link BeanDefinitionParser} implementations that
027: * need to parse and define just a <i>single</i> <code>BeanDefinition</code>.
028: *
029: * <p>Extend this parser class when you want to create a single bean definition
030: * from an arbitrarily complex XML element. You may wish to consider extending
031: * the {@link AbstractSimpleBeanDefinitionParser} when you want to create a
032: * single bean definition from a relatively simple custom XML element.
033: *
034: * <p>The resulting <code>BeanDefinition</code> will be automatically registered
035: * with the {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}.
036: * Your job simply is to {@link #doParse parse} the custom XML {@link Element}
037: * into a single <code>BeanDefinition</code>.
038: *
039: * @author Rob Harrop
040: * @author Juergen Hoeller
041: * @author Rick Evans
042: * @since 2.0
043: * @see #getBeanClass
044: * @see #getBeanClassName
045: * @see #doParse
046: */
047: public abstract class AbstractSingleBeanDefinitionParser extends
048: AbstractBeanDefinitionParser {
049:
050: /**
051: * Creates a {@link BeanDefinitionBuilder} instance for the
052: * {@link #getBeanClass bean Class} and passes it to the
053: * {@link #doParse} strategy method.
054: * @param element the element that is to be parsed into a single BeanDefinition
055: * @param parserContext the object encapsulating the current state of the parsing process
056: * @return the BeanDefinition resulting from the parsing of the supplied {@link Element}
057: * @throws IllegalStateException if the bean {@link Class} returned from
058: * {@link #getBeanClass(org.w3c.dom.Element)} is <code>null</code>
059: * @see #doParse
060: */
061: protected final AbstractBeanDefinition parseInternal(
062: Element element, ParserContext parserContext) {
063: BeanDefinitionBuilder builder = null;
064: Class beanClass = getBeanClass(element);
065: if (beanClass != null) {
066: builder = BeanDefinitionBuilder
067: .rootBeanDefinition(beanClass);
068: } else {
069: String beanClassName = getBeanClassName(element);
070: Assert
071: .state(
072: beanClassName != null,
073: "Either 'getBeanClass' or 'getBeanClassName' must be overridden and return a non-null value");
074: builder = BeanDefinitionBuilder
075: .rootBeanDefinition(beanClassName);
076: }
077: builder.setSource(parserContext.extractSource(element));
078: if (parserContext.isNested()) {
079: // Inner bean definition must receive same singleton status as containing bean.
080: builder.setSingleton(parserContext
081: .getContainingBeanDefinition().isSingleton());
082: }
083: if (parserContext.isDefaultLazyInit()) {
084: // Default-lazy-init applies to custom bean definitions as well.
085: builder.setLazyInit(true);
086: }
087: doParse(element, parserContext, builder);
088: return builder.getBeanDefinition();
089: }
090:
091: /**
092: * Determine the bean class corresponding to the supplied {@link Element}.
093: * <p>Note that, for application classes, it is generally preferable to
094: * override {@link #getBeanClassName} instead, in order to avoid a direct
095: * dependence on the bean implementation class. The BeanDefinitionParser
096: * and its NamespaceHandler can be used within an IDE plugin then, even
097: * if the application classes are not available on the plugin's classpath.
098: * @param element the <code>Element</code> that is being parsed
099: * @return the {@link Class} of the bean that is being defined via parsing
100: * the supplied <code>Element</code>
101: * @see #getBeanClassName
102: */
103: protected Class getBeanClass(Element element) {
104: return null;
105: }
106:
107: /**
108: * Determine the bean class name corresponding to the supplied {@link Element}.
109: * @param element the <code>Element</code> that is being parsed
110: * @return the class name of the bean that is being defined via parsing
111: * the supplied <code>Element</code>
112: * @see #getBeanClass
113: */
114: protected String getBeanClassName(Element element) {
115: return null;
116: }
117:
118: /**
119: * Parse the supplied {@link Element} and populate the supplied
120: * {@link BeanDefinitionBuilder} as required.
121: * <p>The default implementation delegates to the <code>doParse</code>
122: * version without ParserContext argument.
123: * @param element the XML element being parsed
124: * @param parserContext the object encapsulating the current state of the parsing process
125: * @param builder used to define the <code>BeanDefinition</code>
126: * @see #doParse(Element, BeanDefinitionBuilder)
127: */
128: protected void doParse(Element element,
129: ParserContext parserContext, BeanDefinitionBuilder builder) {
130: doParse(element, builder);
131: }
132:
133: /**
134: * Parse the supplied {@link Element} and populate the supplied
135: * {@link BeanDefinitionBuilder} as required.
136: * <p>The default implementation does nothing.
137: * @param element the XML element being parsed
138: * @param builder used to define the <code>BeanDefinition</code>
139: */
140: protected void doParse(Element element,
141: BeanDefinitionBuilder builder) {
142: }
143:
144: }
|