001: /*
002: * Copyright 2004-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.springframework.webflow.engine.builder.xml;
017:
018: import org.springframework.core.io.Resource;
019: import org.springframework.util.Assert;
020: import org.springframework.webflow.definition.registry.ExternalizedFlowDefinitionRegistrar;
021: import org.springframework.webflow.definition.registry.FlowDefinitionHolder;
022: import org.springframework.webflow.definition.registry.FlowDefinitionResource;
023: import org.springframework.webflow.engine.builder.FlowAssembler;
024: import org.springframework.webflow.engine.builder.FlowBuilder;
025: import org.springframework.webflow.engine.builder.FlowServiceLocator;
026: import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolder;
027:
028: /**
029: * A flow definition registrar that populates a flow definition registry with
030: * flow definitions defined in externalized XML resources. Typically used in
031: * conjunction with a {@link XmlFlowRegistryFactoryBean} but may also be used
032: * standalone in programmatic fashion.
033: * <p>
034: * By default, a flow definition registered by this registrar will be assigned a
035: * registry identifier equal to the filename of the underlying definition
036: * resource, minus the filename extension. For example, a XML-based flow
037: * definition defined in the file "flow1.xml" will be identified as "flow1" when
038: * registered in a registry.
039: * <p>
040: * Programmatic usage example:
041: *
042: * <pre class="code">
043: * BeanFactory beanFactory = ...
044: * FlowDefinitionRegistry registry = new FlowDefinitionRegistryImpl();
045: * FlowServiceLocator flowServiceLocator =
046: * new DefaultFlowServiceLocator(registry, beanFactory);
047: * XmlFlowRegistrar registrar = new XmlFlowRegistrar(flowServiceLocator);
048: * File parent = new File("src/webapp/WEB-INF");
049: * registrar.addLocation(new FileSystemResource(new File(parent, "flow1.xml"));
050: * registrar.addLocation(new FileSystemResource(new File(parent, "flow2.xml"));
051: * registrar.registerFlowDefinitions(registry);
052: * </pre>
053: *
054: * @author Keith Donald
055: */
056: public class XmlFlowRegistrar extends
057: ExternalizedFlowDefinitionRegistrar {
058:
059: /**
060: * The xml file suffix constant.
061: */
062: private static final String XML_SUFFIX = ".xml";
063:
064: /**
065: * The locator of services needed by flow definitions.
066: */
067: private FlowServiceLocator flowServiceLocator;
068:
069: /**
070: * The loader of XML-based flow definition documents.
071: */
072: private DocumentLoader documentLoader;
073:
074: /**
075: * Creates a new XML flow registrar. Protected constructor - if used, make
076: * sure the required {@link #flowServiceLocator} reference is set.
077: */
078: protected XmlFlowRegistrar() {
079: }
080:
081: /**
082: * Creates a new XML flow registrar.
083: * @param flowServiceLocator the locator needed to support flow definition
084: * assembly
085: */
086: public XmlFlowRegistrar(FlowServiceLocator flowServiceLocator) {
087: setFlowServiceLocator(flowServiceLocator);
088: }
089:
090: /**
091: * Sets the flow service locator.
092: * @param flowServiceLocator the flow service locator (may not be null)
093: */
094: protected void setFlowServiceLocator(
095: FlowServiceLocator flowServiceLocator) {
096: Assert.notNull(flowServiceLocator,
097: "The flow service locator is required");
098: this .flowServiceLocator = flowServiceLocator;
099: }
100:
101: /**
102: * Returns the flow service locator.
103: */
104: protected FlowServiceLocator getFlowServiceLocator() {
105: return flowServiceLocator;
106: }
107:
108: /**
109: * Sets the loader to load XML-based flow definition documents during flow
110: * definition assembly. Allows for customization over how documents are
111: * loaded. Optional.
112: * @param documentLoader the document loader
113: */
114: public void setDocumentLoader(DocumentLoader documentLoader) {
115: this .documentLoader = documentLoader;
116: }
117:
118: /**
119: * Returns the loader of XML-based flow definition documents.
120: */
121: public DocumentLoader getDocumentLoader() {
122: return documentLoader;
123: }
124:
125: protected boolean isFlowDefinitionResource(Resource resource) {
126: return resource.getFilename().endsWith(XML_SUFFIX);
127: }
128:
129: protected FlowDefinitionHolder createFlowDefinitionHolder(
130: FlowDefinitionResource resource) {
131: FlowBuilder builder = createFlowBuilder(resource.getLocation());
132: FlowAssembler assembler = new FlowAssembler(resource.getId(),
133: resource.getAttributes(), builder);
134: return new RefreshableFlowDefinitionHolder(assembler);
135: }
136:
137: // hook methods
138:
139: /**
140: * Factory method that creates and fully initializes the XML-based flow
141: * definition builder.
142: * @param location the xml-based resource
143: * @return the builder to build the flow definition from the resource.
144: */
145: protected FlowBuilder createFlowBuilder(Resource location) {
146: XmlFlowBuilder builder = new XmlFlowBuilder(location,
147: getFlowServiceLocator());
148: if (documentLoader != null) {
149: builder.setDocumentLoader(documentLoader);
150: }
151: return builder;
152: }
153: }
|