Refactoring per Christian's recommendations for tooling support.

This commit is contained in:
Jeremy Grelle
2008-09-19 20:36:34 +00:00
parent ea81534a64
commit 662075607d
6 changed files with 358 additions and 273 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 <code>&lt;flow-execution-listeners&gt;</code> 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 <code>&lt;flow-execution-listeners&gt;</code> 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;
}
}

View File

@@ -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) {

View File

@@ -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 <code>&lt;flow-registry&gt;</code> 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 <code>&lt;flow-registry&gt;</code> 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;
}
}

View File

@@ -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");