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 }