diff --git a/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java b/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java index 12305827..25b7dd6f 100644 --- a/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java +++ b/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java @@ -88,12 +88,7 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle if (!StringUtils.hasText(conversionService)) { BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder .genericBeanDefinition(FACES_CONVERSION_SERVICE_CLASS_NAME); - conversionService = context.getReaderContext().generateBeanName( - conversionServiceBuilder.getRawBeanDefinition()); - conversionServiceBuilder.getRawBeanDefinition().setSource(context.extractSource(element)); - conversionServiceBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - context.registerBeanComponent(new BeanComponentDefinition(conversionServiceBuilder.getBeanDefinition(), - conversionService)); + conversionService = registerInfrastructureComponent(element, context, conversionServiceBuilder); } definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService); } @@ -103,12 +98,7 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle if (!StringUtils.hasText(viewFactoryCreator)) { BeanDefinitionBuilder viewFactoryCreatorBuilder = BeanDefinitionBuilder .genericBeanDefinition(JSF_VIEW_FACTORY_CREATOR_CLASS_NAME); - viewFactoryCreator = context.getReaderContext().generateBeanName( - viewFactoryCreatorBuilder.getRawBeanDefinition()); - viewFactoryCreatorBuilder.getRawBeanDefinition().setSource(context.extractSource(element)); - viewFactoryCreatorBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - context.registerBeanComponent(new BeanComponentDefinition(viewFactoryCreatorBuilder.getBeanDefinition(), - viewFactoryCreator)); + viewFactoryCreator = registerInfrastructureComponent(element, context, viewFactoryCreatorBuilder); } definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator); } @@ -137,12 +127,7 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle expressionParserBuilder.addConstructorArgValue(expressionFactoryBuilder.getBeanDefinition()); expressionParserBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService); - expressionParser = context.getReaderContext().generateBeanName( - expressionParserBuilder.getRawBeanDefinition()); - expressionParserBuilder.getRawBeanDefinition().setSource(context.extractSource(element)); - expressionParserBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - context.registerBeanComponent(new BeanComponentDefinition(expressionParserBuilder.getBeanDefinition(), - expressionParser)); + expressionParser = registerInfrastructureComponent(element, context, expressionParserBuilder); } else if (enableManagedBeans) { context.getReaderContext().error( @@ -153,16 +138,26 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle } - private String getConversionService(BeanDefinitionBuilder definitionBuilder) { - RuntimeBeanReference conversionServiceReference = (RuntimeBeanReference) definitionBuilder.getBeanDefinition() - .getPropertyValues().getPropertyValue(CONVERSION_SERVICE_PROPERTY).getValue(); - return conversionServiceReference.getBeanName(); - } - private void parseDevelopment(Element element, BeanDefinitionBuilder definitionBuilder) { String development = element.getAttribute(DEVELOPMENT_ATTR); if (StringUtils.hasText(development)) { definitionBuilder.addPropertyValue(DEVELOPMENT_PROPERTY, development); } } + + private String getConversionService(BeanDefinitionBuilder definitionBuilder) { + RuntimeBeanReference conversionServiceReference = (RuntimeBeanReference) definitionBuilder.getBeanDefinition() + .getPropertyValues().getPropertyValue(CONVERSION_SERVICE_PROPERTY).getValue(); + return conversionServiceReference.getBeanName(); + } + + private String registerInfrastructureComponent(Element element, ParserContext context, + BeanDefinitionBuilder componentBuilder) { + String beanName = context.getReaderContext().generateBeanName(componentBuilder.getRawBeanDefinition()); + componentBuilder.getRawBeanDefinition().setSource(context.extractSource(element)); + componentBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + context.registerBeanComponent(new BeanComponentDefinition(componentBuilder.getBeanDefinition(), + beanName)); + return beanName; + } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java index 204149cd..13aea516 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java @@ -15,16 +15,15 @@ */ package org.springframework.webflow.config; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.parsing.CompositeComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.convert.service.DefaultConversionService; +import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; -import org.springframework.webflow.engine.builder.support.FlowBuilderServices; -import org.springframework.webflow.expression.DefaultExpressionParserFactory; -import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator; import org.w3c.dom.Element; /** @@ -34,65 +33,95 @@ import org.w3c.dom.Element; */ class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - protected Class getBeanClass(Element element) { - return FlowBuilderServices.class; + // --------------------------- Full qualified class names ----------------------- // + private static final String DEFAULT_EXPRESSION_PARSER_FACTORY_CLASS_NAME = "org.springframework.webflow.expression.DefaultExpressionParserFactory"; + private static final String DEFAULT_CONVERSION_SERVICE_CLASS_NAME = "org.springframework.binding.convert.service.DefaultConversionService"; + private static final String FLOW_BUILDER_SERVICES_CLASS_NAME = "org.springframework.webflow.engine.builder.support.FlowBuilderServices"; + private static final String MVC_VIEW_FACTORY_CREATOR_CLASS_NAME = "org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"; + + // --------------------------- XML Config Attributes ----------------------- // + private static final String CONVERSION_SERVICE_ATTR = "conversion-service"; + private static final String DEVELOPMENT_ATTR = "development"; + private static final String EXPRESSION_PARSER_ATTR = "expression-parser"; + private static final String VIEW_FACTORY_CREATOR_ATTR = "view-factory-creator"; + + // --------------------------- Bean Configuration Properties --------------------- // + private static final String CONVERSION_SERVICE_PROPERTY = "conversionService"; + private static final String DEVELOPMENT_PROPERTY = "development"; + private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser"; + private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator"; + + protected String getBeanClassName(Element element) { + return FLOW_BUILDER_SERVICES_CLASS_NAME; } - protected void doParse(Element element, BeanDefinitionBuilder builder) { - parseConversionService(element, builder); - parseExpressionParser(element, builder); - parseViewFactoryCreator(element, builder); + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + + CompositeComponentDefinition componentDefinition = new CompositeComponentDefinition(element.getLocalName(), + parserContext.extractSource(element)); + parserContext.pushContainingComponent(componentDefinition); + + parseConversionService(element, parserContext, builder); + parseExpressionParser(element, parserContext, builder); + parseViewFactoryCreator(element, parserContext, builder); parseDevelopment(element, builder); + + parserContext.popAndRegisterContainingComponent(); } - private void parseConversionService(Element element, BeanDefinitionBuilder definitionBuilder) { - String conversionService = element.getAttribute("conversion-service"); - if (StringUtils.hasText(conversionService)) { - definitionBuilder.addPropertyReference("conversionService", conversionService); - } else { - definitionBuilder.addPropertyValue("conversionService", new DefaultConversionService()); + private void parseConversionService(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) { + String conversionService = element.getAttribute(CONVERSION_SERVICE_ATTR); + if (!StringUtils.hasText(conversionService)) { + BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder + .genericBeanDefinition(DEFAULT_CONVERSION_SERVICE_CLASS_NAME); + conversionService = registerInfrastructureComponent(element, context, conversionServiceBuilder); } + definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService); } - private void parseExpressionParser(Element element, BeanDefinitionBuilder definitionBuilder) { - String expressionParser = element.getAttribute("expression-parser"); - if (StringUtils.hasText(expressionParser)) { - definitionBuilder.addPropertyReference("expressionParser", expressionParser); - } else { - Object value = getConversionServiceValue(definitionBuilder); - if (value instanceof RuntimeBeanReference) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(DefaultExpressionParserFactory.class); - builder.setFactoryMethod("getExpressionParser"); - builder.addConstructorArgValue(value); - definitionBuilder.addPropertyValue("expressionParser", builder.getBeanDefinition()); - } else { - ConversionService conversionService = (ConversionService) value; - definitionBuilder.addPropertyValue("expressionParser", DefaultExpressionParserFactory - .getExpressionParser(conversionService)); - } + private void parseExpressionParser(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) { + String expressionParser = element.getAttribute(EXPRESSION_PARSER_ATTR); + if (!StringUtils.hasText(expressionParser)) { + String conversionService = getConversionService(definitionBuilder); + BeanDefinitionBuilder expressionParserBuilder = BeanDefinitionBuilder + .genericBeanDefinition(DEFAULT_EXPRESSION_PARSER_FACTORY_CLASS_NAME); + expressionParserBuilder.setFactoryMethod("getExpressionParser"); + expressionParserBuilder.addConstructorArgReference(conversionService); + expressionParser = registerInfrastructureComponent(element, context, expressionParserBuilder); } + definitionBuilder.addPropertyReference(EXPRESSION_PARSER_PROPERTY, expressionParser); } - private Object getConversionServiceValue(BeanDefinitionBuilder definitionBuilder) { - return definitionBuilder.getBeanDefinition().getPropertyValues().getPropertyValue("conversionService") - .getValue(); - } - - private void parseViewFactoryCreator(Element element, BeanDefinitionBuilder definitionBuilder) { - String viewFactoryCreator = element.getAttribute("view-factory-creator"); - if (StringUtils.hasText(viewFactoryCreator)) { - definitionBuilder.addPropertyReference("viewFactoryCreator", viewFactoryCreator); - } else { - definitionBuilder.addPropertyValue("viewFactoryCreator", BeanDefinitionBuilder.genericBeanDefinition( - MvcViewFactoryCreator.class).getBeanDefinition()); + private void parseViewFactoryCreator(Element element, ParserContext context, BeanDefinitionBuilder definitionBuilder) { + String viewFactoryCreator = element.getAttribute(VIEW_FACTORY_CREATOR_ATTR); + if (!StringUtils.hasText(viewFactoryCreator)) { + BeanDefinitionBuilder viewFactoryCreatorBuilder = BeanDefinitionBuilder + .genericBeanDefinition(MVC_VIEW_FACTORY_CREATOR_CLASS_NAME); + viewFactoryCreator = registerInfrastructureComponent(element, context, viewFactoryCreatorBuilder); } + definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator); } private void parseDevelopment(Element element, BeanDefinitionBuilder definitionBuilder) { - String development = element.getAttribute("development"); + String development = element.getAttribute(DEVELOPMENT_ATTR); if (StringUtils.hasText(development)) { - definitionBuilder.addPropertyValue("development", development); + definitionBuilder.addPropertyValue(DEVELOPMENT_PROPERTY, development); } } + + private String getConversionService(BeanDefinitionBuilder definitionBuilder) { + RuntimeBeanReference conversionServiceReference = (RuntimeBeanReference) definitionBuilder.getBeanDefinition() + .getPropertyValues().getPropertyValue(CONVERSION_SERVICE_PROPERTY).getValue(); + return conversionServiceReference.getBeanName(); + } + + private String registerInfrastructureComponent(Element element, ParserContext context, + BeanDefinitionBuilder componentBuilder) { + String beanName = context.getReaderContext().generateBeanName(componentBuilder.getRawBeanDefinition()); + componentBuilder.getRawBeanDefinition().setSource(context.extractSource(element)); + componentBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + context.registerBeanComponent(new BeanComponentDefinition(componentBuilder.getBeanDefinition(), + beanName)); + return beanName; + } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java index 5b9dbb20..95967bc6 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java @@ -1,62 +1,64 @@ -/* - * Copyright 2004-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.webflow.config; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.ManagedMap; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; - -/** - * {@link BeanDefinitionParser} for the <flow-execution-listeners> tag. - * - * @author Ben Hale - */ -class FlowExecutionListenerLoaderBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - - protected Class getBeanClass(Element element) { - return FlowExecutionListenerLoaderFactoryBean.class; - } - - protected void doParse(Element element, BeanDefinitionBuilder definitionBuilder) { - List listenerElements = DomUtils.getChildElementsByTagName(element, "listener"); - definitionBuilder.addPropertyValue("listeners", parseListenersWithCriteria(listenerElements)); - } - - /** - * Creates a map of listeners with their associated criteria. - * @param listeners the list of listener elements from the bean definition - * @return a map containing keys that are references to given listeners and values of string that represent the - * criteria - */ - private Map parseListenersWithCriteria(List listeners) { - Map listenersWithCriteria = new ManagedMap(listeners.size()); - for (Iterator i = listeners.iterator(); i.hasNext();) { - Element listenerElement = (Element) i.next(); - RuntimeBeanReference ref = new RuntimeBeanReference(listenerElement.getAttribute("ref")); - String criteria = listenerElement.getAttribute("criteria"); - listenersWithCriteria.put(ref, criteria); - } - return listenersWithCriteria; - } +/* + * Copyright 2004-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.webflow.config; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedMap; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; + +/** + * {@link BeanDefinitionParser} for the <flow-execution-listeners> tag. + * + * @author Ben Hale + */ +class FlowExecutionListenerLoaderBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + + private static final String FLOW_EXECUTION_LISTENER_LOADER_FACTORY_BEAN_CLASS_NAME = "org.springframework.webflow.config.FlowExecutionListenerLoaderFactoryBean"; + + protected String getBeanClassName(Element element) { + return FLOW_EXECUTION_LISTENER_LOADER_FACTORY_BEAN_CLASS_NAME; + } + + protected void doParse(Element element, BeanDefinitionBuilder definitionBuilder) { + List listenerElements = DomUtils.getChildElementsByTagName(element, "listener"); + definitionBuilder.addPropertyValue("listeners", parseListenersWithCriteria(listenerElements)); + } + + /** + * Creates a map of listeners with their associated criteria. + * @param listeners the list of listener elements from the bean definition + * @return a map containing keys that are references to given listeners and values of string that represent the + * criteria + */ + private Map parseListenersWithCriteria(List listeners) { + Map listenersWithCriteria = new ManagedMap(listeners.size()); + for (Iterator i = listeners.iterator(); i.hasNext();) { + Element listenerElement = (Element) i.next(); + RuntimeBeanReference ref = new RuntimeBeanReference(listenerElement.getAttribute("ref")); + String criteria = listenerElement.getAttribute("criteria"); + listenersWithCriteria.put(ref, criteria); + } + return listenersWithCriteria; + } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java index 53c5bee0..d2f1a9a0 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java @@ -35,8 +35,10 @@ import org.w3c.dom.Element; */ class FlowExecutorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - protected Class getBeanClass(Element element) { - return FlowExecutorFactoryBean.class; + private static final String FLOW_EXECUTOR_FACTORY_BEAN_CLASS_NAME = "org.springframework.webflow.config.FlowExecutorFactoryBean"; + + protected String getBeanClassName(Element element) { + return FLOW_EXECUTOR_FACTORY_BEAN_CLASS_NAME; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java index c532de19..294da31f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java @@ -1,139 +1,174 @@ -/* - * Copyright 2004-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.webflow.config; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.convert.service.DefaultConversionService; -import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; -import org.springframework.webflow.engine.builder.support.FlowBuilderServices; -import org.springframework.webflow.expression.DefaultExpressionParserFactory; -import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator; -import org.w3c.dom.Element; - -/** - * {@link BeanDefinitionParser} for the flow <flow-registry> tag. - * - * @author Keith Donald - */ -class FlowRegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - - protected Class getBeanClass(Element element) { - return FlowRegistryFactoryBean.class; - } - - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) { - String flowBuilderServices = element.getAttribute("flow-builder-services"); - if (StringUtils.hasText(flowBuilderServices)) { - definitionBuilder.addPropertyReference("flowBuilderServices", flowBuilderServices); - } else { - definitionBuilder.addPropertyValue("flowBuilderServices", createDefaultFlowBuilderServices(parserContext)); - } - String parent = element.getAttribute("parent"); - if (StringUtils.hasText(parent)) { - definitionBuilder.addPropertyReference("parent", parent); - } - definitionBuilder.addPropertyValue("flowLocations", parseLocations(element)); - definitionBuilder.addPropertyValue("flowLocationPatterns", parseLocationPatterns(element)); - definitionBuilder.addPropertyValue("flowBuilders", parseFlowBuilders(element)); - } - - private List parseLocations(Element element) { - List locationElements = DomUtils.getChildElementsByTagName(element, "flow-location"); - if (locationElements.isEmpty()) { - return Collections.EMPTY_LIST; - } - List locations = new ArrayList(locationElements.size()); - for (Iterator it = locationElements.iterator(); it.hasNext();) { - Element locationElement = (Element) it.next(); - String id = locationElement.getAttribute("id"); - String path = locationElement.getAttribute("path"); - locations.add(new FlowLocation(id, path, parseAttributes(locationElement))); - } - return locations; - } - - private List parseLocationPatterns(Element element) { - List locationPatternElements = DomUtils.getChildElementsByTagName(element, "flow-location-pattern"); - if (locationPatternElements.isEmpty()) { - return Collections.EMPTY_LIST; - } - List locationPatterns = new ArrayList(locationPatternElements.size()); - for (Iterator it = locationPatternElements.iterator(); it.hasNext();) { - Element locationPatternElement = (Element) it.next(); - String value = locationPatternElement.getAttribute("value"); - locationPatterns.add(value); - } - return locationPatterns; - } - - private Set parseAttributes(Element element) { - Element definitionAttributesElement = DomUtils.getChildElementByTagName(element, "flow-definition-attributes"); - if (definitionAttributesElement != null) { - List attributeElements = DomUtils.getChildElementsByTagName(definitionAttributesElement, "attribute"); - HashSet attributes = new HashSet(attributeElements.size()); - for (Iterator it = attributeElements.iterator(); it.hasNext();) { - Element attributeElement = (Element) it.next(); - String name = attributeElement.getAttribute("name"); - String value = attributeElement.getAttribute("value"); - String type = attributeElement.getAttribute("type"); - attributes.add(new FlowElementAttribute(name, value, type)); - } - return attributes; - } else { - return null; - } - } - - private List parseFlowBuilders(Element element) { - List builderElements = DomUtils.getChildElementsByTagName(element, "flow-builder"); - if (builderElements.isEmpty()) { - return Collections.EMPTY_LIST; - } - List builders = new ArrayList(builderElements.size()); - for (Iterator it = builderElements.iterator(); it.hasNext();) { - Element builderElement = (Element) it.next(); - String id = builderElement.getAttribute("id"); - String className = builderElement.getAttribute("class"); - builders.add(new FlowBuilderInfo(id, className, parseAttributes(builderElement))); - } - return builders; - } - - private BeanDefinition createDefaultFlowBuilderServices(ParserContext context) { - BeanDefinitionBuilder defaultBuilder = BeanDefinitionBuilder.genericBeanDefinition(FlowBuilderServices.class); - ConversionService conversionService = new DefaultConversionService(); - defaultBuilder.addPropertyValue("conversionService", conversionService); - defaultBuilder.addPropertyValue("expressionParser", DefaultExpressionParserFactory - .getExpressionParser(conversionService)); - defaultBuilder.addPropertyValue("viewFactoryCreator", BeanDefinitionBuilder.genericBeanDefinition( - MvcViewFactoryCreator.class).getBeanDefinition()); - return defaultBuilder.getBeanDefinition(); - } - +/* + * Copyright 2004-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.webflow.config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.parsing.CompositeComponentDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; + +/** + * {@link BeanDefinitionParser} for the flow <flow-registry> tag. + * + * @author Keith Donald + */ +class FlowRegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { + + // --------------------------- Full qualified class names ----------------------- // + private static final String DEFAULT_CONVERSION_SERVICE_CLASS_NAME = "org.springframework.binding.convert.service.DefaultConversionService"; + private static final String DEFAULT_EXPRESSION_PARSER_FACTORY_CLASS_NAME = "org.springframework.webflow.expression.DefaultExpressionParserFactory"; + private static final String FLOW_BUILDER_SERVICES_CLASS_NAME = "org.springframework.webflow.engine.builder.support.FlowBuilderServices"; + private static final String FLOW_REGISTRY_FACTORY_BEAN_CLASS_NAME = "org.springframework.webflow.config.FlowRegistryFactoryBean"; + private static final String MVC_VIEW_FACTORY_CREATOR_CLASS_NAME = "org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"; + + protected String getBeanClassName(Element element) { + return FLOW_REGISTRY_FACTORY_BEAN_CLASS_NAME; + } + + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) { + CompositeComponentDefinition componentDefinition = new CompositeComponentDefinition(element.getLocalName(), + parserContext.extractSource(element)); + parserContext.pushContainingComponent(componentDefinition); + + parseFlowBuilderServices(element, parserContext, definitionBuilder); + + String parent = element.getAttribute("parent"); + if (StringUtils.hasText(parent)) { + definitionBuilder.addPropertyReference("parent", parent); + } + definitionBuilder.addPropertyValue("flowLocations", parseLocations(element)); + definitionBuilder.addPropertyValue("flowLocationPatterns", parseLocationPatterns(element)); + definitionBuilder.addPropertyValue("flowBuilders", parseFlowBuilders(element)); + + parserContext.popAndRegisterContainingComponent(); + } + + private List parseLocations(Element element) { + List locationElements = DomUtils.getChildElementsByTagName(element, "flow-location"); + if (locationElements.isEmpty()) { + return Collections.EMPTY_LIST; + } + List locations = new ArrayList(locationElements.size()); + for (Iterator it = locationElements.iterator(); it.hasNext();) { + Element locationElement = (Element) it.next(); + String id = locationElement.getAttribute("id"); + String path = locationElement.getAttribute("path"); + locations.add(new FlowLocation(id, path, parseAttributes(locationElement))); + } + return locations; + } + + private List parseLocationPatterns(Element element) { + List locationPatternElements = DomUtils.getChildElementsByTagName(element, "flow-location-pattern"); + if (locationPatternElements.isEmpty()) { + return Collections.EMPTY_LIST; + } + List locationPatterns = new ArrayList(locationPatternElements.size()); + for (Iterator it = locationPatternElements.iterator(); it.hasNext();) { + Element locationPatternElement = (Element) it.next(); + String value = locationPatternElement.getAttribute("value"); + locationPatterns.add(value); + } + return locationPatterns; + } + + private Set parseAttributes(Element element) { + Element definitionAttributesElement = DomUtils.getChildElementByTagName(element, "flow-definition-attributes"); + if (definitionAttributesElement != null) { + List attributeElements = DomUtils.getChildElementsByTagName(definitionAttributesElement, "attribute"); + HashSet attributes = new HashSet(attributeElements.size()); + for (Iterator it = attributeElements.iterator(); it.hasNext();) { + Element attributeElement = (Element) it.next(); + String name = attributeElement.getAttribute("name"); + String value = attributeElement.getAttribute("value"); + String type = attributeElement.getAttribute("type"); + attributes.add(new FlowElementAttribute(name, value, type)); + } + return attributes; + } else { + return null; + } + } + + private List parseFlowBuilders(Element element) { + List builderElements = DomUtils.getChildElementsByTagName(element, "flow-builder"); + if (builderElements.isEmpty()) { + return Collections.EMPTY_LIST; + } + List builders = new ArrayList(builderElements.size()); + for (Iterator it = builderElements.iterator(); it.hasNext();) { + Element builderElement = (Element) it.next(); + String id = builderElement.getAttribute("id"); + String className = builderElement.getAttribute("class"); + builders.add(new FlowBuilderInfo(id, className, parseAttributes(builderElement))); + } + return builders; + } + + private void parseFlowBuilderServices(Element element, ParserContext context, + BeanDefinitionBuilder definitionBuilder) { + String flowBuilderServices = element.getAttribute("flow-builder-services"); + if (!StringUtils.hasText(flowBuilderServices)) { + + BeanDefinitionBuilder flowBuilderServicesBuilder = BeanDefinitionBuilder + .genericBeanDefinition(FLOW_BUILDER_SERVICES_CLASS_NAME); + + BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder + .genericBeanDefinition(DEFAULT_CONVERSION_SERVICE_CLASS_NAME); + String conversionService = registerInfrastructureComponent(element, context, conversionServiceBuilder); + flowBuilderServicesBuilder.addPropertyReference("conversionService", conversionService); + + BeanDefinitionBuilder expressionParserBuilder = BeanDefinitionBuilder + .genericBeanDefinition(DEFAULT_EXPRESSION_PARSER_FACTORY_CLASS_NAME); + expressionParserBuilder.setFactoryMethod("getExpressionParser"); + expressionParserBuilder.addConstructorArgReference(conversionService); + String expressionParser = registerInfrastructureComponent(element, context, expressionParserBuilder); + flowBuilderServicesBuilder.addPropertyReference("expressionParser", expressionParser); + + BeanDefinitionBuilder viewFactoryCreatorBuilder = BeanDefinitionBuilder + .genericBeanDefinition(MVC_VIEW_FACTORY_CREATOR_CLASS_NAME); + String viewFactoryCreator = registerInfrastructureComponent(element, context, viewFactoryCreatorBuilder); + flowBuilderServicesBuilder.addPropertyReference("viewFactoryCreator", viewFactoryCreator); + + flowBuilderServices = registerInfrastructureComponent(element, context, flowBuilderServicesBuilder); + } + definitionBuilder.addPropertyReference("flowBuilderServices", flowBuilderServices); + } + + private String registerInfrastructureComponent(Element element, ParserContext context, + BeanDefinitionBuilder viewFactoryCreatorBuilder) { + String beanName = context.getReaderContext().generateBeanName(viewFactoryCreatorBuilder.getRawBeanDefinition()); + viewFactoryCreatorBuilder.getRawBeanDefinition().setSource(context.extractSource(element)); + viewFactoryCreatorBuilder.getRawBeanDefinition().setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + context.registerBeanComponent(new BeanComponentDefinition(viewFactoryCreatorBuilder.getBeanDefinition(), + beanName)); + return beanName; + } + } \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java index bae4060a..e787ee2c 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java @@ -1,12 +1,19 @@ package org.springframework.webflow.config; +import java.util.Iterator; +import java.util.Map; + import junit.framework.TestCase; +import org.springframework.binding.convert.service.DefaultConversionService; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.webflow.definition.FlowDefinition; import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException; import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; import org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException; +import org.springframework.webflow.engine.builder.support.FlowBuilderServices; +import org.springframework.webflow.expression.el.WebFlowELExpressionParser; +import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator; public class FlowRegistryBeanDefinitionParserTests extends TestCase { private ClassPathXmlApplicationContext context; @@ -48,6 +55,21 @@ public class FlowRegistryBeanDefinitionParserTests extends TestCase { assertEquals(new Integer(2), foo3.getAttributes().get("bar")); } + public void testDefaultFlowBuilderServices() { + Map flowBuilderServicesBeans = context.getBeansOfType(FlowBuilderServices.class); + assertTrue(flowBuilderServicesBeans.size() > 0); + + Iterator i = flowBuilderServicesBeans.values().iterator(); + while (i.hasNext()) { + FlowBuilderServices builderServices = (FlowBuilderServices) i.next(); + assertNotNull(builderServices); + assertTrue(builderServices.getExpressionParser() instanceof WebFlowELExpressionParser); + assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator); + assertTrue(builderServices.getConversionService() instanceof DefaultConversionService); + assertFalse(builderServices.getDevelopment()); + } + } + public void testNoSuchFlow() { try { registry.getFlowDefinition("not there");