Index: src/main/java/META-INF/spring.schemas =================================================================== --- src/main/java/META-INF/spring.schemas (revision 7805) +++ src/main/java/META-INF/spring.schemas (working copy) @@ -1,2 +1,2 @@ http\://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd=org/springframework/webflow/config/spring-webflow-config-1.0.xsd -http\://www.springframework.org/schema/webflow-config/spring-webflow-config-1.1.xsd=org/springframework/webflow/config/spring-webflow-config-1.1.xsd \ No newline at end of file +http\://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd=org/springframework/webflow/config/spring-webflow-config-2.0.xsd \ No newline at end of file Index: src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java =================================================================== --- src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java (revision 7805) +++ src/main/java/org/springframework/webflow/config/RegistryBeanDefinitionParser.java (working copy) @@ -15,6 +15,7 @@ */ package org.springframework.webflow.config; +import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -19,11 +20,18 @@ import java.util.Iterator; import java.util.List; +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.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.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; +import org.springframework.webflow.definition.registry.NamespaceMapping; import org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean; import org.w3c.dom.Element; @@ -32,7 +40,7 @@ * * @author Ben Hale */ -class RegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { +class RegistryBeanDefinitionParser extends AbstractBeanDefinitionParser { // elements and attributes @@ -38,6 +46,12 @@ private static final String LOCATION_ELEMENT = "location"; + private static final String NAMESPACE_ELEMENT = "namespace"; + + private static final String NAME_ATTRIBUTE = "name"; + + private static final String PATH_ATTRIBUTE = "path"; + // properties private static final String FLOW_LOCATIONS_PROPERTY = "flowLocations"; @@ -42,22 +56,54 @@ private static final String FLOW_LOCATIONS_PROPERTY = "flowLocations"; - private static final String PATH_ATTRIBUTE = "path"; + private static final String FLOW_NAMESPACE_MAPPINGS_PROPERTY = "flowNamespaceMappings"; + + protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { + BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder + .rootBeanDefinition(XmlFlowRegistryFactoryBean.class); + definitionBuilder.setSource(parserContext.extractSource(element)); + addNamespaceMappings(element, parserContext, definitionBuilder); + addLocations(element, parserContext, definitionBuilder); - protected Class getBeanClass(Element element) { - return XmlFlowRegistryFactoryBean.class; + return definitionBuilder.getBeanDefinition(); } - protected void doParse(Element element, BeanDefinitionBuilder definitionBuilder) { + private void addLocations(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) { List locationElements = DomUtils.getChildElementsByTagName(element, LOCATION_ELEMENT); - List locations = getLocations(locationElements); - definitionBuilder.addPropertyValue(FLOW_LOCATIONS_PROPERTY, locations.toArray(new String[locations.size()])); + definitionBuilder.addPropertyValue(FLOW_LOCATIONS_PROPERTY, getLocations(locationElements, parserContext)); + } + + private void addNamespaceMappings(Element element, ParserContext parserContext, + BeanDefinitionBuilder definitionBuilder) { + List namespaceElements = DomUtils.getChildElementsByTagName(element, NAMESPACE_ELEMENT); + definitionBuilder.addPropertyValue(FLOW_NAMESPACE_MAPPINGS_PROPERTY, getNamespaceMappings(namespaceElements, + parserContext)); } /** - * Parse location definitions from given list of location elements. + * Parsers namespace mappings from a given list of namespace elements. */ - private List getLocations(List locationElements) { + private NamespaceMapping[] getNamespaceMappings(List namespaceElements, ParserContext parserContext) { + List namespaceMappings = new ArrayList(namespaceElements.size()); + for (Iterator it = namespaceElements.iterator(); it.hasNext();) { + Element namespaceElement = (Element) it.next(); + String name = namespaceElement.getAttribute(NAME_ATTRIBUTE); + if (!StringUtils.hasText(name)) { + parserContext.getReaderContext().error( + "The 'name' attribute of the 'namespace' element must have a value", namespaceElement); + } + List locationElements = DomUtils.getChildElementsByTagName(namespaceElement, LOCATION_ELEMENT); + namespaceMappings.add(new NamespaceMapping(name, getLocations(locationElements, parserContext))); + } + return (NamespaceMapping[]) namespaceMappings.toArray(new NamespaceMapping[namespaceMappings.size()]); + } + + /** + * Parse location resources from given list of location elements. + */ + private Resource[] getLocations(List locationElements, ParserContext parserContext) { + ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(parserContext + .getReaderContext().getResourceLoader()); List locations = new ArrayList(locationElements.size()); for (Iterator i = locationElements.iterator(); i.hasNext();) { Element locationElement = (Element) i.next(); @@ -63,9 +109,14 @@ Element locationElement = (Element) i.next(); String path = locationElement.getAttribute(PATH_ATTRIBUTE); if (StringUtils.hasText(path)) { - locations.add(path); + try { + CollectionUtils.mergeArrayIntoCollection(resolver.getResources(path), locations); + } catch (IOException e) { + parserContext.getReaderContext().error("Could not find a flow definition at path '" + path + "'", + locationElement); + } } } - return locations; + return (Resource[]) locations.toArray(new Resource[locations.size()]); } } \ No newline at end of file Index: src/main/java/org/springframework/webflow/config/spring-webflow-config-1.1.xsd =================================================================== --- src/main/java/org/springframework/webflow/config/spring-webflow-config-1.1.xsd (revision 7805) +++ src/main/java/org/springframework/webflow/config/spring-webflow-config-1.1.xsd (working copy) @@ -1,356 +0,0 @@ - - - - - - -Provides an easy way to configure a flow executor and an XML flow definition registry. -]]> - - - - - - - - - - - - - - - - - -Each flow definition registered in this registry is assigned a unique identifier. By default, -this identifier is the name of the externalized resource minus its file extension. For example, -a registry containing flow definitions built from the files "orderitem-flow.xml" and "shipping-flow.xml" -would index those definitions by "orderitem-flow" and "shipping-flow" by default. -
-A flow registry is used by a flow executor at runtime to launch new executions of flow definitions. -]]> -
-
- - - - - - - - -Individual paths such as: -
-	/WEB-INF/flows/orderitem-flow.xml
-
-... are supported as well as wildcard paths such as: -
-	/WEB-INF/flows/**/*-flow.xml
-
-]]> -
-
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\ No newline at end of file Index: src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd =================================================================== --- src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd (revision 0) +++ src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd (revision 0) @@ -0,0 +1,408 @@ + + + + + + +Provides an easy way to configure a flow executor and an XML flow definition registry. +]]> + + + + + + + + + + + + + + + + + +Each flow definition registered in this registry is assigned a unique identifier. By default, +this identifier is the name of the externalized resource minus its file extension. For example, +a registry containing flow definitions built from the files "orderitem-flow.xml" and "shipping-flow.xml" +would index those definitions by "orderitem-flow" and "shipping-flow" by default. +
+A flow registry is used by a flow executor at runtime to launch new executions of flow definitions. +]]> +
+
+ + + + + + + + +Individual paths such as: +
+	/WEB-INF/flows/orderitem-flow.xml
+
+... are supported as well as wildcard paths such as: +
+	/WEB-INF/flows/**/*-flow.xml
+
+]]> +
+
+
+ + + + +Individual paths such as: +
+	/WEB-INF/flows/orderitem-flow.xml
+
+... are supported as well as wildcard paths such as: +
+	/WEB-INF/flows/**/*-flow.xml
+
+]]> +
+
+
+
+
+
+
+
+ + + + + + + +Individual paths such as: +
+	/WEB-INF/flows/orderitem-flow.xml
+
+... are supported as well as wildcard paths such as: +
+	/WEB-INF/flows/**/*-flow.xml
+
+]]> +
+
+
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file Index: src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java =================================================================== --- src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java (revision 7805) +++ src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java (working copy) @@ -44,6 +44,7 @@ * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistry * * @author Keith Donald + * @author Ben Hale */ public abstract class ExternalizedFlowDefinitionRegistrar implements FlowDefinitionRegistrar { @@ -48,7 +49,7 @@ public abstract class ExternalizedFlowDefinitionRegistrar implements FlowDefinitionRegistrar { /** - * File locations of externalized flow definition resources to load. A set of {@link Resource}} objects. + * File locations of externalized flow definition resources to load. A set of {@link Resource} objects. */ private Set locations = new HashSet(); @@ -58,6 +59,12 @@ private Set resources = new HashSet(); /** + * A set of mappings between a namespace and a set of externalized flow definitions.. A set of + * {@link NamespaceMapping} objects. + */ + private Set namespaceMappings = new HashSet(); + + /** * 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. @@ -79,6 +86,14 @@ } /** + * Sets the mappings between a namespace and a set of externalized flow definitions. + * @param namespaceMappings the mapping between a namespace and a set of externalized flow definitions + */ + public void setNamespaceMappings(NamespaceMapping[] namespaceMappings) { + this.namespaceMappings = new HashSet(Arrays.asList(namespaceMappings)); + } + + /** * 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 @@ -128,9 +143,29 @@ return this.resources.addAll(Arrays.asList(resources)); } + /** + * Adds a mapping between a namespace and a set of externalized flow definitions. + * @param namespaceMapping the mapping between a namespace and a set of externalized flow definitions + */ + public boolean addNamespaceMapping(NamespaceMapping namespaceMapping) { + return namespaceMappings.add(namespaceMapping); + } + + /** + * Adds mappings between a namespace and a set of externalized flow definitions. + * @param namespaceMappings the mappings between a namespace and a set of externalized flow definitions + */ + public boolean addNamespaceMappings(NamespaceMapping[] namespaceMappings) { + if (namespaceMappings == null) { + return false; + } + return this.namespaceMappings.addAll(Arrays.asList(namespaceMappings)); + } + public void registerFlowDefinitions(FlowDefinitionRegistry registry) { - processLocations(registry); - processResources(registry); + processNamespaceMappings(namespaceMappings, registry); + processLocations(locations, "", registry); + processResources(resources, "", registry); } // internal helpers @@ -136,16 +171,30 @@ // internal helpers /** + * Register the flow definitions in the namespace mappings. + * @param namespaceMappings The namespace mapping to traverse + * @param registry the registry + */ + private void processNamespaceMappings(Set namespaceMappings, FlowDefinitionRegistry registry) { + for (Iterator it = namespaceMappings.iterator(); it.hasNext();) { + NamespaceMapping namespaceMapping = (NamespaceMapping) it.next(); + processLocations(namespaceMapping.getLocations(), namespaceMapping.getNamespace(), registry); + processResources(namespaceMapping.getResources(), namespaceMapping.getNamespace(), registry); + } + } + + /** * Register the flow definitions at the configured file locations. + * @param locations the set of locations + * @param the namespace to register the flow definitions in * @param registry the registry */ - private void processLocations(FlowDefinitionRegistry registry) { - Iterator it = locations.iterator(); - while (it.hasNext()) { + private void processLocations(Set locations, String namespace, FlowDefinitionRegistry registry) { + for (Iterator it = locations.iterator(); it.hasNext();) { Resource location = (Resource) it.next(); if (isFlowDefinitionResource(location)) { FlowDefinitionResource resource = createFlowDefinitionResource(location); - register(resource, registry); + register(resource, namespace, registry); } } } @@ -152,13 +201,14 @@ /** * Register the flow definitions at the configured file locations. + * @param resources the set of resources + * @param the namespace to register the flow definitions in * @param registry the registry */ - private void processResources(FlowDefinitionRegistry registry) { - Iterator it = resources.iterator(); - while (it.hasNext()) { + private void processResources(Set resources, String namespace, FlowDefinitionRegistry registry) { + for (Iterator it = resources.iterator(); it.hasNext();) { FlowDefinitionResource resource = (FlowDefinitionResource) it.next(); - register(resource, registry); + register(resource, namespace, registry); } } @@ -165,10 +215,11 @@ /** * Helper method to register the flow built from an externalized resource in the registry. * @param resource representation of the externalized flow definition resource + * @param namespace the namespace to register the flow in * @param registry the flow registry to register the flow in */ - protected final void register(FlowDefinitionResource resource, FlowDefinitionRegistry registry) { - registry.registerFlowDefinition(createFlowDefinitionHolder(resource)); + protected final void register(FlowDefinitionResource resource, String namespace, FlowDefinitionRegistry registry) { + registry.registerFlowDefinition(createFlowDefinitionHolder(resource), namespace); } // subclassing hooks Index: src/main/java/org/springframework/webflow/definition/registry/NamespaceMapping.java =================================================================== --- src/main/java/org/springframework/webflow/definition/registry/NamespaceMapping.java (revision 0) +++ src/main/java/org/springframework/webflow/definition/registry/NamespaceMapping.java (revision 0) @@ -0,0 +1,163 @@ +/* + * 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 java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.core.io.Resource; + +/** + * A helper class that contains a mapping from a namespace to a set of locations or resources. + * + * @author Ben Hale + */ +public class NamespaceMapping { + + /** + * The namespace to map all flows to. + */ + private String namespace; + + /** + * File locations of externalized flow definition resources to load. A set of {@link Resource} objects. + */ + private Set locations = new HashSet(); + + /** + * A set of formal externalized flow definitions to load. A set of {@link FlowDefinitionResource} objects. + */ + private Set resources = new HashSet(); + + public NamespaceMapping() { + } + + public NamespaceMapping(String namespace, Resource location) { + this.namespace = namespace; + this.locations.add(location); + } + + public NamespaceMapping(String namespace, Resource[] locations) { + this.namespace = namespace; + setLocations(locations); + } + + public NamespaceMapping(String namespace, FlowDefinitionResource resource) { + this.namespace = namespace; + this.resources.add(resource); + } + + /** + * Returns the namespace to map all flows into. + */ + public String getNamespace() { + return namespace; + } + + /** + * Sets the namespace to map all flows into. + * @param namespace the namespace name + */ + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + /** + * Returns the locations (file paths) pointing to externalized flow definitions. + */ + public Set getLocations() { + return locations; + } + + /** + * 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 + */ + public void setLocations(Resource[] locations) { + this.locations = new HashSet(Arrays.asList(locations)); + } + + /** + * Returns the set of externalized flow definitions. + */ + public Set getResources() { + return resources; + } + + /** + * 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 + */ + public void setResources(FlowDefinitionResource[] resources) { + this.resources = new HashSet(Arrays.asList(resources)); + } + + /** + * 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 + */ + public boolean addLocation(Resource location) { + return locations.add(location); + } + + /** + * 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 + */ + public boolean addLocations(Resource[] locations) { + if (locations == null) { + return false; + } + return this.locations.addAll(Arrays.asList(locations)); + } + + /** + * 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 + */ + public boolean addResource(FlowDefinitionResource resource) { + return resources.add(resource); + } + + /** + * 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 + */ + public boolean addResources(FlowDefinitionResource[] resources) { + if (resources == null) { + return false; + } + return this.resources.addAll(Arrays.asList(resources)); + } +} Index: src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java =================================================================== --- src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java (revision 7805) +++ src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java (working copy) @@ -68,8 +68,9 @@ private DocumentLoader documentLoader; /** - * Creates a new XML flow registrar. Protected constructor - if used, make sure the required - * {@link #flowServiceLocator} reference is set. + * Creates a new XML flow registrar. Protected constructor - if used, make sure the + * {@link #setFlowServiceLocator(FlowServiceLocator)} method is called to set the required flowServiceLocator + * reference. */ protected XmlFlowRegistrar() { } Index: src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java =================================================================== --- src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java (revision 7805) +++ src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java (working copy) @@ -25,6 +25,7 @@ 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.definition.registry.NamespaceMapping; import org.springframework.webflow.engine.builder.AbstractFlowBuildingFlowRegistryFactoryBean; import org.springframework.webflow.engine.builder.DefaultFlowServiceLocator; import org.springframework.webflow.engine.builder.FlowServiceLocator; @@ -56,6 +57,7 @@ * * * @author Keith Donald + * @author Ben Hale */ public class XmlFlowRegistryFactoryBean extends AbstractFlowBuildingFlowRegistryFactoryBean { @@ -70,6 +72,11 @@ private Resource[] locations; /** + * Temporary holder for namespace mappings. + */ + private NamespaceMapping[] namespaceMappings; + + /** * Temporary holder for flow definitions configured using a property map. */ private Properties flowDefinitions; @@ -118,7 +125,7 @@ * * * Flows registered from this set will be automatically assigned an id based on the filename of the matched XML - * resource. + * resource and be registered in the root namespace. * @param locations the resource locations */ public void setFlowLocations(Resource[] locations) { @@ -126,6 +133,17 @@ } /** + * Sets the namespace mappings (namespace name to resource file paths) pointing to XML-based flow definitions. + *

+ * Flows registered from this set will be automatically assigned an id based on the filename of the matched XML + * resource and be registered in the declared namespace. + * @param namespaceMappings the namespace mappings + */ + public void setFlowNamespaceMappings(NamespaceMapping[] namespaceMappings) { + this.namespaceMappings = namespaceMappings; + } + + /** * 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. *

@@ -189,6 +207,7 @@ protected void doPopulate(FlowDefinitionRegistry registry) { addFlowDefinitionLocations(); addFlowDefinitionsFromProperties(); + addNamespaceMappings(); getXmlFlowRegistrar().registerFlowDefinitions(registry); } @@ -197,6 +216,7 @@ */ private void addFlowDefinitionLocations() { if (locations != null) { + for (int i = 0; i < locations.length; i++) { String flowId = FlowDefinitionResource.conventionalFlowId(locations[i]); getXmlFlowRegistrar().addResource( @@ -223,6 +243,15 @@ } /** + * Add flow namespace mappings to the flow definition registrar. + */ + private void addNamespaceMappings() { + if (namespaceMappings != null) { + getXmlFlowRegistrar().setNamespaceMappings(namespaceMappings); + } + } + + /** * Returns the flow attributes to be assigned to the flow with given id. Returns null if no attributes should be * assigned. */ Index: src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml =================================================================== --- src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml (revision 7805) +++ src/test/java/org/springframework/webflow/config/webflow-config-namespace.xml (working copy) @@ -6,7 +6,7 @@ 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"> @@ -17,8 +17,29 @@ - - + + + + + + + + + + + + + + + + + + + + + + + Index: src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java =================================================================== --- src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java (revision 7805) +++ src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java (working copy) @@ -70,6 +70,25 @@ assertEquals("Incorrect number of flows loaded", 0, registry.getFlowDefinitionCount()); } + public void testRegistryWithNamespace() { + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withNamespace"); + assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount()); + assertTrue("Incorrect path", registry.containsFlowDefinition("/namespace/flow1")); + } + + public void testRegistryWithMultipleNamespace() { + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withMultipleNamespace"); + assertEquals("Incorrect number of flows loaded", 2, registry.getFlowDefinitionCount()); + assertTrue("Incorrect path", registry.containsFlowDefinition("/namespace1/flow1")); + assertTrue("Incorrect path", registry.containsFlowDefinition("/namespace2/flow1")); + } + + public void testRegistryWithNamespaceWithWildCards() { + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory + .getBean("withNamespaceWithWildcards"); + assertEquals("Incorrect number of flows loaded", 0, registry.getFlowDefinitionCount()); + } + public void testDefaultExecutor() { FlowExecutorImpl flowExecutor = (FlowExecutorImpl) this.beanFactory.getBean("defaultExecutor"); assertTrue(flowExecutor.getExecutionRepository() instanceof ContinuationFlowExecutionRepository); Index: src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java =================================================================== --- src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java (revision 7805) +++ src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrarTests.java (working copy) @@ -21,9 +21,11 @@ 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.definition.registry.NamespaceMapping; import org.springframework.webflow.engine.builder.BaseFlowServiceLocator; public class XmlFlowRegistrarTests extends TestCase { + private XmlFlowRegistrar registrar; private FlowDefinitionRegistry registry = new FlowDefinitionRegistryImpl(); @@ -35,7 +37,7 @@ public void testAddLocation() { assertEquals(0, registry.getFlowDefinitionCount()); - registrar.addLocation(new ClassPathResource("flow.xml", getClass())); + registrar.addLocation(getLocation()); registrar.registerFlowDefinitions(registry); assertEquals(1, registry.getFlowDefinitionCount()); assertEquals("flow", registry.getFlowDefinition("flow").getId()); @@ -43,7 +45,7 @@ public void testAddResource() { assertEquals(0, registry.getFlowDefinitionCount()); - registrar.addResource(new FlowDefinitionResource("foo", new ClassPathResource("flow.xml", getClass()))); + registrar.addResource(getResource()); registrar.registerFlowDefinitions(registry); assertEquals(1, registry.getFlowDefinitionCount()); assertEquals("foo", registry.getFlowDefinition("foo").getId()); @@ -48,4 +50,32 @@ assertEquals(1, registry.getFlowDefinitionCount()); assertEquals("foo", registry.getFlowDefinition("foo").getId()); } + + public void testAddNamespaceMappingLocation() { + assertEquals(0, registry.getFlowDefinitionCount()); + registrar.addNamespaceMapping(getNamespaceMapping()); + registrar.registerFlowDefinitions(registry); + assertEquals(1, registry.getFlowDefinitionCount()); + assertEquals("flow", registry.getFlowDefinition("/namespace/flow").getId()); + } + + public void testAddNamespaceMappingResource() { + assertEquals(0, registry.getFlowDefinitionCount()); + registrar.addNamespaceMapping(new NamespaceMapping("/namespace", getResource())); + registrar.registerFlowDefinitions(registry); + assertEquals(1, registry.getFlowDefinitionCount()); + assertEquals("foo", registry.getFlowDefinition("/namespace/foo").getId()); + } + + private ClassPathResource getLocation() { + return new ClassPathResource("flow.xml", getClass()); + } + + private FlowDefinitionResource getResource() { + return new FlowDefinitionResource("foo", getLocation()); + } + + private NamespaceMapping getNamespaceMapping() { + return new NamespaceMapping("/namespace", getLocation()); + } } \ No newline at end of file Index: src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanTests.java =================================================================== --- src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanTests.java (revision 7805) +++ src/test/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBeanTests.java (working copy) @@ -22,6 +22,7 @@ import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.NamespaceMapping; public class XmlFlowRegistryFactoryBeanTests extends TestCase { private XmlFlowRegistryFactoryBean factoryBean = new XmlFlowRegistryFactoryBean(); @@ -27,7 +28,7 @@ private XmlFlowRegistryFactoryBean factoryBean = new XmlFlowRegistryFactoryBean(); public void testCreateFromLocations() throws Exception { - ClassPathResource[] locations = new ClassPathResource[] { new ClassPathResource("flow.xml", getClass()) }; + ClassPathResource[] locations = new ClassPathResource[] { getLocation() }; factoryBean.setFlowLocations(locations); factoryBean.setBeanFactory(new StaticListableBeanFactory()); factoryBean.afterPropertiesSet(); @@ -36,6 +37,16 @@ assertEquals("flow", registry.getFlowDefinition("flow").getId()); } + public void testCreateFromNamespaceMappings() throws Exception { + NamespaceMapping[] namespaceMappings = new NamespaceMapping[] { getNamespaceMapping() }; + factoryBean.setFlowNamespaceMappings(namespaceMappings); + factoryBean.setBeanFactory(new StaticListableBeanFactory()); + factoryBean.afterPropertiesSet(); + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject(); + assertEquals(1, registry.getFlowDefinitionCount()); + assertEquals("flow", registry.getFlowDefinition("/namespace/flow").getId()); + } + public void testCreateFromDefinitions() throws Exception { Properties properties = new Properties(); properties.put("foo", "classpath:/org/springframework/webflow/engine/builder/xml/flow.xml"); @@ -46,4 +57,12 @@ assertEquals(1, registry.getFlowDefinitionCount()); assertEquals("foo", registry.getFlowDefinition("foo").getId()); } + + private ClassPathResource getLocation() { + return new ClassPathResource("flow.xml", getClass()); + } + + private NamespaceMapping getNamespaceMapping() { + return new NamespaceMapping("/namespace", getLocation()); + } }