diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java index 2437efc6..0e8e4834 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java @@ -15,16 +15,25 @@ */ package org.springframework.webflow.config; -import java.util.ArrayList; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Set; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser; -import org.springframework.util.StringUtils; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternUtils; import org.springframework.util.xml.DomUtils; -import org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.engine.builder.FlowRegistryFactoryBean; import org.w3c.dom.Element; /** @@ -32,40 +41,73 @@ import org.w3c.dom.Element; * * @author Ben Hale */ -class RegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - - // elements and attributes +class RegistryBeanDefinitionParser extends AbstractBeanDefinitionParser { + // elements private static final String LOCATION_ELEMENT = "location"; - // properties + private static final String NAMESPACE_ELEMENT = "namespace"; - private static final String FLOW_LOCATIONS_PROPERTY = "flowLocations"; + // attributes + private static final String ID_ATTRIBUTE = "id"; + + private static final String NAME_ATTRIBUTE = "name"; private static final String PATH_ATTRIBUTE = "path"; - protected Class getBeanClass(Element element) { - return XmlFlowRegistryFactoryBean.class; + // Properties + private static final String XML_NAMESPACE_FLOW_MAPPINGS_PROPERTY = "xmlNamespaceFlowMappings"; + + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder + .rootBeanDefinition(FlowRegistryFactoryBean.class); + definitionBuilder.setSource(parserContext.extractSource(element)); + parseXml(element, definitionBuilder, parserContext); + return definitionBuilder.getBeanDefinition(); } - protected void doParse(Element element, BeanDefinitionBuilder definitionBuilder) { - List locationElements = DomUtils.getChildElementsByTagName(element, LOCATION_ELEMENT); - List locations = getLocations(locationElements); - definitionBuilder.addPropertyValue(FLOW_LOCATIONS_PROPERTY, locations.toArray(new String[locations.size()])); + public void parseXml(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext parserContext) { + Map xmlNamespaceFlowMappings = new HashMap(); + xmlNamespaceFlowMappings.put("", parseXmlElements( + DomUtils.getChildElementsByTagName(element, LOCATION_ELEMENT), parserContext)); + List namespaceElements = DomUtils.getChildElementsByTagName(element, NAMESPACE_ELEMENT); + for (Iterator it = namespaceElements.iterator(); it.hasNext();) { + Element namespaceElement = (Element) it.next(); + String namespace = namespaceElement.getAttribute(NAME_ATTRIBUTE); + xmlNamespaceFlowMappings.put(namespace, parseXmlElements(DomUtils.getChildElementsByTagName( + namespaceElement, LOCATION_ELEMENT), parserContext)); + } + definitionBuilder.addPropertyValue(XML_NAMESPACE_FLOW_MAPPINGS_PROPERTY, xmlNamespaceFlowMappings); } - /** - * Parse location definitions from given list of location elements. - */ - private List getLocations(List locationElements) { - List locations = new ArrayList(locationElements.size()); - for (Iterator i = locationElements.iterator(); i.hasNext();) { - Element locationElement = (Element) i.next(); - String path = locationElement.getAttribute(PATH_ATTRIBUTE); - if (StringUtils.hasText(path)) { - locations.add(path); + private Set parseXmlElements(List locationElements, ParserContext parserContext) { + ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(parserContext + .getReaderContext().getResourceLoader()); + Set resources = new HashSet(); + for (Iterator it = locationElements.iterator(); it.hasNext();) { + Element locationElement = (Element) it.next(); + try { + Resource[] locations = resolver.getResources(locationElement.getAttribute(PATH_ATTRIBUTE)); + if (locationElement.hasAttribute(ID_ATTRIBUTE)) { + if (locations.length != 1) { + parserContext.getReaderContext().error( + "The 'path' attribute of the 'location' element must point to a single value " + + "flow definition if an id has been specified", locationElement); + } else { + resources.add(new FlowDefinitionResource(locationElement.getAttribute(ID_ATTRIBUTE), + locations[0])); + } + } else { + for (int i = 0; i < locations.length; i++) { + resources.add(new FlowDefinitionResource(locations[i])); + } + } + } catch (IOException e) { + parserContext.getReaderContext().error( + "The 'path' attribute of the 'location' element must point to a valid flow definition " + + "or definitions", locationElement); } } - return locations; + return resources; } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd b/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd index 7c4d8560..74d8ecfa 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd @@ -20,17 +20,17 @@ Provides an easy way to configure a flow executor and an XML flow definition reg - - - - - - - - + + + + + + + + @@ -52,7 +52,7 @@ A flow registry is used by a flow executor at runtime to launch new executions o - + /WEB-INF/flows/**/*-flow.xml +]]> + + + + + + + +Classes must be declared using a fully qualified path name such as +
+	com.interface21.SellItemFlow
+
+]]> +
+
+
+ + + + +Entities must be declared using a fully qualified path name such as +
+	com.interface21.Account
+
+]]> +
+
+
+ + + + @@ -78,12 +119,96 @@ Individual paths such as: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Individual paths such as: +
+	/WEB-INF/flows/orderitem-flow.xml
+
+... are supported as well as wildcard paths such as: +
+	/WEB-INF/flows/**/*-flow.xml
+
+]]> +
+
+
+ + + + +Classes must be declared using a fully qualified path name such as +
+	com.interface21.SellItemFlow
+
+]]> +
+
+
+
+ + + + diff --git a/spring-webflow/src/main/java/org/springframework/webflow/core/collection/AttributeMap.java b/spring-webflow/src/main/java/org/springframework/webflow/core/collection/AttributeMap.java index 17a3bd9a..5d26ca8f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/core/collection/AttributeMap.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/core/collection/AttributeMap.java @@ -38,7 +38,7 @@ public interface AttributeMap extends MapAdaptable { /** * Returns the size of this map. - * @return the nubmer of entries in the map + * @return the number of entries in the map */ public int size(); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/AbstractFlowDefinitionRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/AbstractFlowDefinitionRegistryFactoryBean.java deleted file mode 100644 index f4435e40..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/AbstractFlowDefinitionRegistryFactoryBean.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2004-2007 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.definition.registry; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; - -/** - * A base class for factory beans that create populated flow definition registries. Subclasses should override the - * {@link #doPopulate(FlowDefinitionRegistry)} method to perform the registry population logic, typically delegating to - * a {@link FlowDefinitionRegistrar} strategy to perform the population. - * - * @author Keith Donald - */ -public abstract class AbstractFlowDefinitionRegistryFactoryBean implements FactoryBean, InitializingBean { - - /** - * The registry to register flow definitions in. - */ - private FlowDefinitionRegistry registry = createFlowDefinitionRegistry(); - - /** - * Sets the parent registry of the registry constructed by this factory bean. - *

- * A child registry will delegate to its parent if it cannot fulfill a request to locate a flow definition itself. - * @param parent the parent flow definition registry - */ - public void setParent(FlowDefinitionRegistry parent) { - registry.setParent(parent); - } - - // implementing InitializingBean - - public final void afterPropertiesSet() throws Exception { - init(); - doPopulate(registry); - } - - // implementing FactoryBean - - public Class getObjectType() { - return FlowDefinitionRegistry.class; - } - - public boolean isSingleton() { - return true; - } - - public Object getObject() throws Exception { - // the registry is populated by the time this is called - return getRegistry(); - } - - /** - * Returns the flow definition registry constructed by the factory bean. - */ - public FlowDefinitionRegistry getRegistry() { - return registry; - } - - // subclassing hooks - - /** - * Create the flow definition registry to be populated in {@link #doPopulate(FlowDefinitionRegistry)}. Subclasses - * can override this method if they want to use a custom flow definition registry implementation. - */ - protected FlowDefinitionRegistry createFlowDefinitionRegistry() { - return new FlowDefinitionRegistryImpl(); - } - - /** - * Template method subclasses may override to perform factory bean initialization logic before registry population. - * Will be called before {@link #doPopulate(FlowDefinitionRegistry)}. The default implementation is empty. - */ - protected void init() { - } - - /** - * Template method subclasses must override to perform registry population. - * @param registry the flow definition registry to populate - */ - protected abstract void doPopulate(FlowDefinitionRegistry registry); - -} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java index 8397d189..4ae093b5 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java @@ -15,13 +15,15 @@ */ package org.springframework.webflow.definition.registry; -import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; import org.springframework.core.io.Resource; import org.springframework.core.style.ToStringCreator; +import org.springframework.webflow.engine.builder.FlowServiceLocator; /** * A flow definition registrar that populates a flow definition registry from flow definitions defined within @@ -30,167 +32,139 @@ import org.springframework.core.style.ToStringCreator; *

* Concrete subclasses are expected to derive from this class to provide knowledge about a particular kind of definition * format by implementing the abstract template methods in this class. - *

- * By default, when configuring the {@link #setLocations(Resource[]) locations} property, flow definitions at those - * locations will be assigned a registry identifier equal to the filename of the underlying definition resource, minus - * the filename extension. For example, a XML-based flow definition defined in the file "flow1.xml" will be identified - * as "flow1" when registered in a registry. - *

- * For full control over the assignment of flow identifiers and flow properties, configure formal - * {@link org.springframework.webflow.definition.registry.FlowDefinitionResource} instances using the - * {@link #setResources(FlowDefinitionResource[] resources)} property. * * @see org.springframework.webflow.definition.registry.FlowDefinitionResource * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistry * * @author Keith Donald + * @author Ben Hale */ public abstract class ExternalizedFlowDefinitionRegistrar implements FlowDefinitionRegistrar { /** - * File locations of externalized flow definition resources to load. A set of {@link Resource}} objects. + * The locator of services needed by flow definitions. */ - private Set locations = new HashSet(); + private FlowServiceLocator flowServiceLocator; /** - * A set of formal externalized flow definitions to load. A set of {@link FlowDefinitionResource} objects. + * A set of mappings between a namespace and a set of externalized flow definitions. A map of Strings to Sets + * containing {@link FlowDefinitionResource}s */ - private Set resources = new HashSet(); + private Map namespaceFlowMappings; /** - * Sets the locations (file paths) pointing to externalized flow definitions. - *

- * Flows registered from this set will be automatically assigned an id based on the filename of the flow resource. - * @param locations the resource locations + * The default namespace for flows registered without an explicit namespace. */ - public void setLocations(Resource[] locations) { - this.locations = new HashSet(Arrays.asList(locations)); + private String defaultNamespace = ""; + + /** + * Creates a new registrar with an empty initial set of namespace to flow mappings. + */ + public ExternalizedFlowDefinitionRegistrar() { + this(new HashMap()); } /** - * Sets the formal set of externalized flow definitions this registrar will register. - *

- * Use this method when you want full control over the assigned flow id and the set of properties applied to the - * externalized flow resources. - * @param resources the externalized flow definition specifications + * Creates a new registrar with an initial set of namespace to flow mappings. + * @param namespaceFlowMappings the initial set of namespace to flow mappings */ - public void setResources(FlowDefinitionResource[] resources) { - this.resources = new HashSet(Arrays.asList(resources)); + public ExternalizedFlowDefinitionRegistrar(Map namespaceFlowMappings) { + this.namespaceFlowMappings = namespaceFlowMappings; } /** - * Adds a flow location pointing to an externalized flow resource. - *

- * The flow registered from this location will automatically assigned an id based on the filename of the flow - * resource. - * @param location the definition location + * Sets the default namespace to register flows in. If not set the default namespace is "" (an empty string). + * @param defaultNamespace the default namespace + */ + public void setDefaultNamespace(String defaultNamespace) { + this.defaultNamespace = defaultNamespace; + } + + public void setFlowServiceLocator(FlowServiceLocator flowServiceLocator) { + this.flowServiceLocator = flowServiceLocator; + } + + /** + * Returns the flow service locator for use by subclasses. + */ + protected FlowServiceLocator getFlowServiceLocator() { + return flowServiceLocator; + } + + /** + * Adds an externalized XML flow definition to be registered in the default namespace. + * @param location the resource to register + * @see #addLocation(Resource, String) + * @see #setDefaultNamespace(String) */ public boolean addLocation(Resource location) { - return locations.add(location); + return addLocation(location, defaultNamespace); } /** - * Adds the flow locations pointing to externalized flow resources. - *

- * The flow registered from this location will automatically assigned an id based on the filename of the flow - * resource. - * @param locations the definition locations + * Adds an externalized XML flow definition to be registered. The resource will be assigned a registry identifier + * equal to the filename of the resource, minus the filename extension. For example, an XML-based flow definition + * defined in the file flow1.xml will be identified as flow1 in the registry created + * by this factory bean. + * @param location the resource to register + * @param namespace the namespace to register the flow definition in */ - public boolean addLocations(Resource[] locations) { - if (locations == null) { - return false; - } - return this.locations.addAll(Arrays.asList(locations)); + public boolean addLocation(Resource location, String namespace) { + return getFlows(namespace).add(new FlowDefinitionResource(location)); } /** - * Adds an externalized flow definition specification pointing to an externalized flow resource. - *

- * Use this method when you want full control over the assigned flow id and the set of properties applied to the - * externalized flow resource. - * @param resource the definition the definition resource + * Adds an externalized XML flow definition resource to be registered in the default namespace. + * @param resource the flow definition resource to be registered + * @see #addResource(FlowDefinitionResource, String) + * @see #setDefaultNamespace(String) */ public boolean addResource(FlowDefinitionResource resource) { - return resources.add(resource); + return addResource(resource, defaultNamespace); } /** - * Adds the externalized flow definitions pointing to externalized flow resources. - *

- * Use this method when you want full control over the assigned flow id and the set of properties applied to the - * externalized flow resources. - * @param resources the definitions + * Adds an externalized XML flow definition resource to be registered. + * @param resource the flow definition resource to be registered + * @param namespace the namespace to register the flow definition in */ - public boolean addResources(FlowDefinitionResource[] resources) { - if (resources == null) { - return false; - } - return this.resources.addAll(Arrays.asList(resources)); + public boolean addResource(FlowDefinitionResource resource, String namespace) { + return getFlows(namespace).add(resource); } public void registerFlowDefinitions(FlowDefinitionRegistry registry) { - processLocations(registry); - processResources(registry); - } - - // internal helpers - - /** - * Register the flow definitions at the configured file locations. - * @param registry the registry - */ - private void processLocations(FlowDefinitionRegistry registry) { - Iterator it = locations.iterator(); - while (it.hasNext()) { - Resource location = (Resource) it.next(); - if (isFlowDefinitionResource(location)) { - FlowDefinitionResource resource = createFlowDefinitionResource(location); - register(resource, registry); + for (Iterator mappings = namespaceFlowMappings.entrySet().iterator(); mappings.hasNext();) { + Map.Entry mapping = (Map.Entry) mappings.next(); + String namespace = (String) mapping.getKey(); + for (Iterator resources = ((Set) mapping.getValue()).iterator(); resources.hasNext();) { + FlowDefinitionResource resource = (FlowDefinitionResource) resources.next(); + register(resource, namespace, registry); } } } /** - * Register the flow definitions at the configured file locations. + * Registers a flow definition resource in a given namespace. + * @param resource the resource to register + * @param namespace the namespace to register in * @param registry the registry */ - private void processResources(FlowDefinitionRegistry registry) { - Iterator it = resources.iterator(); - while (it.hasNext()) { - FlowDefinitionResource resource = (FlowDefinitionResource) it.next(); - register(resource, registry); + private void register(FlowDefinitionResource resource, String namespace, FlowDefinitionRegistry registry) { + registry.registerFlowDefinition(createFlowDefinitionHolder(resource), namespace); + } + + /** + * Returns the set of flows to be registered in a namespace. + * @param namespace The namespace for the collection to be returned + */ + private Set getFlows(String namespace) { + if (!namespaceFlowMappings.containsKey(namespace)) { + namespaceFlowMappings.put(namespace, new HashSet()); } + return (Set) namespaceFlowMappings.get(namespace); } - /** - * Helper method to register the flow built from an externalized resource in the registry. - * @param resource representation of the externalized flow definition resource - * @param registry the flow registry to register the flow in - */ - protected final void register(FlowDefinitionResource resource, FlowDefinitionRegistry registry) { - registry.registerFlowDefinition(createFlowDefinitionHolder(resource)); - } - - // subclassing hooks - - /** - * Template method that calculates if the given file resource is actually a flow definition resource. Resources that - * aren't flow definitions will be ignored. Subclasses may override; this implementation simply returns true. - * @param resource the underlying resource - * @return true if yes, false otherwise - */ - protected boolean isFlowDefinitionResource(Resource resource) { - return true; - } - - /** - * Factory method that creates a flow definition from an externalized resource location. - * @param location the location of the resource - * @return the externalized flow definition pointer - */ - protected FlowDefinitionResource createFlowDefinitionResource(Resource location) { - return new FlowDefinitionResource(location); - } + // sub-classing hooks /** * Template factory method subclasses must override to return the holder for the flow definition to be registered @@ -201,6 +175,6 @@ public abstract class ExternalizedFlowDefinitionRegistrar implements FlowDefinit protected abstract FlowDefinitionHolder createFlowDefinitionHolder(FlowDefinitionResource resource); public String toString() { - return new ToStringCreator(this).append("locations", locations).append("resources", resources).toString(); + return new ToStringCreator(this).append("namespaceFlowMappings", namespaceFlowMappings).toString(); } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java index ac0841e4..e359005b 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java @@ -15,6 +15,7 @@ */ package org.springframework.webflow.definition.registry; + /** * A strategy to use to populate a flow definition registry with one or more flow definitions. *

@@ -42,4 +43,5 @@ public interface FlowDefinitionRegistrar { * @param registry the registry to register flow definitions in */ public void registerFlowDefinitions(FlowDefinitionRegistry registry); + } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderFlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderFlowRegistryFactoryBean.java deleted file mode 100644 index 2bf26def..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderFlowRegistryFactoryBean.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder; - -import org.springframework.webflow.core.collection.AttributeMap; -import org.springframework.webflow.definition.registry.FlowDefinitionHolder; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.definition.registry.StaticFlowDefinitionHolder; -import org.springframework.webflow.engine.Flow; -import org.springframework.webflow.engine.builder.AbstractFlowBuilder; -import org.springframework.webflow.engine.builder.AbstractFlowBuildingFlowRegistryFactoryBean; -import org.springframework.webflow.engine.builder.FlowAssembler; - -/** - * Base class for factory beans that create flow definition registries containing flows built using Java based - * {@link AbstractFlowBuilder flow builders}. - *

- * Subclasses only need to define the {@link #doPopulate(FlowDefinitionRegistry)} method and use the - * {@link #registerFlowDefinition(FlowDefinitionRegistry, String, AbstractFlowBuilder)} convenience methods provided by - * this class to register all relevant flows: - * - *

- * public class MyFlowRegistryFactoryBean extends AbstractFlowBuilderFlowRegistryFactoryBean {
- * 	protected void doPopulate(FlowDefinitionRegistry registry) {
- * 		registerFlowDefinition(registry, "my-flow", new MyFlowBuilder());
- * 		registerFlowDefinition(registry, "my-other-flow", new MyOtherFlowBuilder());
- * 	}
- * }
- * 
- * - * @see AbstractFlowBuilder - * - * @since 1.0.2 - * - * @author Erwin Vervaet - */ -public abstract class AbstractFlowBuilderFlowRegistryFactoryBean extends AbstractFlowBuildingFlowRegistryFactoryBean { - - /** - * Register the flow built by given flow builder in specified flow definition registry. - *

- * Note that this method will set the {@link #getFlowServiceLocator() flow service locator} of this class on given - * flow builder. - * @param registry the registry to register the flow in - * @param flowId the flow id to assign - * @param flowBuilder the builder used to build the flow - */ - protected void registerFlowDefinition(FlowDefinitionRegistry registry, String flowId, - AbstractFlowBuilder flowBuilder) { - registerFlowDefinition(registry, flowId, null, flowBuilder); - } - - /** - * Register the flow built by given flow builder in specified flow definition registry. - *

- * Note that this method will set the {@link #getFlowServiceLocator() flow service locator} of this class on given - * flow builder. - * @param registry the registry to register the flow in - * @param flowId the flow id to assign - * @param flowAttributes externally assigned flow attributes that can affect flow construction - * @param flowBuilder the builder used to build the flow - */ - protected void registerFlowDefinition(FlowDefinitionRegistry registry, String flowId, AttributeMap flowAttributes, - AbstractFlowBuilder flowBuilder) { - flowBuilder.setFlowServiceLocator(getFlowServiceLocator()); - Flow flow = new FlowAssembler(flowId, flowAttributes, flowBuilder).assembleFlow(); - FlowDefinitionHolder flowHolder = new StaticFlowDefinitionHolder(flow); - registry.registerFlowDefinition(flowHolder); - } -} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuildingFlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuildingFlowRegistryFactoryBean.java deleted file mode 100644 index eff88afa..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuildingFlowRegistryFactoryBean.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.expression.ExpressionParser; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.ResourceLoader; -import org.springframework.webflow.action.BeanInvokingActionFactory; -import org.springframework.webflow.definition.registry.AbstractFlowDefinitionRegistryFactoryBean; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.engine.Flow; -import org.springframework.webflow.engine.State; -import org.springframework.webflow.execution.Action; - -/** - * A base class for factory beans that create populated registries of flow definitions built using a {@link FlowBuilder}, - * typically a {@link BaseFlowBuilder} subclass. This base class will setup a {@link FlowServiceLocator} for use by the - * flow builder. - *

- * Subclasses should override the {@link #doPopulate(FlowDefinitionRegistry)} template method to perform the registry - * population logic, typically delegating to a - * {@link org.springframework.webflow.definition.registry.FlowDefinitionRegistrar} strategy. - * - * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistry - * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistrar - * - * @author Keith Donald - */ -public abstract class AbstractFlowBuildingFlowRegistryFactoryBean extends AbstractFlowDefinitionRegistryFactoryBean - implements BeanFactoryAware, ResourceLoaderAware { - - /** - * The locator of services needed by the flows built for inclusion in the registry. - */ - private FlowServiceLocator flowServiceLocator; - - /** - * The factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and - * {@link State states}. - */ - private FlowArtifactFactory flowArtifactFactory; - - /** - * The factory encapsulating the creation of bean invoking actions, actions that adapt methods on objects to the - * {@link Action} interface. - */ - private BeanInvokingActionFactory beanInvokingActionFactory; - - /** - * The parser for parsing expression strings into evaluatable expression objects. - */ - private ExpressionParser expressionParser; - - /** - * A conversion service that can convert between types. - */ - private ConversionService conversionService; - - /** - * A resource loader that can load resources. - */ - private ResourceLoader resourceLoader; - - /** - * The Spring bean factory that manages configured flow artifacts. - */ - private BeanFactory beanFactory; - - /** - * Returns the factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and - * {@link State states}. - */ - protected FlowArtifactFactory getFlowArtifactFactory() { - return flowArtifactFactory; - } - - /** - * Sets the factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and - * {@link State states}. - */ - public void setFlowArtifactFactory(FlowArtifactFactory flowArtifactFactory) { - this.flowArtifactFactory = flowArtifactFactory; - } - - /** - * Returns the factory for creating bean invoking actions, actions that adapt methods on objects to the - * {@link Action} interface. - */ - protected BeanInvokingActionFactory getBeanInvokingActionFactory() { - return beanInvokingActionFactory; - } - - /** - * Sets the factory for creating bean invoking actions, actions that adapt methods on objects to the {@link Action} - * interface. - */ - public void setBeanInvokingActionFactory(BeanInvokingActionFactory beanInvokingActionFactory) { - this.beanInvokingActionFactory = beanInvokingActionFactory; - } - - /** - * Returns the expression parser responsible for parsing expression strings into evaluatable expression objects. - */ - protected ExpressionParser getExpressionParser() { - return expressionParser; - } - - /** - * Set the expression parser responsible for parsing expression strings into evaluatable expression objects. - */ - public void setExpressionParser(ExpressionParser expressionParser) { - this.expressionParser = expressionParser; - } - - /** - * Returns the conversion service to use to convert between types; typically from string to a rich object type. - */ - protected ConversionService getConversionService() { - return conversionService; - } - - /** - * Set the conversion service to use to convert between types; typically from string to a rich object type. - */ - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - // implementing ResourceLoaderAware - - /** - * Returns the injected resource loader. - */ - protected ResourceLoader getResourceLoader() { - return resourceLoader; - } - - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - // implementing BeanFactoryAware - - /** - * Returns the bean factory managing this bean. - */ - protected BeanFactory getBeanFactory() { - return beanFactory; - } - - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - protected final void init() { - flowServiceLocator = createFlowServiceLocator(); - init(flowServiceLocator); - } - - // subclassing hooks - - /** - * Factory method for creating the service locator used to locate webflow services during flow assembly. Subclasses - * may override to customize the instantiation and configuration of the locator returned. - * @return the service locator - */ - protected FlowServiceLocator createFlowServiceLocator() { - DefaultFlowServiceLocator serviceLocator = new DefaultFlowServiceLocator(getRegistry(), beanFactory); - if (flowArtifactFactory != null) { - serviceLocator.setFlowArtifactFactory(flowArtifactFactory); - } - if (beanInvokingActionFactory != null) { - serviceLocator.setBeanInvokingActionFactory(beanInvokingActionFactory); - } - if (expressionParser != null) { - serviceLocator.setExpressionParser(expressionParser); - } - if (conversionService != null) { - serviceLocator.setConversionService(conversionService); - } - if (resourceLoader != null) { - serviceLocator.setResourceLoader(resourceLoader); - } - return serviceLocator; - } - - /** - * Called after properties have been set on the service locator, but before registry population. Subclasses may - * override to perform custom initialization of the flow service locator. - * @param flowServiceLocator the flow service locator to use to locate externally managed services needed during - * flow building and assembly, typically used by a - * {@link org.springframework.webflow.definition.registry.FlowDefinitionRegistrar} - */ - protected void init(FlowServiceLocator flowServiceLocator) { - } - - /** - * Returns the strategy for locating dependent artifacts when a flow is being built. May be called by subclasses - * during {@link #doPopulate(FlowDefinitionRegistry) registry population} to wire in the service locator needed for - * flow assembly. - */ - protected FlowServiceLocator getFlowServiceLocator() { - return flowServiceLocator; - } - - protected abstract void doPopulate(FlowDefinitionRegistry registry); -} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBean.java new file mode 100644 index 00000000..91c36d44 --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBean.java @@ -0,0 +1,112 @@ +/* + * Copyright 2004-2007 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.engine.builder; + +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistrar; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.engine.builder.xml.XmlFlowRegistrar; + +/** + * A factory bean that accepts an arbitrary list of {@link FlowDefinitionRegistrar}s and uses them to register flows. + * This implementation should not be used programmatically but rather from the spring-webflow-config XML namespace. + *

+ * Example Usage: + * + *

+ * <flow:registry id="flowRegistry">
+ *     <flow:location path="flow1.xml"/>
+ *     <flow:location id="foo" path="flow2.xml"/>
+ *     <flow:class name="BarClass"/>
+ *     <flow:crud entity="Account"/>
+ *     <flow:namespace name="baz">
+ *         <flow:location path="flow3.xml"/>
+ *         <flow:class name="XyzClass"/>
+ *     </flow:namespace>
+ * </flow:registry>
+ * 
+ * + * @author Ben Hale + */ +public class FlowRegistryFactoryBean implements FactoryBean, InitializingBean, BeanFactoryAware { + + private FlowDefinitionRegistry registry; + + private BeanFactory beanFactory; + + private FlowServiceLocator flowServiceLocator; + + private Map xmlNamespaceFlowMappings; + + public void setFlowServiceLocator(FlowServiceLocator flowServiceLocator) { + this.flowServiceLocator = flowServiceLocator; + } + + public void setXmlNamespaceFlowMappings(Map xmlNamespaceFlowMappings) { + this.xmlNamespaceFlowMappings = xmlNamespaceFlowMappings; + } + + public void afterPropertiesSet() throws Exception { + this.registry = new FlowDefinitionRegistryImpl(); + initXml(registry); + } + + public Object getObject() throws Exception { + return registry; + } + + public Class getObjectType() { + return FlowDefinitionRegistry.class; + } + + public boolean isSingleton() { + return true; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + private void initXml(FlowDefinitionRegistry registry) { + XmlFlowRegistrar registrar = new XmlFlowRegistrar(getFlowServiceLocator(registry)); + for (Iterator mappings = xmlNamespaceFlowMappings.entrySet().iterator(); mappings.hasNext();) { + Map.Entry mapping = (Map.Entry) mappings.next(); + String namespace = (String) mapping.getKey(); + for (Iterator resources = ((Set) mapping.getValue()).iterator(); resources.hasNext();) { + FlowDefinitionResource resource = (FlowDefinitionResource) resources.next(); + registrar.addResource(resource, namespace); + } + } + registrar.registerFlowDefinitions(registry); + } + + private FlowServiceLocator getFlowServiceLocator(FlowDefinitionRegistry registry) { + if (flowServiceLocator == null) { + this.flowServiceLocator = new DefaultFlowServiceLocator(registry, beanFactory); + } + return flowServiceLocator; + } +} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBeanTests.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBeanTests.java new file mode 100644 index 00000000..c973e95a --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBeanTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2004-2007 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.engine.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.test.MockFlowServiceLocator; + +/** + * Tests that the factory bean properly creates a {@link FlowDefinitionRegistry} with the proper definitions in it. + */ +public class FlowRegistryFactoryBeanTests extends TestCase { + + public void testXmlRegistrar() throws Exception { + Set emptyNamespace = new HashSet(); + emptyNamespace.add(new FlowDefinitionResource(fromClassPath("flow1.xml"))); + Set bookingNamespace = new HashSet(); + bookingNamespace.add(new FlowDefinitionResource(fromClassPath("flow2.xml"))); + Map xmlNamespaceFlowMappings = new HashMap(); + xmlNamespaceFlowMappings.put("", emptyNamespace); + xmlNamespaceFlowMappings.put("booking", bookingNamespace); + FlowRegistryFactoryBean factoryBean = new FlowRegistryFactoryBean(); + factoryBean.setFlowServiceLocator(new MockFlowServiceLocator()); + factoryBean.setXmlNamespaceFlowMappings(xmlNamespaceFlowMappings); + factoryBean.afterPropertiesSet(); + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject(); + assertEquals("Incorrect number of flows", 2, registry.getFlowDefinitionCount()); + assertTrue("Missing flow", registry.containsFlowDefinition("flow1")); + assertTrue("Missing flow", registry.containsFlowDefinition("booking/flow2")); + } + + private Resource fromClassPath(String resourceName) { + return new ClassPathResource(resourceName, getClass()); + } + +} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java index ae2994f5..abb385cc 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java @@ -22,17 +22,19 @@ import org.springframework.webflow.definition.registry.FlowDefinitionHolder; import org.springframework.webflow.definition.registry.FlowDefinitionResource; import org.springframework.webflow.engine.builder.FlowAssembler; import org.springframework.webflow.engine.builder.FlowBuilder; +import org.springframework.webflow.engine.builder.FlowRegistryFactoryBean; import org.springframework.webflow.engine.builder.FlowServiceLocator; import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolder; /** * A flow definition registrar that populates a flow definition registry with flow definitions defined in externalized - * XML resources. Typically used in conjunction with a {@link XmlFlowRegistryFactoryBean} but may also be used - * standalone in programmatic fashion. + * XML resources. Typically used in conjunction with a {@link FlowRegistryFactoryBean} but may also be used stand-alone + * in programmatic fashion. *

- * By default, a flow definition registered by this registrar will be assigned a registry identifier equal to the - * filename of the underlying definition resource, minus the filename extension. For example, a XML-based flow - * definition defined in the file "flow1.xml" will be identified as "flow1" when registered in a registry. + * By default, a flow definition added to this registrar with the {@link #addLocation(Resource, String)} method will be + * will be assigned a registry identifier equal to the filename of the underlying definition resource, minus the + * filename extension. For example, a XML-based flow definition defined in the file "flow1.xml" will be identified as + * "flow1" when registered in a registry. *

* Programmatic usage example: * @@ -43,59 +45,28 @@ import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolde * new DefaultFlowServiceLocator(registry, beanFactory); * XmlFlowRegistrar registrar = new XmlFlowRegistrar(flowServiceLocator); * File parent = new File("src/webapp/WEB-INF"); - * registrar.addLocation(new FileSystemResource(new File(parent, "flow1.xml")); - * registrar.addLocation(new FileSystemResource(new File(parent, "flow2.xml")); + * registrar.add(new FileSystemResource(new File(parent, "flow1.xml")); + * registrar.add(new FileSystemResource(new File(parent, "flow2.xml")); * registrar.registerFlowDefinitions(registry); * * * @author Keith Donald + * @author Ben Hale */ public class XmlFlowRegistrar extends ExternalizedFlowDefinitionRegistrar { - /** - * The xml file suffix constant. - */ - private static final String XML_SUFFIX = ".xml"; - - /** - * The locator of services needed by flow definitions. - */ - private FlowServiceLocator flowServiceLocator; - /** * The loader of XML-based flow definition documents. */ private DocumentLoader documentLoader; - /** - * Creates a new XML flow registrar. Protected constructor - if used, make sure the required - * {@link #flowServiceLocator} reference is set. - */ - protected XmlFlowRegistrar() { - } - /** * Creates a new XML flow registrar. * @param flowServiceLocator the locator needed to support flow definition assembly */ public XmlFlowRegistrar(FlowServiceLocator flowServiceLocator) { - setFlowServiceLocator(flowServiceLocator); - } - - /** - * Sets the flow service locator. - * @param flowServiceLocator the flow service locator (may not be null) - */ - protected void setFlowServiceLocator(FlowServiceLocator flowServiceLocator) { Assert.notNull(flowServiceLocator, "The flow service locator is required"); - this.flowServiceLocator = flowServiceLocator; - } - - /** - * Returns the flow service locator. - */ - protected FlowServiceLocator getFlowServiceLocator() { - return flowServiceLocator; + setFlowServiceLocator(flowServiceLocator); } /** @@ -107,16 +78,7 @@ public class XmlFlowRegistrar extends ExternalizedFlowDefinitionRegistrar { this.documentLoader = documentLoader; } - /** - * Returns the loader of XML-based flow definition documents. - */ - public DocumentLoader getDocumentLoader() { - return documentLoader; - } - - protected boolean isFlowDefinitionResource(Resource resource) { - return resource.getFilename().endsWith(XML_SUFFIX); - } + // hook methods protected FlowDefinitionHolder createFlowDefinitionHolder(FlowDefinitionResource resource) { FlowBuilder builder = createFlowBuilder(resource.getLocation()); @@ -124,8 +86,6 @@ public class XmlFlowRegistrar extends ExternalizedFlowDefinitionRegistrar { return new RefreshableFlowDefinitionHolder(assembler); } - // hook methods - /** * Factory method that creates and fully initializes the XML-based flow definition builder. * @param location the xml-based resource diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java deleted file mode 100644 index 2ea21fa7..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder.xml; - -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; - -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.webflow.core.collection.AttributeMap; -import org.springframework.webflow.core.collection.LocalAttributeMap; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.definition.registry.FlowDefinitionResource; -import org.springframework.webflow.engine.builder.AbstractFlowBuildingFlowRegistryFactoryBean; -import org.springframework.webflow.engine.builder.DefaultFlowServiceLocator; -import org.springframework.webflow.engine.builder.FlowServiceLocator; - -/** - * A factory bean that produces a populated flow registry using an {@link XmlFlowRegistrar}. This is the simplest - * implementation to use when using a Spring BeanFactory to deploy an explicit registry of XML-based Flow definitions - * for execution. - *

- * By default, a configured flow definition will be assigned a registry identifier equal to the filename of the - * underlying definition resource, minus the filename extension. For example, an XML-based flow definition defined in - * the file flow1.xml will be identified as flow1 in the registry created by this factory - * bean. - *

- * This class is also BeanFactoryAware and when used with Spring will automatically create a configured - * {@link DefaultFlowServiceLocator} for loading Flow artifacts like Actions from the Spring bean factory during the - * Flow registration process. - *

- * This class is also ResourceLoaderAware; when an instance is created by a Spring BeanFactory the - * factory will automatically configure the XmlFlowRegistrar with a context-relative resource loader for accessing other - * resources during Flow assembly. - * - * Usage example: - * - *

- *     <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.registry.XmlFlowRegistryFactoryBean">
- *         <property name="flowLocations" value="/WEB-INF/flows/*-flow.xml"/> 
- *     </bean>
- * 
- * - * @author Keith Donald - */ -public class XmlFlowRegistryFactoryBean extends AbstractFlowBuildingFlowRegistryFactoryBean { - - /** - * The flow registrar that will perform the definition registrations. - */ - private XmlFlowRegistrar flowRegistrar = new XmlFlowRegistrar(); - - /** - * Temporary holder for flow definition locations. - */ - private Resource[] locations; - - /** - * Temporary holder for flow definitions configured using a property map. - */ - private Properties flowDefinitions; - - /** - * A map that contains a map (java.util.Map) of flow attributes keyed by flow id (String). - */ - private Map flowAttributes; - - /** - * Returns the configured externalized XML flow registrar. - */ - public XmlFlowRegistrar getXmlFlowRegistrar() { - return flowRegistrar; - } - - /** - * Set the configured externalized XML flow registrar. - * @since 1.0.1 - */ - public void setXmlFlowRegistrar(XmlFlowRegistrar flowRegistrar) { - Assert.notNull(flowRegistrar, "The flowRegistrar is required"); - this.flowRegistrar = flowRegistrar; - } - - /** - * Sets the locations (resource file paths) pointing to XML-based flow definitions. - *

- * When configuring as a Spring bean definition, ANT-style resource patterns/wildcards are also supported, taking - * advantage of Spring's built in ResourceArrayPropertyEditor machinery. - *

- * For example: - * - *

-	 *     <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean">
-	 *         <property name="flowLocations" value="/WEB-INF/flows/*-flow.xml"/> 
-	 *     </bean>
-	 * 
- * - * Another example: - * - *
-	 *    <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean">
-	 *          <property name="flowLocations" value="classpath*:/example/flows/*-flow.xml"/> 
-	 *    </bean>
-	 * 
- * - * Flows registered from this set will be automatically assigned an id based on the filename of the matched XML - * resource. - * @param locations the resource locations - */ - public void setFlowLocations(Resource[] locations) { - this.locations = locations; - } - - /** - * Convenience method for setting externalized flow definitions from a java.util.Properties map. - * Allows for more control over the definition, including which flowId is assigned. - *

- * Each property key is the flowId and each property value is the string encoded location of the - * externalized flow definition resource. - *

- * Here is the exact format: - * - *

-	 * flowId = resource
-	 * 
- * - * For example: - * - *
-	 *     <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean">
-	 *         <property name="flowDefinitions">
-	 *             <value>
-	 *                 searchFlow=/WEB-INF/flows/search-flow.xml
-	 *                 detailFlow=/WEB-INF/flows/detail-flow.xml
-	 *             </value>
-	 *         </property>
-	 *     </bean>
-	 * 
- * - * @param flowDefinitions the flow definitions, defined within a properties map - */ - public void setFlowDefinitions(Properties flowDefinitions) { - this.flowDefinitions = flowDefinitions; - } - - /** - * Sets flow attributes from an externalized java.util.Map. The keys in the map are String flow ids. - * The corresponding values should be java.util.Map maps containing flow attributes to be assigned to - * the flow. A flow with an id not contained in the provided map will get not externally defined flow attributes - * assigned. - *

- * Can be used in conjunction with both {@link #setFlowLocations(Resource[])} and - * {@link #setFlowDefinitions(Properties)}. - * @param flowAttributes the flow attributes, keyed by flow id - * @since 1.0.1 - */ - public void setFlowAttributes(Map flowAttributes) { - this.flowAttributes = flowAttributes; - } - - /** - * Sets the loader to load XML-based flow definition documents during flow definition assembly. Allows for - * customization over how flow definition documents are loaded. Optional. - * @param documentLoader the document loader - */ - public void setDocumentLoader(DocumentLoader documentLoader) { - getXmlFlowRegistrar().setDocumentLoader(documentLoader); - } - - protected void init(FlowServiceLocator flowServiceLocator) { - // simply wire in the locator to the registrar - getXmlFlowRegistrar().setFlowServiceLocator(flowServiceLocator); - } - - protected void doPopulate(FlowDefinitionRegistry registry) { - addFlowDefinitionLocations(); - addFlowDefinitionsFromProperties(); - getXmlFlowRegistrar().registerFlowDefinitions(registry); - } - - /** - * Add configured flow definition locations to the flow definition registrar. - */ - private void addFlowDefinitionLocations() { - if (locations != null) { - for (int i = 0; i < locations.length; i++) { - String flowId = FlowDefinitionResource.conventionalFlowId(locations[i]); - getXmlFlowRegistrar().addResource( - new FlowDefinitionResource(flowId, locations[i], getFlowAttributes(flowId))); - } - } - } - - /** - * Add flow definitions configured using a property map to the flow definition registrar. - */ - private void addFlowDefinitionsFromProperties() { - if (flowDefinitions != null) { - Iterator it = flowDefinitions.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - String flowId = (String) entry.getKey(); - String location = (String) entry.getValue(); - Resource resource = getFlowServiceLocator().getResourceLoader().getResource(location); - getXmlFlowRegistrar().addResource( - new FlowDefinitionResource(flowId, resource, getFlowAttributes(flowId))); - } - } - } - - /** - * Returns the flow attributes to be assigned to the flow with given id. Returns null if no attributes should be - * assigned. - */ - private AttributeMap getFlowAttributes(String flowId) { - if (flowAttributes != null) { - Map attributes = (Map) flowAttributes.get(flowId); - if (attributes != null) { - return new LocalAttributeMap(attributes); - } - } - return null; - } -} \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java index 9dc918fc..f98d3fbf 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java @@ -22,7 +22,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.webflow.executor.mvc.FlowController; /** - * Test case that illustrates configuration of a FlowController and its associated artefacts using classic spring bean + * Test case that illustrates configuration of a FlowController and its associated artifacts using classic spring bean * configuration information. This test case does not really test much but serves more as an example. * * @author Erwin Vervaet diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java index 92ebfbad..0bc2c99e 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java @@ -17,6 +17,7 @@ package org.springframework.webflow.config; import junit.framework.TestCase; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.support.DefaultListableBeanFactory; @@ -38,17 +39,12 @@ import org.springframework.webflow.executor.FlowExecutorImpl; /** * Unit tests for the WebFlowConfigNamespaceHandler and its BeanDefinitionParsers. - * - * @author Ben Hale - * @author Erwin Vervaet - * @author Christian Dupuis */ public class WebFlowConfigNamespaceHandlerTests extends TestCase { private DefaultListableBeanFactory beanFactory; protected void setUp() throws Exception { - super.setUp(); this.beanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory); reader.loadBeanDefinitions(new ClassPathResource( @@ -58,16 +54,36 @@ public class WebFlowConfigNamespaceHandlerTests extends TestCase { public void testRegistryWithPath() { FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withPath"); assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount()); - } - - public void testRegistryWithoutPath() { - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withoutPath"); - assertEquals("Incorrect number of flows loaded", 0, registry.getFlowDefinitionCount()); + assertTrue("Incorrect flow name", registry.containsFlowDefinition("/flow1")); } public void testRegistryWithPathWithWildcards() { FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withPathWithWildcards"); - assertEquals("Incorrect number of flows loaded", 0, registry.getFlowDefinitionCount()); + assertEquals("Incorrect number of flows loaded", 3, registry.getFlowDefinitionCount()); + assertTrue("Incorrect flow name", registry.containsFlowDefinition("/flow1")); + assertTrue("Incorrect flow name", registry.containsFlowDefinition("/flow2")); + } + + public void testRegistryWithId() { + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withId"); + assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount()); + assertTrue("Incorrect flow name", registry.containsFlowDefinition("/foo")); + } + + public void testWithIdWithWildCards() { + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory); + try { + reader.loadBeanDefinitions(new ClassPathResource( + "org/springframework/webflow/config/webflow-config-namespace-bad.xml")); + fail("Should not have allowed id with wildcards"); + } catch (BeanDefinitionParsingException e) { + } + } + + public void testRegistryWithNamespace() { + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withNamespace"); + assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount()); + assertTrue("Incorrect flow name", registry.containsFlowDefinition("namespace/flow1")); } public void testDefaultExecutor() { diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml index 2d6cca7c..0dbf25d1 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml @@ -1,14 +1,27 @@ - - + + - - + + + + + + + + + + + + diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow1.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow1.xml new file mode 100644 index 00000000..4e3e7b7e --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow1.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow2.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow2.xml new file mode 100644 index 00000000..4e3e7b7e --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow2.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-classic.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-classic.xml index cc86bd04..99060fe0 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-classic.xml +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-classic.xml @@ -1,104 +1,120 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - true - - - - - - - - - - + http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util-2.0.xsd"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + true + + + + + + + + + + \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace-bad.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace-bad.xml new file mode 100644 index 00000000..c0d84029 --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace-bad.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml index 26565671..afe08f0b 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml @@ -6,19 +6,24 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/webflow-config - http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd"> + http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd"> - - - - - + - - + + + + + + + + + + + diff --git a/spring-webflow/src/test/java/org/springframework/webflow/conversation/impl/ConversationSizeTests.java b/spring-webflow/src/test/java/org/springframework/webflow/conversation/impl/ConversationSizeTests.java index bf264bd3..0e104c38 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/conversation/impl/ConversationSizeTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/conversation/impl/ConversationSizeTests.java @@ -20,13 +20,17 @@ import java.io.ObjectOutputStream; import junit.framework.TestCase; -import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.webflow.config.FlowExecutorFactoryBean; import org.springframework.webflow.config.RepositoryType; import org.springframework.webflow.core.collection.SharedAttributeMap; +import org.springframework.webflow.definition.registry.FlowDefinitionHolder; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistrar; import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl; +import org.springframework.webflow.definition.registry.StaticFlowDefinitionHolder; +import org.springframework.webflow.engine.Flow; import org.springframework.webflow.engine.builder.AbstractFlowBuilder; -import org.springframework.webflow.engine.builder.AbstractFlowBuilderFlowRegistryFactoryBean; +import org.springframework.webflow.engine.builder.FlowAssembler; import org.springframework.webflow.engine.builder.FlowBuilderException; import org.springframework.webflow.execution.support.ApplicationView; import org.springframework.webflow.execution.support.FlowExecutionRedirect; @@ -36,19 +40,16 @@ import org.springframework.webflow.test.MockExternalContext; /** * Test case that looks for the miminum conversation size. - * - * @author Erwin Vervaet */ public class ConversationSizeTests extends TestCase { private SessionBindingConversationManager conversationManager; + private FlowExecutor flowExecutor; protected void setUp() throws Exception { - AbstractFlowBuilderFlowRegistryFactoryBean flowRegistryFactory = new SizeTestFlowRegistry(); - flowRegistryFactory.setBeanFactory(new StaticListableBeanFactory()); - flowRegistryFactory.afterPropertiesSet(); - FlowDefinitionRegistry flowRegistry = flowRegistryFactory.getRegistry(); + FlowDefinitionRegistry flowRegistry = new FlowDefinitionRegistryImpl(); + new SizeTestFlowRegistrar().registerFlowDefinitions(flowRegistry); conversationManager = new SessionBindingConversationManager(); @@ -110,9 +111,6 @@ public class ConversationSizeTests extends TestCase { oout.writeObject(obj); oout.flush(); int objSize = bout.toByteArray().length; - - // System.out.println(">>>> serialized size of '" + obj + "' is " + objSize); - return objSize; } @@ -123,9 +121,12 @@ public class ConversationSizeTests extends TestCase { } } - private static class SizeTestFlowRegistry extends AbstractFlowBuilderFlowRegistryFactoryBean { - protected void doPopulate(FlowDefinitionRegistry registry) { - registerFlowDefinition(registry, "size-test-flow", new SizeTestFlowBuilder()); + private static class SizeTestFlowRegistrar implements FlowDefinitionRegistrar { + + public void registerFlowDefinitions(FlowDefinitionRegistry registry) { + Flow flow = new FlowAssembler("size-test-flow", null, new SizeTestFlowBuilder()).assembleFlow(); + FlowDefinitionHolder flowHolder = new StaticFlowDefinitionHolder(flow); + registry.registerFlowDefinition(flowHolder); } } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderParameterizationTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderParameterizationTests.java index 6cff6850..7a3df47b 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderParameterizationTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderParameterizationTests.java @@ -17,32 +17,32 @@ package org.springframework.webflow.engine.builder; import junit.framework.TestCase; -import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.core.collection.MutableAttributeMap; +import org.springframework.webflow.definition.registry.FlowDefinitionHolder; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistrar; import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl; +import org.springframework.webflow.definition.registry.StaticFlowDefinitionHolder; import org.springframework.webflow.engine.Flow; import org.springframework.webflow.execution.ViewSelection; import org.springframework.webflow.execution.support.ApplicationView; +import org.springframework.webflow.test.MockFlowServiceLocator; import org.springframework.webflow.test.MockRequestControlContext; /** * Test parameterization of flow built using an AbstractFlowBuilder when registering the flows with a * FlowDefinitionRegistry. - * - * @author Erwin Vervaet */ public class AbstractFlowBuilderParameterizationTests extends TestCase { private FlowDefinitionRegistry registry; protected void setUp() throws Exception { - TestFlowRegistryFactoryBean registryFactory = new TestFlowRegistryFactoryBean(); - StaticListableBeanFactory beanFactory = new StaticListableBeanFactory(); - beanFactory.addBean("testAction", new ParameterizationTestAction()); - registryFactory.setBeanFactory(beanFactory); - registryFactory.afterPropertiesSet(); - registry = registryFactory.getRegistry(); + registry = new FlowDefinitionRegistryImpl(); + MockFlowServiceLocator flowServiceLocator = new MockFlowServiceLocator(); + flowServiceLocator.registerBean("testAction", new ParameterizationTestAction()); + new TestFlowRegistrar(flowServiceLocator).registerFlowDefinitions(registry); } public void testFlowParameterization() { @@ -74,24 +74,40 @@ public class AbstractFlowBuilderParameterizationTests extends TestCase { public class TestFlowBuilder extends AbstractFlowBuilder { + public TestFlowBuilder(FlowServiceLocator flowServiceLocator) { + setFlowServiceLocator(flowServiceLocator); + } + public void buildStates() throws FlowBuilderException { addActionState("test", action("testAction"), transition(on(success()), to("finish"))); addEndState("finish", "${activeFlow.attributes['name']}"); } } - public class TestFlowRegistryFactoryBean extends AbstractFlowBuilderFlowRegistryFactoryBean { + private class TestFlowRegistrar implements FlowDefinitionRegistrar { - protected void doPopulate(FlowDefinitionRegistry registry) { - MutableAttributeMap attributes = new LocalAttributeMap(); - attributes.put("name", "A"); - attributes.put("someKey", "someValue"); - registerFlowDefinition(registry, "flowA", attributes, new TestFlowBuilder()); + private FlowServiceLocator flowServiceLocator; - attributes = new LocalAttributeMap(); - attributes.put("name", "B"); - attributes.put("someOtherKey", "someOtherValue"); - registerFlowDefinition(registry, "flowB", attributes, new TestFlowBuilder()); + public TestFlowRegistrar(FlowServiceLocator flowServiceLocator) { + this.flowServiceLocator = flowServiceLocator; + } + + public void registerFlowDefinitions(FlowDefinitionRegistry registry) { + MutableAttributeMap attributesA = new LocalAttributeMap(); + attributesA.put("name", "A"); + attributesA.put("someKey", "someValue"); + Flow flowA = new FlowAssembler("flowA", attributesA, new TestFlowBuilder(flowServiceLocator)) + .assembleFlow(); + FlowDefinitionHolder flowHolderA = new StaticFlowDefinitionHolder(flowA); + registry.registerFlowDefinition(flowHolderA); + + MutableAttributeMap attributesB = new LocalAttributeMap(); + attributesB.put("name", "B"); + attributesB.put("someOtherKey", "someOtherValue"); + Flow flowB = new FlowAssembler("flowB", attributesB, new TestFlowBuilder(flowServiceLocator)) + .assembleFlow(); + FlowDefinitionHolder flowHolderB = new StaticFlowDefinitionHolder(flowB); + registry.registerFlowDefinition(flowHolderB); } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java index 2b54b550..873020ab 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java @@ -18,12 +18,14 @@ package org.springframework.webflow.engine.builder.xml; import junit.framework.TestCase; import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl; import org.springframework.webflow.definition.registry.FlowDefinitionResource; import org.springframework.webflow.engine.builder.BaseFlowServiceLocator; public class XmlFlowRegistrarTests extends TestCase { + private XmlFlowRegistrar registrar; private FlowDefinitionRegistry registry = new FlowDefinitionRegistryImpl(); @@ -33,19 +35,41 @@ public class XmlFlowRegistrarTests extends TestCase { registrar = new XmlFlowRegistrar(locator); } - public void testAddLocation() { - assertEquals(0, registry.getFlowDefinitionCount()); - registrar.addLocation(new ClassPathResource("flow.xml", getClass())); - registrar.registerFlowDefinitions(registry); - assertEquals(1, registry.getFlowDefinitionCount()); - assertEquals("flow", registry.getFlowDefinition("flow").getId()); - } - public void testAddResource() { assertEquals(0, registry.getFlowDefinitionCount()); - registrar.addResource(new FlowDefinitionResource("foo", new ClassPathResource("flow.xml", getClass()))); + registrar.addResource(new FlowDefinitionResource("foo", fromClassPath("flow.xml")), "namespace"); registrar.registerFlowDefinitions(registry); assertEquals(1, registry.getFlowDefinitionCount()); - assertEquals("foo", registry.getFlowDefinition("foo").getId()); + assertEquals("foo", registry.getFlowDefinition("namespace/foo").getId()); + } + + public void testAddResourceDefaultNamespace() { + assertEquals(0, registry.getFlowDefinitionCount()); + registrar.setDefaultNamespace("default"); + registrar.addResource(new FlowDefinitionResource("foo", fromClassPath("flow.xml"))); + registrar.registerFlowDefinitions(registry); + assertEquals(1, registry.getFlowDefinitionCount()); + assertEquals("foo", registry.getFlowDefinition("default/foo").getId()); + } + + public void testAddLocation() { + assertEquals(0, registry.getFlowDefinitionCount()); + registrar.addLocation(fromClassPath("flow.xml"), "namespace"); + registrar.registerFlowDefinitions(registry); + assertEquals(1, registry.getFlowDefinitionCount()); + assertEquals("flow", registry.getFlowDefinition("namespace/flow").getId()); + } + + public void testAddLocationDefaultNamespace() { + assertEquals(0, registry.getFlowDefinitionCount()); + registrar.setDefaultNamespace("default"); + registrar.addLocation(fromClassPath("flow.xml")); + registrar.registerFlowDefinitions(registry); + assertEquals(1, registry.getFlowDefinitionCount()); + assertEquals("flow", registry.getFlowDefinition("default/flow").getId()); + } + + private Resource fromClassPath(String resourceName) { + return new ClassPathResource(resourceName, getClass()); } } \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanParameterizationTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanParameterizationTests.java deleted file mode 100644 index 304a65ad..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanParameterizationTests.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder.xml; - -import junit.framework.TestCase; - -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.engine.Flow; -import org.springframework.webflow.execution.ViewSelection; -import org.springframework.webflow.execution.support.ApplicationView; -import org.springframework.webflow.test.MockRequestControlContext; - -/** - * Test flow parameterization using the XmlFlowRegistryFactoryBean. - * - * @author Erwin Vervaet - */ -public class XmlFlowRegistryFactoryBeanParameterizationTests extends TestCase { - - private ApplicationContext applicationContext; - - protected void setUp() throws Exception { - applicationContext = new ClassPathXmlApplicationContext("parameterizedFlowContext.xml", getClass()); - } - - public void testNoFlowParameterization() { - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) applicationContext.getBean("flowRegistry0"); - assertEquals(1, registry.getFlowDefinitionCount()); - assertTrue(registry.containsFlowDefinition("parameterizedFlow")); - Flow parameterizedFlow = (Flow) registry.getFlowDefinition("parameterizedFlow"); - assertEquals(0, parameterizedFlow.getAttributes().size()); - assertNull(parameterizedFlow.getAttributes().get("foo")); - } - - public void testSimpleFlowParameterization() { - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) applicationContext.getBean("flowRegistry1"); - assertEquals(1, registry.getFlowDefinitionCount()); - assertTrue(registry.containsFlowDefinition("parameterizedFlow")); - Flow parameterizedFlow = (Flow) registry.getFlowDefinition("parameterizedFlow"); - assertEquals(1, parameterizedFlow.getAttributes().size()); - assertEquals("bar", parameterizedFlow.getAttributes().get("foo")); - } - - public void testAdvancedParameterization() { - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) applicationContext.getBean("flowRegistry2"); - - assertEquals(2, registry.getFlowDefinitionCount()); - assertTrue(registry.containsFlowDefinition("flowA")); - Flow flowA = (Flow) registry.getFlowDefinition("flowA"); - assertEquals(2, flowA.getAttributes().size()); - assertEquals("A", flowA.getAttributes().get("name")); - assertEquals("someValue", flowA.getAttributes().get("someKey")); - assertNull(flowA.getAttributes().get("someOtherKey")); - - assertTrue(registry.containsFlowDefinition("flowB")); - Flow flowB = (Flow) registry.getFlowDefinition("flowB"); - assertEquals(2, flowB.getAttributes().size()); - assertEquals("B", flowB.getAttributes().get("name")); - assertEquals("someOtherValue", flowB.getAttributes().get("someOtherKey")); - assertNull(flowB.getAttributes().get("someKey")); - } - - public void testAdvancedParameterizationAtRuntime() { - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) applicationContext.getBean("flowRegistry2"); - - Flow flowA = (Flow) registry.getFlowDefinition("flowA"); - ViewSelection viewSelection = flowA.start(new MockRequestControlContext(flowA), null); - assertEquals("A", ((ApplicationView) viewSelection).getViewName()); - - Flow flowB = (Flow) registry.getFlowDefinition("flowB"); - viewSelection = flowB.start(new MockRequestControlContext(flowB), null); - assertEquals("B", ((ApplicationView) viewSelection).getViewName()); - } -} diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanTests.java deleted file mode 100644 index e5f6ee32..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanTests.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder.xml; - -import java.util.Properties; - -import junit.framework.TestCase; - -import org.springframework.beans.factory.support.StaticListableBeanFactory; -import org.springframework.core.io.ClassPathResource; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; - -public class XmlFlowRegistryFactoryBeanTests extends TestCase { - private XmlFlowRegistryFactoryBean factoryBean = new XmlFlowRegistryFactoryBean(); - - public void testCreateFromLocations() throws Exception { - ClassPathResource[] locations = new ClassPathResource[] { new ClassPathResource("flow.xml", getClass()) }; - factoryBean.setFlowLocations(locations); - factoryBean.setBeanFactory(new StaticListableBeanFactory()); - factoryBean.afterPropertiesSet(); - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject(); - assertEquals(1, registry.getFlowDefinitionCount()); - assertEquals("flow", registry.getFlowDefinition("flow").getId()); - } - - public void testCreateFromDefinitions() throws Exception { - Properties properties = new Properties(); - properties.put("foo", "classpath:/org/springframework/webflow/engine/builder/xml/flow.xml"); - factoryBean.setFlowDefinitions(properties); - factoryBean.setBeanFactory(new StaticListableBeanFactory()); - factoryBean.afterPropertiesSet(); - FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject(); - assertEquals(1, registry.getFlowDefinitionCount()); - assertEquals("foo", registry.getFlowDefinition("foo").getId()); - } -} diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/parameterizedFlowContext.xml b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/parameterizedFlowContext.xml deleted file mode 100644 index 486d2137..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/parameterizedFlowContext.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - flowA=classpath:org/springframework/webflow/engine/builder/xml/parameterizedFlow.xml - flowB=classpath:org/springframework/webflow/engine/builder/xml/parameterizedFlow.xml - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/context.xml b/spring-webflow/src/test/java/org/springframework/webflow/executor/context.xml index 8bcc893a..efa3d7e0 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/executor/context.xml +++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/context.xml @@ -1,27 +1,36 @@ - + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://www.springframework.org/schema/webflow-config + http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd"> - + - + - + - - - + + + - + \ No newline at end of file