|
|
|
|
@@ -25,6 +25,7 @@ import java.util.List;
|
|
|
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.BeanFactory;
|
|
|
|
|
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
|
|
|
|
import org.springframework.binding.convert.ConversionExecutor;
|
|
|
|
|
import org.springframework.binding.convert.ConversionService;
|
|
|
|
|
import org.springframework.binding.expression.Expression;
|
|
|
|
|
@@ -38,11 +39,15 @@ import org.springframework.binding.mapping.RequiredMapping;
|
|
|
|
|
import org.springframework.binding.method.MethodSignature;
|
|
|
|
|
import org.springframework.binding.method.Parameter;
|
|
|
|
|
import org.springframework.binding.method.Parameters;
|
|
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
|
|
import org.springframework.context.support.GenericApplicationContext;
|
|
|
|
|
import org.springframework.core.io.Resource;
|
|
|
|
|
import org.springframework.core.style.ToStringCreator;
|
|
|
|
|
import org.springframework.util.Assert;
|
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
import org.springframework.util.xml.DomUtils;
|
|
|
|
|
import org.springframework.web.context.WebApplicationContext;
|
|
|
|
|
import org.springframework.web.context.support.GenericWebApplicationContext;
|
|
|
|
|
import org.springframework.webflow.action.ActionResultExposer;
|
|
|
|
|
import org.springframework.webflow.action.EvaluateAction;
|
|
|
|
|
import org.springframework.webflow.action.SetAction;
|
|
|
|
|
@@ -78,34 +83,29 @@ import org.w3c.dom.NodeList;
|
|
|
|
|
import org.xml.sax.SAXException;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Flow builder that builds flows as defined in an XML document. The XML document
|
|
|
|
|
* should adhere to the following format:
|
|
|
|
|
*
|
|
|
|
|
* Flow builder that builds flows as defined in an XML document. The XML document should adhere to the following format:
|
|
|
|
|
*
|
|
|
|
|
* <pre>
|
|
|
|
|
* <?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
* <flow xmlns="http://www.springframework.org/schema/webflow"
|
|
|
|
|
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
|
|
|
* xsi:schemaLocation="http://www.springframework.org/schema/webflow
|
|
|
|
|
* http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* <!-- Define your states here -->
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* </flow>
|
|
|
|
|
* </pre>
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* <p>
|
|
|
|
|
* Consult the <a
|
|
|
|
|
* href="http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">webflow
|
|
|
|
|
* XML schema</a> for more information on the XML-based flow definition format.
|
|
|
|
|
* Consult the <a href="http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">web flow XML schema</a>
|
|
|
|
|
* for more information on the XML-based flow definition format.
|
|
|
|
|
* <p>
|
|
|
|
|
* This builder will setup a flow-local bean factory for the flow being
|
|
|
|
|
* constructed. That flow-local bean factory will be populated with XML bean
|
|
|
|
|
* definitions contained in files referenced using the "import" element. The
|
|
|
|
|
* flow-local bean factory will use the bean factory defing this flow builder as
|
|
|
|
|
* a parent. As such, the flow can access artifacts in either its flow-local
|
|
|
|
|
* bean factory or in the parent bean factory hierarchy, e.g. the bean factory
|
|
|
|
|
* of the dispatcher.
|
|
|
|
|
*
|
|
|
|
|
* This builder will setup a flow-local bean factory for the flow being constructed. That flow-local bean factory will
|
|
|
|
|
* be populated with XML bean definitions contained in files referenced using the "import" element. The flow-local bean
|
|
|
|
|
* factory will use the bean factory defing this flow builder as a parent. As such, the flow can access artifacts in
|
|
|
|
|
* either its flow-local bean factory or in the parent bean factory hierarchy, e.g. the bean factory of the dispatcher.
|
|
|
|
|
*
|
|
|
|
|
* @author Erwin Vervaet
|
|
|
|
|
* @author Keith Donald
|
|
|
|
|
*/
|
|
|
|
|
@@ -238,15 +238,14 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private static final String RESOURCE_ATTRIBUTE = "resource";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The resource from which the document element being parsed was read. Used
|
|
|
|
|
* as a location for relative resource lookup.
|
|
|
|
|
* The resource from which the document element being parsed was read. Used as a location for relative resource
|
|
|
|
|
* lookup.
|
|
|
|
|
*/
|
|
|
|
|
protected Resource location;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A flow service locator local to this builder that first looks in a
|
|
|
|
|
* locally-managed Spring application context for services before searching
|
|
|
|
|
* the externally managed {@link #getFlowServiceLocator()}.
|
|
|
|
|
* A flow service locator local to this builder that first looks in a locally-managed Spring bean factory for
|
|
|
|
|
* services before searching the externally managed {@link #getFlowServiceLocator() service locator}.
|
|
|
|
|
*/
|
|
|
|
|
private LocalFlowServiceLocator localFlowServiceLocator;
|
|
|
|
|
|
|
|
|
|
@@ -256,14 +255,12 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private DocumentLoader documentLoader = new DefaultDocumentLoader();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The in-memory document object model (DOM) of the XML Document read from
|
|
|
|
|
* the flow definition resource.
|
|
|
|
|
* The in-memory document object model (DOM) of the XML Document read from the flow definition resource.
|
|
|
|
|
*/
|
|
|
|
|
private Document document;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new XML flow builder parsing the document at the specified
|
|
|
|
|
* location.
|
|
|
|
|
* Create a new XML flow builder parsing the document at the specified location.
|
|
|
|
|
* @param location the location of the XML-based flow definition resource
|
|
|
|
|
*/
|
|
|
|
|
public XmlFlowBuilder(Resource location) {
|
|
|
|
|
@@ -271,12 +268,10 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new XML flow builder parsing the document at the specified
|
|
|
|
|
* location, using the provided service locator to access externally managed
|
|
|
|
|
* flow artifacts.
|
|
|
|
|
* Create a new XML flow builder parsing the document at the specified location, using the provided service locator
|
|
|
|
|
* to access externally managed flow artifacts.
|
|
|
|
|
* @param location the location of the XML-based flow definition resource
|
|
|
|
|
* @param flowServiceLocator the locator for services needed by this builder
|
|
|
|
|
* to build its Flow
|
|
|
|
|
* @param flowServiceLocator the locator for services needed by this builder to build its Flow
|
|
|
|
|
*/
|
|
|
|
|
public XmlFlowBuilder(Resource location, FlowServiceLocator flowServiceLocator) {
|
|
|
|
|
super(flowServiceLocator);
|
|
|
|
|
@@ -284,16 +279,16 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the resource from which the document element was loaded. This is
|
|
|
|
|
* used for location relative loading of other resources.
|
|
|
|
|
* Returns the resource from which the document element was loaded. This is used for location relative loading of
|
|
|
|
|
* other resources.
|
|
|
|
|
*/
|
|
|
|
|
public Resource getLocation() {
|
|
|
|
|
return location;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the resource from which the document element was loaded. This is
|
|
|
|
|
* used for location relative loading of other resources.
|
|
|
|
|
* Sets the resource from which the document element was loaded. This is used for location relative loading of other
|
|
|
|
|
* resources.
|
|
|
|
|
*/
|
|
|
|
|
public void setLocation(Resource location) {
|
|
|
|
|
Assert.notNull(location, "The resource location of the XML-based flow definition is required");
|
|
|
|
|
@@ -301,8 +296,8 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the loader that will load the XML-based flow definition document.
|
|
|
|
|
* Optional, defaults to {@link DefaultDocumentLoader}.
|
|
|
|
|
* Sets the loader that will load the XML-based flow definition document. Optional, defaults to
|
|
|
|
|
* {@link DefaultDocumentLoader}.
|
|
|
|
|
* @param documentLoader the document loader
|
|
|
|
|
*/
|
|
|
|
|
public void setDocumentLoader(DocumentLoader documentLoader) {
|
|
|
|
|
@@ -381,7 +376,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
public Resource getResource() {
|
|
|
|
|
return location;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// helpers
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -406,8 +401,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the artifact factory of the flow service locator local
|
|
|
|
|
* to this builder.
|
|
|
|
|
* Returns the artifact factory of the flow service locator local to this builder.
|
|
|
|
|
*/
|
|
|
|
|
protected FlowArtifactFactory getFlowArtifactFactory() {
|
|
|
|
|
return getLocalFlowServiceLocator().getFlowArtifactFactory();
|
|
|
|
|
@@ -416,28 +410,25 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
// utility (from Spring 2.x DomUtils)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Utility method that returns the first child element identified by its
|
|
|
|
|
* name.
|
|
|
|
|
* Utility method that returns the first child element identified by its name.
|
|
|
|
|
* @param ele the DOM element to analyze
|
|
|
|
|
* @param childEleName the child element name to look for
|
|
|
|
|
* @return the <code>org.w3c.dom.Element</code> instance, or
|
|
|
|
|
* <code>null</code> if none found
|
|
|
|
|
* @return the <code>org.w3c.dom.Element</code> instance, or <code>null</code> if none found
|
|
|
|
|
*/
|
|
|
|
|
protected Element getChildElementByTagName(Element ele, String childEleName) {
|
|
|
|
|
NodeList nl = ele.getChildNodes();
|
|
|
|
|
for (int i = 0; i < nl.getLength(); i++) {
|
|
|
|
|
Node node = nl.item(i);
|
|
|
|
|
if (node instanceof Element && nodeNameEquals(node, childEleName)) {
|
|
|
|
|
return (Element)node;
|
|
|
|
|
return (Element) node;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Namespace-aware equals comparison. Returns <code>true</code> if either
|
|
|
|
|
* {@link Node#getLocalName} or {@link Node#getNodeName} equals
|
|
|
|
|
* <code>desiredName</code>, otherwise returns <code>false</code>.
|
|
|
|
|
* Namespace-aware equals comparison. Returns <code>true</code> if either {@link Node#getLocalName} or
|
|
|
|
|
* {@link Node#getNodeName} equals <code>desiredName</code>, otherwise returns <code>false</code>.
|
|
|
|
|
*/
|
|
|
|
|
protected boolean nodeNameEquals(Node node, String desiredName) {
|
|
|
|
|
return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName());
|
|
|
|
|
@@ -462,7 +453,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
List importElements = DomUtils.getChildElementsByTagName(flowElement, IMPORT_ELEMENT);
|
|
|
|
|
Resource[] resources = new Resource[importElements.size()];
|
|
|
|
|
for (int i = 0; i < importElements.size(); i++) {
|
|
|
|
|
Element importElement = (Element)importElements.get(i);
|
|
|
|
|
Element importElement = (Element) importElements.get(i);
|
|
|
|
|
try {
|
|
|
|
|
resources[i] = getLocation().createRelative(importElement.getAttribute(RESOURCE_ATTRIBUTE));
|
|
|
|
|
}
|
|
|
|
|
@@ -471,7 +462,57 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
+ importElement.getAttribute(RESOURCE_ATTRIBUTE) + "'", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
localFlowServiceLocator.push(new LocalFlowServiceRegistry(flow, resources));
|
|
|
|
|
localFlowServiceLocator.push(new LocalFlowServiceRegistry(flow, createLocalBeanFactory(flow, resources)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create the local bean factory from the resources provided. This factory typcially houses services needed
|
|
|
|
|
* locally by the flow definition.
|
|
|
|
|
* <p>
|
|
|
|
|
* Subclasses may override this metod to customize the population of the context local to the flow definition
|
|
|
|
|
* being built, registering mock implementations of services for a test environment.
|
|
|
|
|
* @param flow the current flow definition being built
|
|
|
|
|
* @param resources the file resources to assemble the bean factory from; typically XML-based
|
|
|
|
|
* @return the bean factory
|
|
|
|
|
* @since 1.0.4
|
|
|
|
|
*/
|
|
|
|
|
protected BeanFactory createLocalBeanFactory(Flow flow, Resource[] resources) {
|
|
|
|
|
// see if this factory has a parent
|
|
|
|
|
BeanFactory parent = null;
|
|
|
|
|
if (localFlowServiceLocator.isEmpty()) {
|
|
|
|
|
try {
|
|
|
|
|
parent = getFlowServiceLocator().getBeanFactory();
|
|
|
|
|
}
|
|
|
|
|
catch (UnsupportedOperationException e) {
|
|
|
|
|
// can't link to a parent
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
parent = localFlowServiceLocator.top().getBeanFactory();
|
|
|
|
|
}
|
|
|
|
|
// determine the context implementation based on the current environment
|
|
|
|
|
GenericApplicationContext context;
|
|
|
|
|
if (parent instanceof WebApplicationContext) {
|
|
|
|
|
GenericWebApplicationContext webContext = new GenericWebApplicationContext();
|
|
|
|
|
webContext.setServletContext(((WebApplicationContext) parent).getServletContext());
|
|
|
|
|
context = webContext;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
context = new GenericApplicationContext();
|
|
|
|
|
}
|
|
|
|
|
// set the parent if necessary
|
|
|
|
|
if (parent instanceof ApplicationContext) {
|
|
|
|
|
context.setParent((ApplicationContext) parent);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (parent != null) {
|
|
|
|
|
context.getBeanFactory().setParentBeanFactory(parent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
context.setResourceLoader(getFlowServiceLocator().getResourceLoader());
|
|
|
|
|
new XmlBeanDefinitionReader(context).loadBeanDefinitions(resources);
|
|
|
|
|
context.refresh();
|
|
|
|
|
return context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void destroyLocalServiceRegistry() {
|
|
|
|
|
@@ -481,7 +522,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private void parseAndAddFlowVariables(Element flowElement, Flow flow) {
|
|
|
|
|
List varElements = DomUtils.getChildElementsByTagName(flowElement, VAR_ELEMENT);
|
|
|
|
|
for (Iterator it = varElements.iterator(); it.hasNext();) {
|
|
|
|
|
flow.addVariable(parseVariable((Element)it.next()));
|
|
|
|
|
flow.addVariable(parseVariable((Element) it.next()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -494,7 +535,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (StringUtils.hasText(element.getAttribute(CLASS_ATTRIBUTE))) {
|
|
|
|
|
Class variableClass = (Class)fromStringTo(Class.class).execute(element.getAttribute(CLASS_ATTRIBUTE));
|
|
|
|
|
Class variableClass = (Class) fromStringTo(Class.class).execute(element.getAttribute(CLASS_ATTRIBUTE));
|
|
|
|
|
return new SimpleFlowVariable(element.getAttribute(NAME_ATTRIBUTE), variableClass, scope);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
@@ -528,7 +569,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private void parseAndAddInlineFlowDefinitions(Element parentFlowElement, Flow flow) {
|
|
|
|
|
List inlineFlowElements = DomUtils.getChildElementsByTagName(parentFlowElement, INLINE_FLOW_ELEMENT);
|
|
|
|
|
for (Iterator it = inlineFlowElements.iterator(); it.hasNext();) {
|
|
|
|
|
Element inlineFlowElement = (Element)it.next();
|
|
|
|
|
Element inlineFlowElement = (Element) it.next();
|
|
|
|
|
String inlineFlowId = inlineFlowElement.getAttribute(ID_ATTRIBUTE);
|
|
|
|
|
Element flowElement = getChildElementByTagName(inlineFlowElement, FLOW_ATTRIBUTE);
|
|
|
|
|
Flow inlineFlow = parseFlow(inlineFlowId, null, flowElement);
|
|
|
|
|
@@ -547,7 +588,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
parseAndAddEndActions(flowElement, inlineFlow);
|
|
|
|
|
inlineFlow.setOutputMapper(parseOutputMapper(flowElement));
|
|
|
|
|
inlineFlow.getExceptionHandlerSet().addAll(parseExceptionHandlers(flowElement));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
destroyLocalServiceRegistry();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -556,7 +597,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
for (int i = 0; i < childNodeList.getLength(); i++) {
|
|
|
|
|
Node childNode = childNodeList.item(i);
|
|
|
|
|
if (childNode instanceof Element) {
|
|
|
|
|
Element stateElement = (Element)childNode;
|
|
|
|
|
Element stateElement = (Element) childNode;
|
|
|
|
|
if (nodeNameEquals(stateElement, ACTION_STATE_ELEMENT)) {
|
|
|
|
|
parseAndAddActionState(stateElement, flow);
|
|
|
|
|
}
|
|
|
|
|
@@ -588,13 +629,15 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void parseAndAddActionState(Element element, Flow flow) {
|
|
|
|
|
getFlowArtifactFactory().createActionState(parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
getFlowArtifactFactory().createActionState(
|
|
|
|
|
parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
parseAnnotatedActions(element), parseTransitions(element), parseExceptionHandlers(element),
|
|
|
|
|
parseExitActions(element), parseAttributes(element));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void parseAndAddViewState(Element element, Flow flow) {
|
|
|
|
|
getFlowArtifactFactory().createViewState(parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
getFlowArtifactFactory().createViewState(
|
|
|
|
|
parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
parseViewSelector(element), parseRenderActions(element), parseTransitions(element),
|
|
|
|
|
parseExceptionHandlers(element), parseExitActions(element), parseAttributes(element));
|
|
|
|
|
}
|
|
|
|
|
@@ -606,13 +649,15 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void parseAndAddSubflowState(Element element, Flow flow) {
|
|
|
|
|
getFlowArtifactFactory().createSubflowState(parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
getFlowArtifactFactory().createSubflowState(
|
|
|
|
|
parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
parseSubflow(element), parseFlowAttributeMapper(element), parseTransitions(element),
|
|
|
|
|
parseExceptionHandlers(element), parseExitActions(element), parseAttributes(element));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void parseAndAddEndState(Element element, Flow flow) {
|
|
|
|
|
getFlowArtifactFactory().createEndState(parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
getFlowArtifactFactory().createEndState(
|
|
|
|
|
parseId(element), flow, parseEntryActions(element),
|
|
|
|
|
parseViewSelector(element), parseOutputMapper(element), parseExceptionHandlers(element),
|
|
|
|
|
parseAttributes(element));
|
|
|
|
|
}
|
|
|
|
|
@@ -655,29 +700,29 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
List transitions = new LinkedList();
|
|
|
|
|
List transitionElements = DomUtils.getChildElementsByTagName(element, TRANSITION_ELEMENT);
|
|
|
|
|
for (Iterator it = transitionElements.iterator(); it.hasNext();) {
|
|
|
|
|
Element transitionElement = (Element)it.next();
|
|
|
|
|
Element transitionElement = (Element) it.next();
|
|
|
|
|
if (!StringUtils.hasText(transitionElement.getAttribute(ON_EXCEPTION_ATTRIBUTE))) {
|
|
|
|
|
// the "on-exception transition" is not really a transition but rather
|
|
|
|
|
// a FlowExecutionExceptionHandler (see parseTransitionExecutingExceptionHandlers)
|
|
|
|
|
transitions.add(parseTransition(transitionElement));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (Transition[])transitions.toArray(new Transition[transitions.size()]);
|
|
|
|
|
return (Transition[]) transitions.toArray(new Transition[transitions.size()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Transition parseTransition(Element element) {
|
|
|
|
|
TransitionCriteria matchingCriteria = (TransitionCriteria)fromStringTo(TransitionCriteria.class).execute(
|
|
|
|
|
element.getAttribute(ON_ATTRIBUTE));
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver)fromStringTo(TargetStateResolver.class).execute(
|
|
|
|
|
element.getAttribute(TO_ATTRIBUTE));
|
|
|
|
|
TransitionCriteria matchingCriteria = (TransitionCriteria)
|
|
|
|
|
fromStringTo(TransitionCriteria.class).execute(element.getAttribute(ON_ATTRIBUTE));
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver)
|
|
|
|
|
fromStringTo(TargetStateResolver.class).execute(element.getAttribute(TO_ATTRIBUTE));
|
|
|
|
|
TransitionCriteria executionCriteria = TransitionCriteriaChain.criteriaChainFor(parseAnnotatedActions(element));
|
|
|
|
|
return getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria, executionCriteria,
|
|
|
|
|
parseAttributes(element));
|
|
|
|
|
return getFlowArtifactFactory().createTransition(
|
|
|
|
|
targetStateResolver, matchingCriteria, executionCriteria, parseAttributes(element));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ViewSelector parseViewSelector(Element element) {
|
|
|
|
|
String viewName = element.getAttribute(VIEW_ATTRIBUTE);
|
|
|
|
|
return (ViewSelector)fromStringTo(ViewSelector.class).execute(viewName);
|
|
|
|
|
return (ViewSelector) fromStringTo(ViewSelector.class).execute(viewName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Flow parseSubflow(Element element) {
|
|
|
|
|
@@ -687,30 +732,30 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private AnnotatedAction[] parseAnnotatedActions(Element element) {
|
|
|
|
|
List actions = new LinkedList();
|
|
|
|
|
NodeList childNodeList = element.getChildNodes();
|
|
|
|
|
for (int i=0; i < childNodeList.getLength(); i++) {
|
|
|
|
|
for (int i = 0; i < childNodeList.getLength(); i++) {
|
|
|
|
|
Node childNode = childNodeList.item(i);
|
|
|
|
|
if (!(childNode instanceof Element)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeNameEquals(childNode, ACTION_ELEMENT)) {
|
|
|
|
|
// parse standard action
|
|
|
|
|
actions.add(parseAnnotatedAction((Element)childNode));
|
|
|
|
|
actions.add(parseAnnotatedAction((Element) childNode));
|
|
|
|
|
}
|
|
|
|
|
else if (nodeNameEquals(childNode, BEAN_ACTION_ELEMENT)) {
|
|
|
|
|
// parse bean invoking action
|
|
|
|
|
actions.add(parseAnnotatedBeanInvokingAction((Element)childNode));
|
|
|
|
|
actions.add(parseAnnotatedBeanInvokingAction((Element) childNode));
|
|
|
|
|
}
|
|
|
|
|
else if (nodeNameEquals(childNode, EVALUATE_ACTION_ELEMENT)) {
|
|
|
|
|
// parse evaluate action
|
|
|
|
|
actions.add(parseAnnotatedEvaluateAction((Element)childNode));
|
|
|
|
|
actions.add(parseAnnotatedEvaluateAction((Element) childNode));
|
|
|
|
|
}
|
|
|
|
|
else if (nodeNameEquals(childNode, SET_ELEMENT)) {
|
|
|
|
|
// parse set action
|
|
|
|
|
actions.add(parseAnnotatedSetAction((Element)childNode));
|
|
|
|
|
actions.add(parseAnnotatedSetAction((Element) childNode));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (AnnotatedAction[])actions.toArray(new AnnotatedAction[actions.size()]);
|
|
|
|
|
return (AnnotatedAction[]) actions.toArray(new AnnotatedAction[actions.size()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private AnnotatedAction parseAnnotatedAction(Element element) {
|
|
|
|
|
@@ -759,12 +804,13 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
Parameters parameters = new Parameters();
|
|
|
|
|
Iterator it = DomUtils.getChildElementsByTagName(methodArgumentsElement, ARGUMENT_ELEMENT).iterator();
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
Element argumentElement = (Element)it.next();
|
|
|
|
|
Expression name = getLocalFlowServiceLocator().getExpressionParser()
|
|
|
|
|
.parseExpression(argumentElement.getAttribute(EXPRESSION_ATTRIBUTE));
|
|
|
|
|
Element argumentElement = (Element) it.next();
|
|
|
|
|
Expression name = getLocalFlowServiceLocator().getExpressionParser().parseExpression(
|
|
|
|
|
argumentElement.getAttribute(EXPRESSION_ATTRIBUTE));
|
|
|
|
|
Class type = null;
|
|
|
|
|
if (argumentElement.hasAttribute(PARAMETER_TYPE_ATTRIBUTE)) {
|
|
|
|
|
type = (Class)fromStringTo(Class.class).execute(argumentElement.getAttribute(PARAMETER_TYPE_ATTRIBUTE));
|
|
|
|
|
type = (Class) fromStringTo(Class.class)
|
|
|
|
|
.execute(argumentElement.getAttribute(PARAMETER_TYPE_ATTRIBUTE));
|
|
|
|
|
}
|
|
|
|
|
parameters.add(new Parameter(type, name));
|
|
|
|
|
}
|
|
|
|
|
@@ -793,8 +839,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
|
|
|
|
|
private Action parseEvaluateAction(Element element) {
|
|
|
|
|
String expressionString = element.getAttribute(EXPRESSION_ATTRIBUTE);
|
|
|
|
|
Expression expression = getLocalFlowServiceLocator().getExpressionParser()
|
|
|
|
|
.parseExpression(expressionString);
|
|
|
|
|
Expression expression = getLocalFlowServiceLocator().getExpressionParser().parseExpression(expressionString);
|
|
|
|
|
return new EvaluateAction(expression, parseEvaluationResultExposer(element));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -816,15 +861,15 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private Action parseSetAction(Element element) {
|
|
|
|
|
String attributeExpressionString = element.getAttribute(ATTRIBUTE_ATTRIBUTE);
|
|
|
|
|
SettableExpression attributeExpression = getLocalFlowServiceLocator().getExpressionParser()
|
|
|
|
|
.parseSettableExpression(attributeExpressionString);
|
|
|
|
|
Expression valueExpression = getLocalFlowServiceLocator().getExpressionParser()
|
|
|
|
|
.parseExpression(element.getAttribute(VALUE_ATTRIBUTE));
|
|
|
|
|
.parseSettableExpression(attributeExpressionString);
|
|
|
|
|
Expression valueExpression = getLocalFlowServiceLocator().getExpressionParser().parseExpression(
|
|
|
|
|
element.getAttribute(VALUE_ATTRIBUTE));
|
|
|
|
|
return new SetAction(attributeExpression, parseScope(element, ScopeType.REQUEST), valueExpression);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ScopeType parseScope(Element element, ScopeType defaultValue) {
|
|
|
|
|
if (element.hasAttribute(SCOPE_ATTRIBUTE) && !element.getAttribute(SCOPE_ATTRIBUTE).equals(DEFAULT_VALUE)) {
|
|
|
|
|
return (ScopeType)fromStringTo(ScopeType.class).execute(element.getAttribute(SCOPE_ATTRIBUTE));
|
|
|
|
|
return (ScopeType) fromStringTo(ScopeType.class).execute(element.getAttribute(SCOPE_ATTRIBUTE));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return defaultValue;
|
|
|
|
|
@@ -835,7 +880,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
LocalAttributeMap attributes = new LocalAttributeMap();
|
|
|
|
|
List propertyElements = DomUtils.getChildElementsByTagName(element, ATTRIBUTE_ELEMENT);
|
|
|
|
|
for (int i = 0; i < propertyElements.size(); i++) {
|
|
|
|
|
parseAndSetAttribute((Element)propertyElements.get(i), attributes);
|
|
|
|
|
parseAndSetAttribute((Element) propertyElements.get(i), attributes);
|
|
|
|
|
}
|
|
|
|
|
return attributes;
|
|
|
|
|
}
|
|
|
|
|
@@ -849,14 +894,14 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
else {
|
|
|
|
|
List valueElements = DomUtils.getChildElementsByTagName(element, VALUE_ELEMENT);
|
|
|
|
|
Assert.state(valueElements.size() == 1, "A property value should be specified for property '" + name + "'");
|
|
|
|
|
value = DomUtils.getTextValue((Element)valueElements.get(0));
|
|
|
|
|
value = DomUtils.getTextValue((Element) valueElements.get(0));
|
|
|
|
|
}
|
|
|
|
|
attributes.put(name, convertPropertyValue(element, value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Object convertPropertyValue(Element element, String stringValue) {
|
|
|
|
|
if (element.hasAttribute(TYPE_ATTRIBUTE)) {
|
|
|
|
|
Class targetClass = (Class)fromStringTo(Class.class).execute(element.getAttribute(TYPE_ATTRIBUTE));
|
|
|
|
|
Class targetClass = (Class) fromStringTo(Class.class).execute(element.getAttribute(TYPE_ATTRIBUTE));
|
|
|
|
|
// convert string value to instance of target class
|
|
|
|
|
return fromStringTo(targetClass).execute(stringValue);
|
|
|
|
|
}
|
|
|
|
|
@@ -869,9 +914,9 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
List transitions = new LinkedList();
|
|
|
|
|
List transitionElements = DomUtils.getChildElementsByTagName(element, IF_ELEMENT);
|
|
|
|
|
for (Iterator it = transitionElements.iterator(); it.hasNext();) {
|
|
|
|
|
transitions.addAll(Arrays.asList(parseIf((Element)it.next())));
|
|
|
|
|
transitions.addAll(Arrays.asList(parseIf((Element) it.next())));
|
|
|
|
|
}
|
|
|
|
|
return (Transition[])transitions.toArray(new Transition[transitions.size()]);
|
|
|
|
|
return (Transition[]) transitions.toArray(new Transition[transitions.size()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Transition[] parseIf(Element element) {
|
|
|
|
|
@@ -886,17 +931,17 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Transition parseThen(Element element) {
|
|
|
|
|
Expression expression = getLocalFlowServiceLocator().getExpressionParser()
|
|
|
|
|
.parseExpression(element.getAttribute(TEST_ATTRIBUTE));
|
|
|
|
|
Expression expression = getLocalFlowServiceLocator().getExpressionParser().parseExpression(
|
|
|
|
|
element.getAttribute(TEST_ATTRIBUTE));
|
|
|
|
|
TransitionCriteria matchingCriteria = new BooleanExpressionTransitionCriteria(expression);
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver)fromStringTo(TargetStateResolver.class).execute(
|
|
|
|
|
element.getAttribute(THEN_ATTRIBUTE));
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
|
|
|
|
|
.execute(element.getAttribute(THEN_ATTRIBUTE));
|
|
|
|
|
return getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Transition parseElse(Element element) {
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver)fromStringTo(TargetStateResolver.class).execute(
|
|
|
|
|
element.getAttribute(ELSE_ATTRIBUTE));
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
|
|
|
|
|
.execute(element.getAttribute(ELSE_ATTRIBUTE));
|
|
|
|
|
return getFlowArtifactFactory().createTransition(targetStateResolver, null, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -945,7 +990,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
ExpressionParser parser = getLocalFlowServiceLocator().getExpressionParser();
|
|
|
|
|
List mappingElements = DomUtils.getChildElementsByTagName(element, MAPPING_ELEMENT);
|
|
|
|
|
for (Iterator it = mappingElements.iterator(); it.hasNext();) {
|
|
|
|
|
Element mappingElement = (Element)it.next();
|
|
|
|
|
Element mappingElement = (Element) it.next();
|
|
|
|
|
Expression source = parser.parseExpression(mappingElement.getAttribute(SOURCE_ATTRIBUTE));
|
|
|
|
|
SettableExpression target = null;
|
|
|
|
|
if (StringUtils.hasText(mappingElement.getAttribute(TARGET_ATTRIBUTE))) {
|
|
|
|
|
@@ -967,7 +1012,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
private void parseSimpleAttributeMappings(DefaultAttributeMapper mapper, List elements) {
|
|
|
|
|
ExpressionParser parser = getLocalFlowServiceLocator().getExpressionParser();
|
|
|
|
|
for (Iterator it = elements.iterator(); it.hasNext();) {
|
|
|
|
|
Element element = (Element)it.next();
|
|
|
|
|
Element element = (Element) it.next();
|
|
|
|
|
SettableExpression attribute = parser.parseSettableExpression(element.getAttribute(NAME_ATTRIBUTE));
|
|
|
|
|
SettableExpression expression = new AttributeExpression(attribute, parseScope(element, ScopeType.FLOW));
|
|
|
|
|
if (getRequired(element, false)) {
|
|
|
|
|
@@ -981,7 +1026,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
|
|
|
|
|
private boolean getRequired(Element element, boolean defaultValue) {
|
|
|
|
|
if (StringUtils.hasText(element.getAttribute(REQUIRED_ATTRIBUTE))) {
|
|
|
|
|
return ((Boolean)fromStringTo(Boolean.class).execute(element.getAttribute(REQUIRED_ATTRIBUTE)))
|
|
|
|
|
return ((Boolean) fromStringTo(Boolean.class).execute(element.getAttribute(REQUIRED_ATTRIBUTE)))
|
|
|
|
|
.booleanValue();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
@@ -995,8 +1040,8 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
if (StringUtils.hasText(from)) {
|
|
|
|
|
if (StringUtils.hasText(to)) {
|
|
|
|
|
ConversionService service = getLocalFlowServiceLocator().getConversionService();
|
|
|
|
|
Class sourceClass = (Class)fromStringTo(Class.class).execute(from);
|
|
|
|
|
Class targetClass = (Class)fromStringTo(Class.class).execute(to);
|
|
|
|
|
Class sourceClass = (Class) fromStringTo(Class.class).execute(from);
|
|
|
|
|
Class targetClass = (Class) fromStringTo(Class.class).execute(to);
|
|
|
|
|
return service.getConversionExecutor(sourceClass, targetClass);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
@@ -1013,10 +1058,10 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
FlowExecutionExceptionHandler[] transitionExecutingHandlers = parseTransitionExecutingExceptionHandlers(element);
|
|
|
|
|
FlowExecutionExceptionHandler[] customHandlers = parseCustomExceptionHandlers(element);
|
|
|
|
|
FlowExecutionExceptionHandler[] exceptionHandlers =
|
|
|
|
|
new FlowExecutionExceptionHandler[transitionExecutingHandlers.length + customHandlers.length];
|
|
|
|
|
new FlowExecutionExceptionHandler[transitionExecutingHandlers.length + customHandlers.length];
|
|
|
|
|
System.arraycopy(transitionExecutingHandlers, 0, exceptionHandlers, 0, transitionExecutingHandlers.length);
|
|
|
|
|
System.arraycopy(customHandlers, 0, exceptionHandlers, transitionExecutingHandlers.length,
|
|
|
|
|
customHandlers.length);
|
|
|
|
|
customHandlers.length);
|
|
|
|
|
return exceptionHandlers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1033,22 +1078,22 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
}
|
|
|
|
|
List exceptionHandlers = new LinkedList();
|
|
|
|
|
for (Iterator it = transitionElements.iterator(); it.hasNext();) {
|
|
|
|
|
Element transitionElement = (Element)it.next();
|
|
|
|
|
Element transitionElement = (Element) it.next();
|
|
|
|
|
if (StringUtils.hasText(transitionElement.getAttribute(ON_EXCEPTION_ATTRIBUTE))) {
|
|
|
|
|
// the "on-exception transitions" are not really transitions but rather
|
|
|
|
|
// FlowExecutionExceptionHandlers
|
|
|
|
|
exceptionHandlers.add(parseTransitionExecutingExceptionHandler(transitionElement));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (FlowExecutionExceptionHandler[])exceptionHandlers
|
|
|
|
|
return (FlowExecutionExceptionHandler[]) exceptionHandlers
|
|
|
|
|
.toArray(new FlowExecutionExceptionHandler[exceptionHandlers.size()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private FlowExecutionExceptionHandler parseTransitionExecutingExceptionHandler(Element element) {
|
|
|
|
|
TransitionExecutingStateExceptionHandler handler = new TransitionExecutingStateExceptionHandler();
|
|
|
|
|
Class exceptionClass = (Class)fromStringTo(Class.class).execute(element.getAttribute(ON_EXCEPTION_ATTRIBUTE));
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver)fromStringTo(TargetStateResolver.class).execute(
|
|
|
|
|
element.getAttribute(TO_ATTRIBUTE));
|
|
|
|
|
Class exceptionClass = (Class) fromStringTo(Class.class).execute(element.getAttribute(ON_EXCEPTION_ATTRIBUTE));
|
|
|
|
|
TargetStateResolver targetStateResolver = (TargetStateResolver)
|
|
|
|
|
fromStringTo(TargetStateResolver.class).execute(element.getAttribute(TO_ATTRIBUTE));
|
|
|
|
|
handler.add(exceptionClass, targetStateResolver);
|
|
|
|
|
handler.getActionList().addAll(parseAnnotatedActions(element));
|
|
|
|
|
return handler;
|
|
|
|
|
@@ -1058,10 +1103,10 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder {
|
|
|
|
|
List exceptionHandlers = new LinkedList();
|
|
|
|
|
List handlerElements = DomUtils.getChildElementsByTagName(element, EXCEPTION_HANDLER_ELEMENT);
|
|
|
|
|
for (int i = 0; i < handlerElements.size(); i++) {
|
|
|
|
|
Element handlerElement = (Element)handlerElements.get(i);
|
|
|
|
|
Element handlerElement = (Element) handlerElements.get(i);
|
|
|
|
|
exceptionHandlers.add(parseCustomExceptionHandler(handlerElement));
|
|
|
|
|
}
|
|
|
|
|
return (FlowExecutionExceptionHandler[])exceptionHandlers
|
|
|
|
|
return (FlowExecutionExceptionHandler[]) exceptionHandlers
|
|
|
|
|
.toArray(new FlowExecutionExceptionHandler[exceptionHandlers.size()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|