001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 package org.kuali.kfs.sys.spring.datadictionary;
017
018 import org.apache.log4j.Logger;
019 import org.springframework.beans.factory.support.AbstractBeanDefinition;
020 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
021 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
022 import org.springframework.beans.factory.xml.ParserContext;
023 import org.springframework.util.StringUtils;
024 import org.w3c.dom.Element;
025 import org.w3c.dom.Node;
026 import org.w3c.dom.NodeList;
027
028 public abstract class KualiBeanDefinitionParserBase extends AbstractBeanDefinitionParser {
029
030 private static Logger LOG = Logger.getLogger(KualiBeanDefinitionParserBase.class);
031
032 protected void parseEmbeddedPropertyElements(Element element, BeanDefinitionBuilder bean) {
033 NodeList children = element.getChildNodes();
034 for ( int i = 0; i < children.getLength(); i++ ) {
035 Node child = children.item(i);
036 if ( child.getLocalName() != null && child.getLocalName().equals("property") ) {
037 Element propertyElement = (Element)child;
038 String propName = propertyElement.getAttribute("name");
039 String propValue = propertyElement.getAttribute("value");
040 if ( propValue != null ) {
041 bean.addPropertyValue(propName, propValue);
042 } else if ( propertyElement.getAttribute("ref") != null ) {
043 bean.addPropertyReference(propName, propertyElement.getAttribute("ref") );
044 }
045 }
046 }
047 }
048
049 protected void handleAbstractAttribute( Element element, BeanDefinitionBuilder bean) {
050 String abstractStr = element.getAttribute("abstract");
051
052 if ( StringUtils.hasText(abstractStr) ) {
053 bean.setAbstract( Boolean.valueOf(abstractStr) );
054 }
055 }
056
057 /* The below copied from AbstractSingleBeanDefinitionParser and modified to allow for parent beans to be handled. */
058 /**
059 * Creates a {@link BeanDefinitionBuilder} instance for the
060 * {@link #getBeanClass bean Class} and passes it to the
061 * {@link #doParse} strategy method.
062 * @param element the element that is to be parsed into a single BeanDefinition
063 * @param parserContext the object encapsulating the current state of the parsing process
064 * @return the BeanDefinition resulting from the parsing of the supplied {@link Element}
065 * @throws IllegalStateException if the bean {@link Class} returned from
066 * {@link #getBeanClass(org.w3c.dom.Element)} is <code>null</code>
067 * @see #doParse
068 */
069 @SuppressWarnings("unchecked")
070 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
071 BeanDefinitionBuilder builder = null;
072
073 String parent = element.getAttribute("parent");
074 String beanClass = element.getAttribute("class");
075 if ( StringUtils.hasText(beanClass) ) {
076 try {
077 builder = BeanDefinitionBuilder.rootBeanDefinition(Class.forName(beanClass));
078 } catch (Exception ex) {
079 LOG.fatal( "Unable to resolve class given in class element of a " + element.getLocalName() + " element with id " + element.getAttribute("id"), ex );
080 throw new RuntimeException(ex);
081 }
082 } else if ( StringUtils.hasText(parent)) {
083 builder = BeanDefinitionBuilder.childBeanDefinition(parent);
084 } else if ( getBeanClass(element) != null ) {
085 builder = BeanDefinitionBuilder.rootBeanDefinition(getBeanClass(element));
086 } else {
087 builder = BeanDefinitionBuilder.childBeanDefinition(getBaseBeanTypeParent(element));
088 }
089 builder.setSource(parserContext.extractSource(element));
090 if (parserContext.isNested()) {
091 // Inner bean definition must receive same singleton status as containing bean.
092 builder.setSingleton(parserContext.getContainingBeanDefinition().isSingleton());
093 }
094 if (parserContext.isDefaultLazyInit()) {
095 // Default-lazy-init applies to custom bean definitions as well.
096 builder.setLazyInit(true);
097 }
098 doParse(element, parserContext, builder);
099 return builder.getBeanDefinition();
100 }
101
102 /**
103 * Parse the supplied {@link Element} and populate the supplied
104 * {@link BeanDefinitionBuilder} as required.
105 * <p>The default implementation delegates to the <code>doParse</code>
106 * version without ParserContext argument.
107 * @param element the XML element being parsed
108 * @param parserContext the object encapsulating the current state of the parsing process
109 * @param builder used to define the <code>BeanDefinition</code>
110 * @see #doParse(Element, BeanDefinitionBuilder)
111 */
112 protected abstract void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder);
113
114 protected abstract String getBaseBeanTypeParent( Element element );
115
116 protected Class getBeanClass( Element element ) {
117 return null;
118 }
119 }