SWF-94 Add support for Flow Inheritance
This commit is contained in:
@@ -19,10 +19,15 @@ import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImp
|
||||
import org.springframework.webflow.engine.builder.FlowAssembler;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.FlowModelFlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolder;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderContextImpl;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
|
||||
|
||||
/**
|
||||
* A factory for a flow definition registry. Is a Spring FactoryBean, for provision by the flow definition registry bean
|
||||
@@ -39,6 +44,11 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
|
||||
*/
|
||||
private FlowDefinitionRegistryImpl flowRegistry;
|
||||
|
||||
/**
|
||||
* The model registry produced by this factory bean.
|
||||
*/
|
||||
private FlowModelRegistryImpl flowModelRegistry;
|
||||
|
||||
/**
|
||||
* Flow definitions defined in external files that should be registered in the registry produced by this factory
|
||||
* bean.
|
||||
@@ -76,6 +86,7 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
flowResourceFactory = new FlowDefinitionResourceFactory(flowBuilderServices.getResourceLoader());
|
||||
flowRegistry = new FlowDefinitionRegistryImpl();
|
||||
flowModelRegistry = new FlowModelRegistryImpl();
|
||||
registerFlowLocations();
|
||||
registerFlowBuilders();
|
||||
}
|
||||
@@ -137,8 +148,18 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
|
||||
}
|
||||
|
||||
private FlowBuilder createFlowBuilder(FlowDefinitionResource resource) {
|
||||
return new FlowModelFlowBuilder(createFlowModelHolder(resource), resource.getPath());
|
||||
}
|
||||
|
||||
private FlowModelHolder createFlowModelHolder(FlowDefinitionResource resource) {
|
||||
FlowModelHolder modelHolder = new DefaultFlowModelHolder(createFlowModelBuilder(resource), resource.getId());
|
||||
flowModelRegistry.registerFlowModel(modelHolder);
|
||||
return modelHolder;
|
||||
}
|
||||
|
||||
private FlowModelBuilder createFlowModelBuilder(FlowDefinitionResource resource) {
|
||||
if (isXml(resource.getPath())) {
|
||||
return new XmlFlowBuilder(resource.getPath());
|
||||
return new XmlFlowModelBuilder(resource.getPath(), flowModelRegistry);
|
||||
} else {
|
||||
throw new IllegalArgumentException(resource
|
||||
+ " is not a supported resource type; supported types are [.xml]");
|
||||
|
||||
@@ -23,11 +23,13 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelConstructionException;
|
||||
|
||||
/**
|
||||
* A generic registry implementation for housing one or more flow definitions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry {
|
||||
|
||||
@@ -65,6 +67,8 @@ public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry {
|
||||
return parent.getFlowDefinition(id);
|
||||
}
|
||||
throw e;
|
||||
} catch (FlowModelConstructionException e) {
|
||||
throw new FlowDefinitionConstructionException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,877 @@
|
||||
package org.springframework.webflow.engine.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.support.RuntimeBindingConversionExecutor;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.ParserContext;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
import org.springframework.binding.mapping.Mapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapper;
|
||||
import org.springframework.binding.mapping.impl.DefaultMapping;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.StringUtils;
|
||||
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.ExternalRedirectAction;
|
||||
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
|
||||
import org.springframework.webflow.action.RenderAction;
|
||||
import org.springframework.webflow.action.SetAction;
|
||||
import org.springframework.webflow.action.ViewFactoryActionAdapter;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
|
||||
import org.springframework.webflow.engine.FlowVariable;
|
||||
import org.springframework.webflow.engine.SubflowAttributeMapper;
|
||||
import org.springframework.webflow.engine.TargetStateResolver;
|
||||
import org.springframework.webflow.engine.Transition;
|
||||
import org.springframework.webflow.engine.TransitionCriteria;
|
||||
import org.springframework.webflow.engine.VariableValueFactory;
|
||||
import org.springframework.webflow.engine.ViewVariable;
|
||||
import org.springframework.webflow.engine.builder.support.AbstractFlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.support.ActionExecutingViewFactory;
|
||||
import org.springframework.webflow.engine.model.AbstractActionModel;
|
||||
import org.springframework.webflow.engine.model.AbstractMappingModel;
|
||||
import org.springframework.webflow.engine.model.AbstractStateModel;
|
||||
import org.springframework.webflow.engine.model.ActionStateModel;
|
||||
import org.springframework.webflow.engine.model.AttributeModel;
|
||||
import org.springframework.webflow.engine.model.BeanImportModel;
|
||||
import org.springframework.webflow.engine.model.DecisionStateModel;
|
||||
import org.springframework.webflow.engine.model.EndStateModel;
|
||||
import org.springframework.webflow.engine.model.EvaluateModel;
|
||||
import org.springframework.webflow.engine.model.ExceptionHandlerModel;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.IfModel;
|
||||
import org.springframework.webflow.engine.model.InputModel;
|
||||
import org.springframework.webflow.engine.model.OutputModel;
|
||||
import org.springframework.webflow.engine.model.PersistenceContextModel;
|
||||
import org.springframework.webflow.engine.model.RenderModel;
|
||||
import org.springframework.webflow.engine.model.SecuredModel;
|
||||
import org.springframework.webflow.engine.model.SetModel;
|
||||
import org.springframework.webflow.engine.model.SubflowStateModel;
|
||||
import org.springframework.webflow.engine.model.TransitionModel;
|
||||
import org.springframework.webflow.engine.model.VarModel;
|
||||
import org.springframework.webflow.engine.model.ViewStateModel;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
import org.springframework.webflow.engine.support.BeanFactoryVariableValueFactory;
|
||||
import org.springframework.webflow.engine.support.DefaultTransitionCriteria;
|
||||
import org.springframework.webflow.engine.support.GenericSubflowAttributeMapper;
|
||||
import org.springframework.webflow.engine.support.TransitionCriteriaChain;
|
||||
import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.security.SecurityRule;
|
||||
import org.springframework.webflow.util.ResourceHolder;
|
||||
|
||||
public class FlowModelFlowBuilder extends AbstractFlowBuilder implements ResourceHolder {
|
||||
|
||||
private FlowModelHolder flowModelHolder;
|
||||
private FlowModel flowModel;
|
||||
private LocalFlowBuilderContext localFlowBuilderContext;
|
||||
private Resource resource;
|
||||
|
||||
public FlowModelFlowBuilder(FlowModelHolder flowModelHolder) {
|
||||
this.flowModelHolder = flowModelHolder;
|
||||
}
|
||||
|
||||
public FlowModelFlowBuilder(FlowModelHolder flowModelHolder, Resource resource) {
|
||||
this.flowModelHolder = flowModelHolder;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this builder. This could cause the builder to open a stream to an externalized resource representing
|
||||
* the flow definition, for example.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void doInit() throws FlowBuilderException {
|
||||
flowModel = flowModelHolder.getFlowModel();
|
||||
initLocalFlowContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds any variables initialized by the flow when it starts.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildVariables() throws FlowBuilderException {
|
||||
if (flowModel.getVars() != null) {
|
||||
for (Iterator varIt = flowModel.getVars().iterator(); varIt.hasNext();) {
|
||||
getFlow().addVariable(convertFlowVariable((VarModel) varIt.next()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the input mapper responsible for mapping flow input on start.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildInputMapper() throws FlowBuilderException {
|
||||
if (flowModel.getInputs() != null) {
|
||||
getFlow().setInputMapper(convertFlowInputMapper(flowModel.getInputs()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds any start actions to execute when the flow starts.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildStartActions() throws FlowBuilderException {
|
||||
if (flowModel.getOnStartActions() != null) {
|
||||
getFlow().getStartActionList().addAll(convertActions(flowModel.getOnStartActions()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the states of the flow.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildStates() throws FlowBuilderException {
|
||||
if (flowModel.getStates() == null) {
|
||||
throw new FlowBuilderException("At least one state is required to build a flow definition");
|
||||
}
|
||||
for (Iterator stateIt = flowModel.getStates().iterator(); stateIt.hasNext();) {
|
||||
AbstractStateModel state = (AbstractStateModel) stateIt.next();
|
||||
if (state instanceof ActionStateModel) {
|
||||
convertActionState((ActionStateModel) state, getFlow());
|
||||
} else if (state instanceof ViewStateModel) {
|
||||
convertViewState((ViewStateModel) state, getFlow());
|
||||
} else if (state instanceof DecisionStateModel) {
|
||||
convertDecisionState((DecisionStateModel) state, getFlow());
|
||||
} else if (state instanceof SubflowStateModel) {
|
||||
convertSubflowState((SubflowStateModel) state, getFlow());
|
||||
} else if (state instanceof EndStateModel) {
|
||||
convertEndState((EndStateModel) state, getFlow());
|
||||
}
|
||||
}
|
||||
if (flowModel.getStartStateId() != null) {
|
||||
getFlow().setStartState(flowModel.getStartStateId());
|
||||
} else {
|
||||
// default to the identifier of the first state in the flow model
|
||||
getFlow().setStartState(((AbstractStateModel) flowModel.getStates().get(0)).getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds any transitions shared by all states of the flow.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildGlobalTransitions() throws FlowBuilderException {
|
||||
if (flowModel.getGlobalTransitions() != null) {
|
||||
getFlow().getGlobalTransitionSet().addAll(convertTransitions(flowModel.getGlobalTransitions()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds any end actions to execute when the flow ends.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildEndActions() throws FlowBuilderException {
|
||||
if (flowModel.getOnEndActions() != null) {
|
||||
getFlow().getEndActionList().addAll(convertActions(flowModel.getOnEndActions()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the output mapper responsible for mapping flow output on end.
|
||||
* @throws FlowBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void buildOutputMapper() throws FlowBuilderException {
|
||||
if (flowModel.getOutputs() != null) {
|
||||
getFlow().setOutputMapper(convertFlowOutputMapper(flowModel.getOutputs()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and adds all exception handlers to the flow built by this builder.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
public void buildExceptionHandlers() throws FlowBuilderException {
|
||||
getFlow().getExceptionHandlerSet().addAll(
|
||||
convertExceptionHandlers(flowModel.getExceptionHandlers(), flowModel.getGlobalTransitions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
|
||||
* call to the {@link #init(FlowBuilderContext)} method.
|
||||
* @throws FlowBuilderException an exception occurred building this flow
|
||||
*/
|
||||
public void doDispose() throws FlowBuilderException {
|
||||
flowModel = null;
|
||||
setLocalContext(null);
|
||||
}
|
||||
|
||||
private void initLocalFlowContext() {
|
||||
List resources = new LinkedList();
|
||||
if (getFlowModel().getBeanImports() != null) {
|
||||
if (getResource() == null) {
|
||||
throw new FlowBuilderException("A resource must be defined in order to load bean-imports");
|
||||
}
|
||||
for (Iterator beanImportIt = getFlowModel().getBeanImports().iterator(); beanImportIt.hasNext();) {
|
||||
BeanImportModel beanImport = (BeanImportModel) beanImportIt.next();
|
||||
try {
|
||||
resources.add(getResource().createRelative(beanImport.getResource()));
|
||||
} catch (IOException e) {
|
||||
throw new FlowBuilderException("Could not access flow-relative artifact resource '"
|
||||
+ beanImport.getResource() + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
setLocalContext(new LocalFlowBuilderContext(getContext(), createFlowApplicationContext((Resource[]) resources
|
||||
.toArray(new Resource[resources.size()]))));
|
||||
}
|
||||
|
||||
protected Flow createFlow() {
|
||||
Flow flow = convertFlow(flowModel);
|
||||
flow.setBeanFactory(getLocalContext().getBeanFactory());
|
||||
flow.setResourceLoader(getLocalContext().getResourceLoader());
|
||||
return flow;
|
||||
}
|
||||
|
||||
private Flow convertFlow(FlowModel flow) {
|
||||
String flowId = getLocalContext().getFlowId();
|
||||
AttributeMap externallyAssignedAttributes = getLocalContext().getFlowAttributes();
|
||||
MutableAttributeMap flowAttributes = convertMetaAttributes(flow.getAttributes());
|
||||
convertPersistenceContext(flow.getPersistenceContext(), flowAttributes);
|
||||
convertSecured(flow.getSecured(), flowAttributes);
|
||||
return this.getLocalContext().getFlowArtifactFactory().createFlow(flowId,
|
||||
flowAttributes.union(externallyAssignedAttributes));
|
||||
}
|
||||
|
||||
protected GenericApplicationContext createFlowApplicationContext(Resource[] resources) {
|
||||
// see if this factory has a parent
|
||||
BeanFactory parent = getContext().getBeanFactory();
|
||||
// determine the context implementation based on the current environment
|
||||
GenericApplicationContext flowContext;
|
||||
if (parent instanceof WebApplicationContext) {
|
||||
GenericWebApplicationContext webContext = new GenericWebApplicationContext();
|
||||
webContext.setServletContext(((WebApplicationContext) parent).getServletContext());
|
||||
flowContext = webContext;
|
||||
} else {
|
||||
flowContext = new GenericApplicationContext();
|
||||
}
|
||||
// set the parent if necessary
|
||||
if (parent instanceof ApplicationContext) {
|
||||
flowContext.setParent((ApplicationContext) parent);
|
||||
} else {
|
||||
if (parent != null) {
|
||||
flowContext.getBeanFactory().setParentBeanFactory(parent);
|
||||
}
|
||||
}
|
||||
flowContext.setResourceLoader(new FlowRelativeResourceLoader(resource));
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext);
|
||||
new XmlBeanDefinitionReader(flowContext).loadBeanDefinitions(resources);
|
||||
registerFlowBeans(flowContext.getDefaultListableBeanFactory());
|
||||
flowContext.refresh();
|
||||
return flowContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register beans in the bean factory local to the flow definition being built.
|
||||
* <p>
|
||||
* Subclasses may override this method to customize the population of the bean factory local to the flow definition
|
||||
* being built; for example, to register mock implementations of services in a test environment.
|
||||
* @param beanFactory the bean factory; register local beans with it using
|
||||
* {@link ConfigurableBeanFactory#registerSingleton(String, Object)}
|
||||
*/
|
||||
protected void registerFlowBeans(ConfigurableBeanFactory beanFactory) {
|
||||
}
|
||||
|
||||
private FlowVariable convertFlowVariable(VarModel var) {
|
||||
Class clazz = (Class) fromStringTo(Class.class).execute(var.getClassName());
|
||||
VariableValueFactory valueFactory = new BeanFactoryVariableValueFactory(clazz,
|
||||
(AutowireCapableBeanFactory) getFlow().getBeanFactory());
|
||||
ScopeType scope = convertScopeType(var.getScope(), ScopeType.FLOW);
|
||||
if (!(scope == ScopeType.FLOW || scope == ScopeType.CONVERSATION)) {
|
||||
throw new IllegalArgumentException("Only " + ScopeType.FLOW + " or " + ScopeType.CONVERSATION
|
||||
+ " scope is allowed for flow variables");
|
||||
}
|
||||
return new FlowVariable(var.getName(), valueFactory, scope == ScopeType.FLOW ? true : false);
|
||||
}
|
||||
|
||||
private Mapper convertFlowInputMapper(List inputs) {
|
||||
DefaultMapper inputMapper = new DefaultMapper();
|
||||
if (inputs != null) {
|
||||
for (Iterator inputIt = inputs.iterator(); inputIt.hasNext();) {
|
||||
inputMapper.addMapping(convertFlowInputMapping((InputModel) inputIt.next()));
|
||||
}
|
||||
}
|
||||
return inputMapper;
|
||||
}
|
||||
|
||||
private DefaultMapping convertFlowInputMapping(InputModel input) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = input.getName();
|
||||
String value = null;
|
||||
if (StringUtils.hasText(input.getValue())) {
|
||||
value = input.getValue();
|
||||
} else {
|
||||
value = name;
|
||||
}
|
||||
Expression source = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
|
||||
Expression target = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
convertMappingConversionExecutor(input, mapping);
|
||||
convertMappingRequired(input, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private Mapper convertSubflowInputMapper(List inputs) {
|
||||
DefaultMapper inputMapper = new DefaultMapper();
|
||||
if (inputs != null) {
|
||||
for (Iterator inputIt = inputs.iterator(); inputIt.hasNext();) {
|
||||
inputMapper.addMapping(convertSubflowInputMapping((InputModel) inputIt.next()));
|
||||
}
|
||||
}
|
||||
return inputMapper;
|
||||
}
|
||||
|
||||
private DefaultMapping convertSubflowInputMapping(InputModel input) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = input.getName();
|
||||
String value = null;
|
||||
if (StringUtils.hasText(input.getValue())) {
|
||||
value = input.getValue();
|
||||
} else {
|
||||
value = name;
|
||||
}
|
||||
Expression source = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression target = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
convertMappingConversionExecutor(input, mapping);
|
||||
convertMappingRequired(input, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private Mapper convertFlowOutputMapper(List outputs) {
|
||||
DefaultMapper outputMapper = new DefaultMapper();
|
||||
if (outputs != null) {
|
||||
for (Iterator outputIt = outputs.iterator(); outputIt.hasNext();) {
|
||||
outputMapper.addMapping(convertFlowOutputMapping((OutputModel) outputIt.next()));
|
||||
}
|
||||
}
|
||||
return outputMapper;
|
||||
}
|
||||
|
||||
private DefaultMapping convertFlowOutputMapping(OutputModel output) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = output.getName();
|
||||
String value = null;
|
||||
if (StringUtils.hasText(output.getValue())) {
|
||||
value = output.getValue();
|
||||
} else {
|
||||
value = name;
|
||||
}
|
||||
Expression source = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression target = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
convertMappingConversionExecutor(output, mapping);
|
||||
convertMappingRequired(output, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private Mapper convertSubflowOutputMapper(List outputs) {
|
||||
DefaultMapper outputMapper = new DefaultMapper();
|
||||
if (outputs != null) {
|
||||
for (Iterator outputIt = outputs.iterator(); outputIt.hasNext();) {
|
||||
outputMapper.addMapping(convertSubflowOutputMapping((OutputModel) outputIt.next()));
|
||||
}
|
||||
}
|
||||
return outputMapper;
|
||||
}
|
||||
|
||||
private DefaultMapping convertSubflowOutputMapping(OutputModel output) {
|
||||
ExpressionParser parser = getLocalContext().getExpressionParser();
|
||||
String name = output.getName();
|
||||
String value = null;
|
||||
if (StringUtils.hasText(output.getValue())) {
|
||||
value = output.getValue();
|
||||
} else {
|
||||
value = name;
|
||||
}
|
||||
Expression source = parser.parseExpression(name, new ParserContextImpl().eval(MutableAttributeMap.class));
|
||||
Expression target = parser.parseExpression(value, new ParserContextImpl().eval(RequestContext.class));
|
||||
DefaultMapping mapping = new DefaultMapping(source, target);
|
||||
convertMappingConversionExecutor(output, mapping);
|
||||
convertMappingRequired(output, mapping);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
private void convertMappingConversionExecutor(AbstractMappingModel model, DefaultMapping mapping) {
|
||||
if (StringUtils.hasText(model.getType())) {
|
||||
Class type = (Class) fromStringTo(Class.class).execute(model.getType());
|
||||
ConversionExecutor typeConverter = new RuntimeBindingConversionExecutor(type, getLocalContext()
|
||||
.getConversionService());
|
||||
mapping.setTypeConverter(typeConverter);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertMappingRequired(AbstractMappingModel model, DefaultMapping mapping) {
|
||||
if (StringUtils.hasText(model.getRequired())) {
|
||||
boolean required = ((Boolean) fromStringTo(Boolean.class).execute(model.getRequired())).booleanValue();
|
||||
mapping.setRequired(required);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertActionState(ActionStateModel state, Flow flow) {
|
||||
MutableAttributeMap attributes = convertMetaAttributes(state.getAttributes());
|
||||
convertSecured(state.getSecured(), attributes);
|
||||
getLocalContext().getFlowArtifactFactory().createActionState(state.getId(), flow,
|
||||
convertActions(state.getOnEntryActions()), convertActions(state.getActions()),
|
||||
convertTransitions(state.getTransitions()),
|
||||
convertExceptionHandlers(state.getExceptionHandlers(), state.getTransitions()),
|
||||
convertActions(state.getOnExitActions()), attributes);
|
||||
}
|
||||
|
||||
private void convertViewState(ViewStateModel state, Flow flow) {
|
||||
ViewFactory viewFactory = convertViewFactory(state.getView(), state.getId(), false);
|
||||
Boolean redirect = null;
|
||||
if (StringUtils.hasText(state.getRedirect())) {
|
||||
redirect = (Boolean) fromStringTo(Boolean.class).execute(state.getRedirect());
|
||||
}
|
||||
boolean popup = false;
|
||||
if (StringUtils.hasText(state.getPopup())) {
|
||||
popup = ((Boolean) fromStringTo(Boolean.class).execute(state.getPopup())).booleanValue();
|
||||
}
|
||||
MutableAttributeMap attributes = convertMetaAttributes(state.getAttributes());
|
||||
convertSecured(state.getSecured(), attributes);
|
||||
getLocalContext().getFlowArtifactFactory().createViewState(state.getId(), flow,
|
||||
convertViewVariables(state.getVars()), convertActions(state.getOnEntryActions()), viewFactory,
|
||||
redirect, popup, convertActions(state.getOnRenderActions()),
|
||||
convertTransitions(state.getTransitions()),
|
||||
convertExceptionHandlers(state.getExceptionHandlers(), state.getTransitions()),
|
||||
convertActions(state.getOnExitActions()), attributes);
|
||||
}
|
||||
|
||||
private void convertDecisionState(DecisionStateModel state, Flow flow) {
|
||||
MutableAttributeMap attributes = convertMetaAttributes(state.getAttributes());
|
||||
convertSecured(state.getSecured(), attributes);
|
||||
getLocalContext().getFlowArtifactFactory().createDecisionState(state.getId(), flow,
|
||||
convertActions(state.getOnEntryActions()), convertIfs(state.getIfs()),
|
||||
convertExceptionHandlers(state.getExceptionHandlers(), null), convertActions(state.getOnExitActions()),
|
||||
attributes);
|
||||
}
|
||||
|
||||
private void convertSubflowState(SubflowStateModel state, Flow flow) {
|
||||
MutableAttributeMap attributes = convertMetaAttributes(state.getAttributes());
|
||||
convertSecured(state.getSecured(), attributes);
|
||||
getLocalContext().getFlowArtifactFactory().createSubflowState(state.getId(), flow,
|
||||
convertActions(state.getOnEntryActions()), convertSubflowExpression(state.getSubflow()),
|
||||
convertSubflowAttributeMapper(state), convertTransitions(state.getTransitions()),
|
||||
convertExceptionHandlers(state.getExceptionHandlers(), state.getTransitions()),
|
||||
convertActions(state.getOnExitActions()), attributes);
|
||||
}
|
||||
|
||||
private Expression convertSubflowExpression(String subflow) {
|
||||
Expression subflowId = getLocalContext().getExpressionParser().parseExpression(subflow,
|
||||
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
|
||||
return new SubflowExpression(subflowId, getLocalContext().getFlowDefinitionLocator());
|
||||
}
|
||||
|
||||
private SubflowAttributeMapper convertSubflowAttributeMapper(SubflowStateModel state) {
|
||||
if (StringUtils.hasText(state.getSubflowAttributeMapper())) {
|
||||
String attributeMapperBeanId = state.getSubflowAttributeMapper();
|
||||
return (SubflowAttributeMapper) getLocalContext().getBeanFactory().getBean(attributeMapperBeanId,
|
||||
SubflowAttributeMapper.class);
|
||||
} else {
|
||||
Mapper inputMapper = convertSubflowInputMapper(state.getInputs());
|
||||
Mapper outputMapper = convertSubflowOutputMapper(state.getOutputs());
|
||||
return new GenericSubflowAttributeMapper(inputMapper, outputMapper);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertEndState(EndStateModel state, Flow flow) {
|
||||
MutableAttributeMap attributes = convertMetaAttributes(state.getAttributes());
|
||||
if (StringUtils.hasText(state.getCommit())) {
|
||||
attributes.put("commit", fromStringTo(Boolean.class).execute(state.getCommit()));
|
||||
}
|
||||
convertSecured(state.getSecured(), attributes);
|
||||
getLocalContext().getFlowArtifactFactory().createEndState(state.getId(), flow,
|
||||
convertActions(state.getOnEntryActions()),
|
||||
new ViewFactoryActionAdapter(convertViewFactory(state.getView(), state.getId(), true)),
|
||||
convertFlowOutputMapper(state.getOutputs()),
|
||||
convertExceptionHandlers(state.getExceptionHandlers(), null), attributes);
|
||||
}
|
||||
|
||||
private ViewFactory convertViewFactory(String view, String stateId, boolean endState) {
|
||||
if (!StringUtils.hasText(view)) {
|
||||
if (endState) {
|
||||
return null;
|
||||
} else {
|
||||
view = getLocalContext().getViewFactoryCreator().getViewIdByConvention(stateId);
|
||||
Expression viewId = getLocalContext().getExpressionParser().parseExpression(view,
|
||||
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
|
||||
return createViewFactory(viewId);
|
||||
}
|
||||
} else if (view.startsWith("externalRedirect:")) {
|
||||
String encodedUrl = view.substring("externalRedirect:".length());
|
||||
Expression externalUrl = getLocalContext().getExpressionParser().parseExpression(encodedUrl,
|
||||
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
|
||||
return new ActionExecutingViewFactory(new ExternalRedirectAction(externalUrl));
|
||||
} else if (view.startsWith("flowRedirect:")) {
|
||||
String flowRedirect = view.substring("flowRedirect:".length());
|
||||
Expression expression = getLocalContext().getExpressionParser().parseExpression(flowRedirect,
|
||||
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
|
||||
return new ActionExecutingViewFactory(new FlowDefinitionRedirectAction(expression));
|
||||
} else {
|
||||
Expression viewId = getLocalContext().getExpressionParser().parseExpression(view,
|
||||
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
|
||||
return createViewFactory(viewId);
|
||||
}
|
||||
}
|
||||
|
||||
private ViewFactory createViewFactory(Expression viewId) {
|
||||
return getLocalContext().getViewFactoryCreator().createViewFactory(viewId,
|
||||
getLocalContext().getExpressionParser(), getLocalContext().getFormatterRegistry(),
|
||||
getLocalContext().getResourceLoader());
|
||||
}
|
||||
|
||||
private ViewVariable[] convertViewVariables(List vars) {
|
||||
List variables = new LinkedList();
|
||||
if (vars != null) {
|
||||
for (Iterator varIt = vars.iterator(); varIt.hasNext();) {
|
||||
variables.add(convertViewVariable((VarModel) varIt.next()));
|
||||
}
|
||||
}
|
||||
return (ViewVariable[]) variables.toArray(new ViewVariable[variables.size()]);
|
||||
}
|
||||
|
||||
private ViewVariable convertViewVariable(VarModel var) {
|
||||
Class clazz = (Class) fromStringTo(Class.class).execute(var.getClassName());
|
||||
VariableValueFactory valueFactory = new BeanFactoryVariableValueFactory(clazz,
|
||||
(AutowireCapableBeanFactory) getFlow().getBeanFactory());
|
||||
return new ViewVariable(var.getName(), valueFactory);
|
||||
}
|
||||
|
||||
private Transition[] convertIfs(List ifs) {
|
||||
List transitions = new LinkedList();
|
||||
if (ifs != null) {
|
||||
for (Iterator ifIt = ifs.iterator(); ifIt.hasNext();) {
|
||||
transitions.addAll(Arrays.asList(convertIf((IfModel) ifIt.next())));
|
||||
}
|
||||
}
|
||||
return (Transition[]) transitions.toArray(new Transition[transitions.size()]);
|
||||
}
|
||||
|
||||
private Transition[] convertIf(IfModel conditional) {
|
||||
Transition thenTransition = convertThen(conditional);
|
||||
if (StringUtils.hasText(conditional.getElse())) {
|
||||
Transition elseTransition = convertElse(conditional);
|
||||
return new Transition[] { thenTransition, elseTransition };
|
||||
} else {
|
||||
return new Transition[] { thenTransition };
|
||||
}
|
||||
}
|
||||
|
||||
private Transition convertThen(IfModel conditional) {
|
||||
Expression expression = getLocalContext().getExpressionParser().parseExpression(conditional.getTest(),
|
||||
new ParserContextImpl().eval(RequestContext.class).expect(Boolean.class));
|
||||
TransitionCriteria matchingCriteria = new DefaultTransitionCriteria(expression);
|
||||
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
|
||||
.execute(conditional.getThen());
|
||||
return getLocalContext().getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria, null,
|
||||
null);
|
||||
}
|
||||
|
||||
private Transition convertElse(IfModel conditional) {
|
||||
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
|
||||
.execute(conditional.getElse());
|
||||
return getLocalContext().getFlowArtifactFactory().createTransition(targetStateResolver, null, null, null);
|
||||
}
|
||||
|
||||
private FlowExecutionExceptionHandler[] convertExceptionHandlers(List modelExceptionHandlers, List modelTransitions) {
|
||||
FlowExecutionExceptionHandler[] transitionExecutingHandlers = convertTransitionExecutingExceptionHandlers(modelTransitions);
|
||||
FlowExecutionExceptionHandler[] customHandlers = convertCustomExceptionHandlers(modelExceptionHandlers);
|
||||
FlowExecutionExceptionHandler[] exceptionHandlers = new FlowExecutionExceptionHandler[transitionExecutingHandlers.length
|
||||
+ customHandlers.length];
|
||||
System.arraycopy(transitionExecutingHandlers, 0, exceptionHandlers, 0, transitionExecutingHandlers.length);
|
||||
System.arraycopy(customHandlers, 0, exceptionHandlers, transitionExecutingHandlers.length,
|
||||
customHandlers.length);
|
||||
return exceptionHandlers;
|
||||
}
|
||||
|
||||
private FlowExecutionExceptionHandler[] convertTransitionExecutingExceptionHandlers(List transitions) {
|
||||
List exceptionHandlers = new LinkedList();
|
||||
if (transitions != null) {
|
||||
for (Iterator transitionIt = transitions.iterator(); transitionIt.hasNext();) {
|
||||
TransitionModel transition = (TransitionModel) transitionIt.next();
|
||||
if (StringUtils.hasText(transition.getOnException())) {
|
||||
if (transition.getSecured() != null) {
|
||||
throw new FlowBuilderException("Exception based transitions cannot be secured");
|
||||
}
|
||||
exceptionHandlers.add(convertTransitionExecutingExceptionHandler(transition));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (FlowExecutionExceptionHandler[]) exceptionHandlers
|
||||
.toArray(new FlowExecutionExceptionHandler[exceptionHandlers.size()]);
|
||||
}
|
||||
|
||||
private FlowExecutionExceptionHandler convertTransitionExecutingExceptionHandler(TransitionModel transition) {
|
||||
TransitionExecutingFlowExecutionExceptionHandler handler = new TransitionExecutingFlowExecutionExceptionHandler();
|
||||
Class exceptionClass = (Class) fromStringTo(Class.class).execute(transition.getOnException());
|
||||
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
|
||||
.execute(transition.getTo());
|
||||
handler.add(exceptionClass, targetStateResolver);
|
||||
handler.getActionList().addAll(convertActions(transition.getActions()));
|
||||
return handler;
|
||||
}
|
||||
|
||||
private FlowExecutionExceptionHandler[] convertCustomExceptionHandlers(List modelExceptionHandlers) {
|
||||
List exceptionHandlers = new LinkedList();
|
||||
if (modelExceptionHandlers != null) {
|
||||
for (Iterator exceptionHandlerIt = modelExceptionHandlers.iterator(); exceptionHandlerIt.hasNext();) {
|
||||
exceptionHandlers.add(convertCustomExceptionHandler((ExceptionHandlerModel) exceptionHandlerIt.next()));
|
||||
}
|
||||
}
|
||||
return (FlowExecutionExceptionHandler[]) exceptionHandlers
|
||||
.toArray(new FlowExecutionExceptionHandler[exceptionHandlers.size()]);
|
||||
}
|
||||
|
||||
private FlowExecutionExceptionHandler convertCustomExceptionHandler(ExceptionHandlerModel exceptionHandler) {
|
||||
return (FlowExecutionExceptionHandler) getLocalContext().getBeanFactory().getBean(
|
||||
exceptionHandler.getBeanName(), FlowExecutionExceptionHandler.class);
|
||||
}
|
||||
|
||||
private Transition[] convertTransitions(List modelTransactions) {
|
||||
List transitions = new LinkedList();
|
||||
if (modelTransactions != null) {
|
||||
for (Iterator modelTransactionIt = modelTransactions.iterator(); modelTransactionIt.hasNext();) {
|
||||
TransitionModel transition = (TransitionModel) modelTransactionIt.next();
|
||||
if (!StringUtils.hasText(transition.getOnException())) {
|
||||
transitions.add(convertTransition(transition));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (Transition[]) transitions.toArray(new Transition[transitions.size()]);
|
||||
}
|
||||
|
||||
private Transition convertTransition(TransitionModel transition) {
|
||||
TransitionCriteria matchingCriteria = (TransitionCriteria) fromStringTo(TransitionCriteria.class).execute(
|
||||
transition.getOn());
|
||||
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
|
||||
.execute(transition.getTo());
|
||||
TransitionCriteria executionCriteria = TransitionCriteriaChain.criteriaChainFor(convertActions(transition
|
||||
.getActions()));
|
||||
MutableAttributeMap attributes = convertMetaAttributes(transition.getAttributes());
|
||||
convertSecured(transition.getSecured(), attributes);
|
||||
return getLocalContext().getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria,
|
||||
executionCriteria, attributes);
|
||||
}
|
||||
|
||||
private Action[] convertActions(List modelActions) {
|
||||
List actions = new LinkedList();
|
||||
if (modelActions != null) {
|
||||
for (Iterator modelActionIt = modelActions.iterator(); modelActionIt.hasNext();) {
|
||||
AbstractActionModel action = (AbstractActionModel) modelActionIt.next();
|
||||
if (action instanceof EvaluateModel) {
|
||||
actions.add(convertEvaluateAction((EvaluateModel) action));
|
||||
} else if (action instanceof RenderModel) {
|
||||
actions.add(convertRenderAction((RenderModel) action));
|
||||
} else if (action instanceof SetModel) {
|
||||
actions.add(convertSetAction((SetModel) action));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (Action[]) actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
private Action convertEvaluateAction(EvaluateModel evaluate) {
|
||||
String expressionString = evaluate.getExpression();
|
||||
Expression expression = getLocalContext().getExpressionParser().parseExpression(expressionString,
|
||||
new ParserContextImpl().eval(RequestContext.class));
|
||||
return new EvaluateAction(expression, convertEvaluationActionResultExposer(evaluate));
|
||||
}
|
||||
|
||||
private ActionResultExposer convertEvaluationActionResultExposer(EvaluateModel evaluate) {
|
||||
if (StringUtils.hasText(evaluate.getResult())) {
|
||||
Expression resultExpression = getLocalContext().getExpressionParser().parseExpression(evaluate.getResult(),
|
||||
new ParserContextImpl().eval(RequestContext.class));
|
||||
Class expectedResultType = null;
|
||||
if (StringUtils.hasText(evaluate.getResultType())) {
|
||||
expectedResultType = (Class) fromStringTo(Class.class).execute(evaluate.getResultType());
|
||||
}
|
||||
return new ActionResultExposer(resultExpression, expectedResultType, getLocalContext()
|
||||
.getConversionService());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Action convertRenderAction(RenderModel render) {
|
||||
String[] fragmentExpressionStrings = StringUtils.commaDelimitedListToStringArray(render.getFragments());
|
||||
fragmentExpressionStrings = StringUtils.trimArrayElements(fragmentExpressionStrings);
|
||||
ParserContext context = new ParserContextImpl().template().eval(RequestContext.class).expect(String.class);
|
||||
Expression[] fragments = new Expression[fragmentExpressionStrings.length];
|
||||
for (int i = 0; i < fragmentExpressionStrings.length; i++) {
|
||||
String fragment = fragmentExpressionStrings[i];
|
||||
fragments[i] = getLocalContext().getExpressionParser().parseExpression(fragment, context);
|
||||
}
|
||||
return new RenderAction(fragments);
|
||||
}
|
||||
|
||||
private Action convertSetAction(SetModel set) {
|
||||
Expression nameExpression = getLocalContext().getExpressionParser().parseExpression(set.getName(),
|
||||
new ParserContextImpl().eval(RequestContext.class));
|
||||
Expression valueExpression = getLocalContext().getExpressionParser().parseExpression(set.getValue(),
|
||||
new ParserContextImpl().eval(RequestContext.class));
|
||||
Class expectedType = null;
|
||||
if (StringUtils.hasText(set.getType())) {
|
||||
expectedType = (Class) fromStringTo(Class.class).execute(set.getType());
|
||||
}
|
||||
return new SetAction(nameExpression, valueExpression, expectedType, getLocalContext().getConversionService());
|
||||
}
|
||||
|
||||
private MutableAttributeMap convertMetaAttributes(List modelAttributes) {
|
||||
LocalAttributeMap attributes = new LocalAttributeMap();
|
||||
if (modelAttributes != null) {
|
||||
for (Iterator modelAttributeIt = modelAttributes.iterator(); modelAttributeIt.hasNext();) {
|
||||
convertMetaAttribute((AttributeModel) modelAttributeIt.next(), attributes);
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private void convertMetaAttribute(AttributeModel attribute, MutableAttributeMap attributes) {
|
||||
String name = attribute.getName();
|
||||
String value = attribute.getValue();
|
||||
attributes.put(name, convertAttributeValueIfNecessary(attribute, value));
|
||||
}
|
||||
|
||||
private Object convertAttributeValueIfNecessary(AttributeModel attribute, String stringValue) {
|
||||
if (StringUtils.hasText(attribute.getType())) {
|
||||
Class targetClass = (Class) fromStringTo(Class.class).execute(attribute.getType());
|
||||
return fromStringTo(targetClass).execute(stringValue);
|
||||
} else {
|
||||
return stringValue;
|
||||
}
|
||||
}
|
||||
|
||||
private void convertPersistenceContext(PersistenceContextModel persistenceContext, MutableAttributeMap attributes) {
|
||||
if (persistenceContext != null) {
|
||||
attributes.put("persistenceContext", Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertSecured(SecuredModel secured, MutableAttributeMap attributes) {
|
||||
if (secured != null) {
|
||||
SecurityRule rule = new SecurityRule();
|
||||
rule.setAttributes(SecurityRule.convertAttributesFromCommaSeparatedString(secured.getAttributes()));
|
||||
String comparisonType = secured.getMatch();
|
||||
if ("any".equals(comparisonType)) {
|
||||
rule.setComparisonType(SecurityRule.COMPARISON_ANY);
|
||||
} else if ("all".equals(comparisonType)) {
|
||||
rule.setComparisonType(SecurityRule.COMPARISON_ALL);
|
||||
} else {
|
||||
// default to any
|
||||
rule.setComparisonType(SecurityRule.COMPARISON_ANY);
|
||||
}
|
||||
attributes.put(SecurityRule.SECURITY_ATTRIBUTE_NAME, rule);
|
||||
}
|
||||
}
|
||||
|
||||
private ScopeType convertScopeType(String scope, ScopeType defaultScope) {
|
||||
if (StringUtils.hasText(scope)) {
|
||||
return (ScopeType) fromStringTo(ScopeType.class).execute(scope);
|
||||
} else {
|
||||
return defaultScope;
|
||||
}
|
||||
}
|
||||
|
||||
private ConversionExecutor fromStringTo(Class targetType) throws ConversionException {
|
||||
return getLocalContext().getConversionService().getConversionExecutor(String.class, targetType);
|
||||
}
|
||||
|
||||
protected FlowModel getFlowModel() {
|
||||
return flowModel;
|
||||
}
|
||||
|
||||
protected LocalFlowBuilderContext getLocalContext() {
|
||||
return localFlowBuilderContext;
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
protected void setLocalContext(LocalFlowBuilderContext localFlowBuilderContext) {
|
||||
this.localFlowBuilderContext = localFlowBuilderContext;
|
||||
}
|
||||
|
||||
private static class FlowRelativeResourceLoader implements ResourceLoader {
|
||||
private Resource resource;
|
||||
|
||||
public FlowRelativeResourceLoader(Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return resource.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
public Resource getResource(String location) {
|
||||
try {
|
||||
return resource.createRelative(location);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class SubflowExpression implements Expression {
|
||||
|
||||
private Expression subflowId;
|
||||
|
||||
private FlowDefinitionLocator flowDefinitionLocator;
|
||||
|
||||
public SubflowExpression(Expression subflowId, FlowDefinitionLocator flowDefinitionLocator) {
|
||||
this.subflowId = subflowId;
|
||||
this.flowDefinitionLocator = flowDefinitionLocator;
|
||||
}
|
||||
|
||||
public Object getValue(Object context) throws EvaluationException {
|
||||
String subflowId = (String) this.subflowId.getValue(context);
|
||||
return flowDefinitionLocator.getFlowDefinition(subflowId);
|
||||
}
|
||||
|
||||
public void setValue(Object context, Object value) throws EvaluationException {
|
||||
throw new UnsupportedOperationException("Cannot set a subflow expression");
|
||||
}
|
||||
|
||||
public Class getValueType(Object context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.builder.xml;
|
||||
package org.springframework.webflow.engine.builder;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
@@ -23,9 +23,6 @@ import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
|
||||
/**
|
||||
* A builder context that delegates to a flow-local bean factory for builder services. Such builder services override
|
||||
@@ -138,6 +138,9 @@ public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder {
|
||||
private void refreshIfChanged() {
|
||||
long calculatedLastModified = calculateLastModified();
|
||||
if (calculatedLastModified > lastModified) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing flow definition [" + flowDefinition.getId() + "]");
|
||||
}
|
||||
assembleFlow();
|
||||
lastModified = calculatedLastModified;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
The XML-based flow builder implementation.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
|
||||
/**
|
||||
* Model support for actions.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractActionModel extends AbstractModel {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for mappings.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractMappingModel extends AbstractModel {
|
||||
|
||||
private String name;
|
||||
private String value;
|
||||
private String type;
|
||||
private String required;
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
if (StringUtils.hasText(name)) {
|
||||
this.name = name;
|
||||
} else {
|
||||
this.name = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
this.value = value;
|
||||
} else {
|
||||
this.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type the type to set
|
||||
*/
|
||||
public void setType(String type) {
|
||||
if (StringUtils.hasText(type)) {
|
||||
this.type = type;
|
||||
} else {
|
||||
this.type = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the required
|
||||
*/
|
||||
public String getRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param required the required to set
|
||||
*/
|
||||
public void setRequired(String required) {
|
||||
if (StringUtils.hasText(required)) {
|
||||
this.required = required;
|
||||
} else {
|
||||
this.required = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Contains basic merge functions that can be utilized by other models.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractModel implements Model {
|
||||
|
||||
/**
|
||||
* Merge two objects. If the child is null, the parent will be returned. Else the child will be returned.
|
||||
* @param child the child object to merge
|
||||
* @param parent the parent object to merge
|
||||
* @return the merged string
|
||||
*/
|
||||
protected Object merge(Object child, Object parent) {
|
||||
if (child == null) {
|
||||
return parent;
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two strings. If the child is null, the parent will be returned. Else the child will be returned.
|
||||
* @param child the child string to merge
|
||||
* @param parent the parent string to merge
|
||||
* @return the merged string
|
||||
*/
|
||||
protected String merge(String child, String parent) {
|
||||
return (String) merge((Object) child, (Object) parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two model elements. If the child is null, the parent will be returned. Else the parent element will be
|
||||
* merged into the child element with the result returned
|
||||
* @param child the child model element to merge
|
||||
* @param parent the parent model element to merge
|
||||
* @return the merged element model
|
||||
*/
|
||||
protected Model merge(Model child, Model parent) {
|
||||
if (child == null) {
|
||||
return parent;
|
||||
} else if (parent == null) {
|
||||
return child;
|
||||
} else {
|
||||
child.merge(parent);
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two lists. All child element will be in the merged list. All parent elements not in the child list will be
|
||||
* added. Mergeable elements in both lists will be merged according to that element merge rules. New items are added
|
||||
* to the end of the list
|
||||
* @param child the child list to merge
|
||||
* @param parent the parent list to merge
|
||||
* @return the merged list
|
||||
*/
|
||||
protected LinkedList merge(LinkedList child, LinkedList parent) {
|
||||
return merge(child, parent, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two lists. All child element will be in the merged list. All parent elements not in the child list will be
|
||||
* added. Mergeable elements in both lists will be merged according to that element merge rules.
|
||||
* @param child the child list to merge
|
||||
* @param parent the parent list to merge
|
||||
* @param addAtEnd if true new items will be added at the end of the list, otherwise the beginning
|
||||
* @return the merged list
|
||||
*/
|
||||
protected LinkedList merge(LinkedList child, LinkedList parent, boolean addAtEnd) {
|
||||
if (parent == null) {
|
||||
return child;
|
||||
} else if (child == null) {
|
||||
return parent;
|
||||
} else {
|
||||
for (Iterator parentIt = parent.iterator(); parentIt.hasNext();) {
|
||||
Model parentElement = (Model) parentIt.next();
|
||||
if (!child.contains(parentElement)) {
|
||||
boolean matchFound = false;
|
||||
for (Iterator childIt = child.iterator(); !matchFound && childIt.hasNext();) {
|
||||
Model childElement = (Model) childIt.next();
|
||||
if (childElement.isMergeableWith(parentElement)) {
|
||||
matchFound = true;
|
||||
childElement.merge(parentElement);
|
||||
}
|
||||
}
|
||||
if (!matchFound) {
|
||||
if (addAtEnd) {
|
||||
child.addLast(parentElement);
|
||||
} else {
|
||||
child.addFirst(parentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for states.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractStateModel extends AbstractModel {
|
||||
private String id;
|
||||
private LinkedList attributes;
|
||||
private SecuredModel secured;
|
||||
private LinkedList onEntryActions;
|
||||
private LinkedList exceptionHandlers;
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(String id) {
|
||||
if (StringUtils.hasText(id)) {
|
||||
this.id = id;
|
||||
} else {
|
||||
this.id = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the attributes
|
||||
*/
|
||||
public LinkedList getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set
|
||||
*/
|
||||
public void setAttributes(LinkedList attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attribute the attribute to add
|
||||
*/
|
||||
public void addAttribute(AttributeModel attribute) {
|
||||
if (attribute == null) {
|
||||
return;
|
||||
}
|
||||
if (attributes == null) {
|
||||
attributes = new LinkedList();
|
||||
}
|
||||
attributes.add(attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to add
|
||||
*/
|
||||
public void addAttributes(LinkedList attributes) {
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.attributes == null) {
|
||||
this.attributes = new LinkedList();
|
||||
}
|
||||
this.attributes.addAll(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the secured
|
||||
*/
|
||||
public SecuredModel getSecured() {
|
||||
return secured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param secured the secured to set
|
||||
*/
|
||||
public void setSecured(SecuredModel secured) {
|
||||
this.secured = secured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on entry actions
|
||||
*/
|
||||
public LinkedList getOnEntryActions() {
|
||||
return onEntryActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onEntryActions the on entry actions to set
|
||||
*/
|
||||
public void setOnEntryActions(LinkedList onEntryActions) {
|
||||
this.onEntryActions = onEntryActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onEntryAction the on entry action to add
|
||||
*/
|
||||
public void addOnEntryAction(AbstractActionModel onEntryAction) {
|
||||
if (onEntryAction == null) {
|
||||
return;
|
||||
}
|
||||
if (onEntryActions == null) {
|
||||
onEntryActions = new LinkedList();
|
||||
}
|
||||
onEntryActions.add(onEntryAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onEntryActions the on entry actions to add
|
||||
*/
|
||||
public void addOnEntryActions(LinkedList onEntryActions) {
|
||||
if (onEntryActions == null || onEntryActions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.onEntryActions == null) {
|
||||
this.onEntryActions = new LinkedList();
|
||||
}
|
||||
this.onEntryActions.addAll(onEntryActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the exception handlers
|
||||
*/
|
||||
public LinkedList getExceptionHandlers() {
|
||||
return exceptionHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionHandlers the exception handlers to set
|
||||
*/
|
||||
public void setExceptionHandlers(LinkedList exceptionHandlers) {
|
||||
this.exceptionHandlers = exceptionHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionHandler the exception handler to add
|
||||
*/
|
||||
public void addExceptionHandler(ExceptionHandlerModel exceptionHandler) {
|
||||
if (exceptionHandler == null) {
|
||||
return;
|
||||
}
|
||||
if (exceptionHandlers == null) {
|
||||
exceptionHandlers = new LinkedList();
|
||||
}
|
||||
exceptionHandlers.add(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionHandlers the exception handlers to add
|
||||
*/
|
||||
public void addExceptionHandlers(LinkedList exceptionHandlers) {
|
||||
if (exceptionHandlers == null || exceptionHandlers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.exceptionHandlers == null) {
|
||||
this.exceptionHandlers = new LinkedList();
|
||||
}
|
||||
this.exceptionHandlers.addAll(exceptionHandlers);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Model support for transitionable states.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractTransitionableStateModel extends AbstractStateModel {
|
||||
private LinkedList transitions;
|
||||
private LinkedList onExitActions;
|
||||
|
||||
/**
|
||||
* @return the transitions
|
||||
*/
|
||||
public LinkedList getTransitions() {
|
||||
return transitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transitions the transitions to set
|
||||
*/
|
||||
public void setTransitions(LinkedList transitions) {
|
||||
this.transitions = transitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transition the transition to add
|
||||
*/
|
||||
public void addTransition(TransitionModel transition) {
|
||||
if (transition == null) {
|
||||
return;
|
||||
}
|
||||
if (transitions == null) {
|
||||
transitions = new LinkedList();
|
||||
}
|
||||
transitions.add(transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transitions the transitions to add
|
||||
*/
|
||||
public void addTransitions(LinkedList transitions) {
|
||||
if (transitions == null || transitions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.transitions == null) {
|
||||
this.transitions = new LinkedList();
|
||||
}
|
||||
this.transitions.addAll(transitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on exit actions
|
||||
*/
|
||||
public LinkedList getOnExitActions() {
|
||||
return onExitActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onExitActions the on exit actions to set
|
||||
*/
|
||||
public void setOnExitActions(LinkedList onExitActions) {
|
||||
this.onExitActions = onExitActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onExitAction the on exit action to add
|
||||
*/
|
||||
public void addOnExitAction(AbstractActionModel onExitAction) {
|
||||
if (onExitAction == null) {
|
||||
return;
|
||||
}
|
||||
if (this.onExitActions == null) {
|
||||
this.onExitActions = new LinkedList();
|
||||
}
|
||||
this.onExitActions.add(onExitAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onExitActions the on exit actions to add
|
||||
*/
|
||||
public void addOnExitsActions(LinkedList onExitActions) {
|
||||
if (onExitActions == null || onExitActions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.onExitActions == null) {
|
||||
this.onExitActions = new LinkedList();
|
||||
}
|
||||
this.onExitActions.addAll(onExitActions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Model support for action states.
|
||||
* <p>
|
||||
* A state where one or more actions are executed. This state type is typically used to invoke application code. An
|
||||
* action state is a transitionable state. A transition out of this state is driven by the result of action execution.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class ActionStateModel extends AbstractTransitionableStateModel {
|
||||
private LinkedList actions;
|
||||
|
||||
/**
|
||||
* Create an action state model
|
||||
* @param id the state identifier
|
||||
*/
|
||||
public ActionStateModel(String id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an action state model
|
||||
* @param id the state identifier
|
||||
* @param attributes meta attributes for the state
|
||||
* @param secured security settings for the state
|
||||
* @param onEntryActions actions to execute upon entry
|
||||
* @param transitions transitions for the state
|
||||
* @param onExitActions actions to execute before leaving the state
|
||||
* @param actions actions to execute during the state
|
||||
* @param exceptionHandlers exception handlers for the state
|
||||
*/
|
||||
public ActionStateModel(String id, LinkedList attributes, SecuredModel secured, LinkedList onEntryActions,
|
||||
LinkedList transitions, LinkedList onExitActions, LinkedList actions, LinkedList exceptionHandlers) {
|
||||
setId(id);
|
||||
setAttributes(attributes);
|
||||
setSecured(secured);
|
||||
setOnEntryActions(onEntryActions);
|
||||
setTransitions(transitions);
|
||||
setOnExitActions(onExitActions);
|
||||
setActions(actions);
|
||||
setExceptionHandlers(exceptionHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the action state to merge into this state
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
ActionStateModel state = (ActionStateModel) model;
|
||||
setAttributes(merge(getAttributes(), state.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), state.getSecured()));
|
||||
setOnEntryActions(merge(getOnEntryActions(), state.getOnEntryActions(), false));
|
||||
setExceptionHandlers(merge(getExceptionHandlers(), state.getExceptionHandlers()));
|
||||
setTransitions(merge(getTransitions(), state.getTransitions()));
|
||||
setOnExitActions(merge(getOnExitActions(), state.getOnExitActions(), false));
|
||||
setActions(merge(getActions(), state.getActions(), false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this action state
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof ActionStateModel)) {
|
||||
return false;
|
||||
}
|
||||
ActionStateModel state = (ActionStateModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getId(), state.getId());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof ActionStateModel)) {
|
||||
return false;
|
||||
}
|
||||
ActionStateModel state = (ActionStateModel) obj;
|
||||
if (state == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getId(), state.getId())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), state.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), state.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnEntryActions(), state.getOnEntryActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExceptionHandlers(), state.getExceptionHandlers())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getTransitions(), state.getTransitions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnExitActions(), state.getOnExitActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getActions(), state.getActions())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getId()) * 27 + ObjectUtils.nullSafeHashCode(getAttributes()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getSecured()) * 27 + ObjectUtils.nullSafeHashCode(getOnEntryActions())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getExceptionHandlers()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getTransitions()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOnExitActions()) * 27 + ObjectUtils.nullSafeHashCode(getActions())
|
||||
* 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actions
|
||||
*/
|
||||
public LinkedList getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actions the actions to set
|
||||
*/
|
||||
public void setActions(LinkedList actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param action the action to add
|
||||
*/
|
||||
public void addAction(AbstractActionModel action) {
|
||||
if (action == null) {
|
||||
return;
|
||||
}
|
||||
if (actions == null) {
|
||||
actions = new LinkedList();
|
||||
}
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actions the actions to add
|
||||
*/
|
||||
public void addAction(LinkedList actions) {
|
||||
if (actions == null || actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.actions == null) {
|
||||
this.actions = new LinkedList();
|
||||
}
|
||||
this.actions.addAll(actions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for attributes.
|
||||
* <p>
|
||||
* A meta attribute describing or otherwise annotating it's holder.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class AttributeModel extends AbstractModel {
|
||||
private String name;
|
||||
private String type;
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Create an attribute model
|
||||
* @param name the name of the attribute
|
||||
* @param value the value of the attribute
|
||||
*/
|
||||
public AttributeModel(String name, String value) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an attribute model
|
||||
* @param name the name of the attribute
|
||||
* @param value the value of the attribute
|
||||
* @param type the type of the value
|
||||
*/
|
||||
public AttributeModel(String name, String value, String type) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
setType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the attribute to merge into this attribute
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
AttributeModel attribute = (AttributeModel) model;
|
||||
setType(merge(getType(), attribute.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this attribute
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof AttributeModel)) {
|
||||
return false;
|
||||
}
|
||||
AttributeModel attribute = (AttributeModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getName(), attribute.getName())
|
||||
&& ObjectUtils.nullSafeEquals(getValue(), attribute.getValue());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof AttributeModel)) {
|
||||
return false;
|
||||
}
|
||||
AttributeModel attribute = (AttributeModel) obj;
|
||||
if (attribute == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getName(), attribute.getName())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getType(), attribute.getType())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getValue(), attribute.getValue())) {
|
||||
return false;
|
||||
} else {
|
||||
return super.equals(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getName()) * 27 + ObjectUtils.nullSafeHashCode(getType()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getValue()) * 27 + super.hashCode() * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
if (StringUtils.hasText(name)) {
|
||||
this.name = name;
|
||||
} else {
|
||||
this.name = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type the type to set
|
||||
*/
|
||||
public void setType(String type) {
|
||||
if (StringUtils.hasText(type)) {
|
||||
this.type = type;
|
||||
} else {
|
||||
this.type = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
this.value = value;
|
||||
} else {
|
||||
this.value = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for bean imports.
|
||||
* <p>
|
||||
* Imports user-defined beans defined at a resource location. These beans become part of the flow's bean factory and are
|
||||
* resolvable using flow expressions.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class BeanImportModel extends AbstractModel {
|
||||
private String resource;
|
||||
|
||||
/**
|
||||
* Create a bean import model
|
||||
* @param resource the resource containing beans to import
|
||||
*/
|
||||
public BeanImportModel(String resource) {
|
||||
setResource(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean imports are not mergeable
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
// not mergeable
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean imports are not mergeable
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof BeanImportModel)) {
|
||||
return false;
|
||||
}
|
||||
BeanImportModel beanImport = (BeanImportModel) obj;
|
||||
if (beanImport == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getResource(), beanImport.getResource())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getResource()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resource
|
||||
*/
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resource the resource to set
|
||||
*/
|
||||
public void setResource(String resource) {
|
||||
if (StringUtils.hasText(resource)) {
|
||||
this.resource = resource;
|
||||
} else {
|
||||
this.resource = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Model support for decision states.
|
||||
* <p>
|
||||
* Evaluates one or more expressions to decide what state to transition to next. Intended to be used as an idempotent
|
||||
* 'navigation' or 'routing' state.
|
||||
* <p>
|
||||
* A decision state is a transitionable state. A decision state transition can be triggered by evaluating a boolean
|
||||
* expression against the flow execution request context. To define transition expressions, use the 'if' element.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DecisionStateModel extends AbstractStateModel {
|
||||
private LinkedList ifs;
|
||||
private LinkedList onExitActions;
|
||||
|
||||
/**
|
||||
* Create a decision state model
|
||||
* @param id the state identifier
|
||||
*/
|
||||
public DecisionStateModel(String id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a decision state model
|
||||
* @param id the state identifier
|
||||
* @param ifs decision tests
|
||||
* @param onExitActions actions to execute before exiting this state
|
||||
* @param attributes meta attributes for this state
|
||||
* @param secured security settings for this state
|
||||
* @param onEntryActions actions to execute upon entering this state
|
||||
* @param exceptionHandlers exception handlers for this state
|
||||
*/
|
||||
public DecisionStateModel(String id, LinkedList ifs, LinkedList onExitActions, LinkedList attributes,
|
||||
SecuredModel secured, LinkedList onEntryActions, LinkedList exceptionHandlers) {
|
||||
setId(id);
|
||||
setIfs(ifs);
|
||||
setOnExitActions(onExitActions);
|
||||
setAttributes(attributes);
|
||||
setSecured(secured);
|
||||
setOnEntryActions(onEntryActions);
|
||||
setExceptionHandlers(exceptionHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the decision state to merge into this state
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
DecisionStateModel state = (DecisionStateModel) model;
|
||||
setAttributes(merge(getAttributes(), state.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), state.getSecured()));
|
||||
setOnEntryActions(merge(getOnEntryActions(), state.getOnEntryActions(), false));
|
||||
setExceptionHandlers(merge(getExceptionHandlers(), state.getExceptionHandlers()));
|
||||
setIfs(merge(getIfs(), state.getIfs()));
|
||||
setOnExitActions(merge(getOnExitActions(), state.getOnExitActions(), false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this decision state
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof DecisionStateModel)) {
|
||||
return false;
|
||||
}
|
||||
DecisionStateModel state = (DecisionStateModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getId(), state.getId());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof DecisionStateModel)) {
|
||||
return false;
|
||||
}
|
||||
DecisionStateModel state = (DecisionStateModel) obj;
|
||||
if (state == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getId(), state.getId())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), state.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), state.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnEntryActions(), state.getOnEntryActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExceptionHandlers(), state.getExceptionHandlers())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getIfs(), state.getIfs())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnExitActions(), state.getOnExitActions())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getId()) * 27 + ObjectUtils.nullSafeHashCode(getAttributes()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getSecured()) * 27 + ObjectUtils.nullSafeHashCode(getOnEntryActions())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getExceptionHandlers()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getIfs()) * 27 + ObjectUtils.nullSafeHashCode(getOnExitActions()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ifs
|
||||
*/
|
||||
public LinkedList getIfs() {
|
||||
return ifs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ifs the ifs to set
|
||||
*/
|
||||
public void setIfs(LinkedList ifs) {
|
||||
this.ifs = ifs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param conditional the if to add
|
||||
*/
|
||||
public void addIf(IfModel conditional) {
|
||||
if (conditional == null) {
|
||||
return;
|
||||
}
|
||||
if (ifs == null) {
|
||||
ifs = new LinkedList();
|
||||
}
|
||||
ifs.add(conditional);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ifs the ifs to add
|
||||
*/
|
||||
public void addIf(LinkedList ifs) {
|
||||
if (ifs == null || ifs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.ifs == null) {
|
||||
this.ifs = new LinkedList();
|
||||
}
|
||||
this.ifs.addAll(ifs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on exit actions
|
||||
*/
|
||||
public LinkedList getOnExitActions() {
|
||||
return onExitActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onExitActions the on exit actions to set
|
||||
*/
|
||||
public void setOnExitActions(LinkedList onExitActions) {
|
||||
this.onExitActions = onExitActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onExitAction the on exit action to add
|
||||
*/
|
||||
public void addOnExitAction(AbstractActionModel onExitAction) {
|
||||
if (onExitAction == null) {
|
||||
return;
|
||||
}
|
||||
if (onExitActions == null) {
|
||||
onExitActions = new LinkedList();
|
||||
}
|
||||
onExitActions.add(onExitAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onExitActions the on exit actions to add
|
||||
*/
|
||||
public void addOnExitActions(LinkedList onExitActions) {
|
||||
if (onExitActions == null || onExitActions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.onExitActions == null) {
|
||||
this.onExitActions = new LinkedList();
|
||||
}
|
||||
this.onExitActions.addAll(onExitActions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for end states.
|
||||
* <p>
|
||||
* A state that terminates this flow when entered. Defines a flow outcome.
|
||||
* <p>
|
||||
* An end state is not transitionable; there are never transitions out of an end state. When an end-state is entered, an
|
||||
* instance of this flow is terminated.
|
||||
* <p>
|
||||
* When this flow terminates, if it was the "root" flow the entire execution is terminated. If this flow was a subflow,
|
||||
* its parent flow resumes.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class EndStateModel extends AbstractStateModel {
|
||||
private String view;
|
||||
private String commit;
|
||||
private LinkedList outputs;
|
||||
|
||||
/**
|
||||
* Create an end state model
|
||||
* @param id the state identifier
|
||||
*/
|
||||
public EndStateModel(String id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an end state model
|
||||
* @param id the state identifier
|
||||
* @param view the view to render
|
||||
* @param commit indicate if the persistence context should be committed
|
||||
* @param outputs output mappings
|
||||
* @param attributes meta attributes for the state
|
||||
* @param secured security settings for the state
|
||||
* @param onEntryActions actions to execute when entering the state
|
||||
* @param exceptionHandlers exception handlers for the state
|
||||
*/
|
||||
public EndStateModel(String id, String view, String commit, LinkedList outputs, LinkedList attributes,
|
||||
SecuredModel secured, LinkedList onEntryActions, LinkedList exceptionHandlers) {
|
||||
setId(id);
|
||||
setView(view);
|
||||
setCommit(commit);
|
||||
setOutputs(outputs);
|
||||
setAttributes(attributes);
|
||||
setSecured(secured);
|
||||
setOnEntryActions(onEntryActions);
|
||||
setExceptionHandlers(exceptionHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the end state to merge into this state
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
EndStateModel state = (EndStateModel) model;
|
||||
setAttributes(merge(getAttributes(), state.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), state.getSecured()));
|
||||
setOnEntryActions(merge(getOnEntryActions(), state.getOnEntryActions(), false));
|
||||
setExceptionHandlers(merge(getExceptionHandlers(), state.getExceptionHandlers()));
|
||||
setView(merge(getView(), state.getView()));
|
||||
setCommit(merge(getCommit(), state.getCommit()));
|
||||
setOutputs(merge(getOutputs(), state.getOutputs(), false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this end state
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof EndStateModel)) {
|
||||
return false;
|
||||
}
|
||||
EndStateModel state = (EndStateModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getId(), state.getId());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof EndStateModel)) {
|
||||
return false;
|
||||
}
|
||||
EndStateModel state = (EndStateModel) obj;
|
||||
if (state == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getId(), state.getId())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), state.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), state.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnEntryActions(), state.getOnEntryActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExceptionHandlers(), state.getExceptionHandlers())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getView(), state.getView())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getCommit(), state.getCommit())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOutputs(), state.getOutputs())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hasCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getId()) * 27 + ObjectUtils.nullSafeHashCode(getAttributes()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getSecured()) * 27 + ObjectUtils.nullSafeHashCode(getOnEntryActions())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getExceptionHandlers()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getView()) * 27 + ObjectUtils.nullSafeHashCode(getCommit()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOutputs()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the view
|
||||
*/
|
||||
public String getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param view the view factory to set
|
||||
*/
|
||||
public void setView(String view) {
|
||||
if (StringUtils.hasText(view)) {
|
||||
this.view = view;
|
||||
} else {
|
||||
this.view = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the commit
|
||||
*/
|
||||
public String getCommit() {
|
||||
return commit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param commit the commit to set
|
||||
*/
|
||||
public void setCommit(String commit) {
|
||||
if (StringUtils.hasText(commit)) {
|
||||
this.commit = commit;
|
||||
} else {
|
||||
this.commit = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the outputs
|
||||
*/
|
||||
public LinkedList getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputs the outputs to set
|
||||
*/
|
||||
public void setOutputs(LinkedList outputs) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param output the output mapping to add
|
||||
*/
|
||||
public void addOutput(OutputModel output) {
|
||||
if (output == null) {
|
||||
return;
|
||||
}
|
||||
if (outputs == null) {
|
||||
outputs = new LinkedList();
|
||||
}
|
||||
outputs.add(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputs the output mappings to add
|
||||
*/
|
||||
public void addOutputs(LinkedList outputs) {
|
||||
if (outputs == null || outputs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.outputs == null) {
|
||||
this.outputs = new LinkedList();
|
||||
}
|
||||
this.outputs.addAll(outputs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for evaluate actions.
|
||||
* <p>
|
||||
* Evaluates an expression against the flow request context.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class EvaluateModel extends AbstractActionModel {
|
||||
private String expression;
|
||||
private String result;
|
||||
private String resultType;
|
||||
|
||||
/**
|
||||
* Create an evaluate action model
|
||||
* @param expression the expression to evaluate
|
||||
*/
|
||||
public EvaluateModel(String expression) {
|
||||
setExpression(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an evaluate action model
|
||||
* @param expression the expression to evaluate
|
||||
* @param result where to store the result of the expressions
|
||||
*/
|
||||
public EvaluateModel(String expression, String result) {
|
||||
setExpression(expression);
|
||||
setResult(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an evaluate action model
|
||||
* @param expression the expression to evaluate
|
||||
* @param result where to store the result of the expressions
|
||||
* @param resultType the type of the result
|
||||
*/
|
||||
public EvaluateModel(String expression, String result, String resultType) {
|
||||
setExpression(expression);
|
||||
setResult(result);
|
||||
setResultType(resultType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the evaluate action to merge into this evaluate
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
EvaluateModel evaluate = (EvaluateModel) model;
|
||||
setResult(merge(getResult(), evaluate.getResult()));
|
||||
setResultType(merge(getResultType(), evaluate.getResultType()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this evaluate action
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof EvaluateModel)) {
|
||||
return false;
|
||||
}
|
||||
EvaluateModel evaluate = (EvaluateModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getExpression(), evaluate.getExpression());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof EvaluateModel)) {
|
||||
return false;
|
||||
}
|
||||
EvaluateModel evaluate = (EvaluateModel) obj;
|
||||
if (evaluate == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExpression(), evaluate.getExpression())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getResult(), evaluate.getResult())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getResultType(), evaluate.getResultType())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getExpression()) * 27 + ObjectUtils.nullSafeHashCode(getResult()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getResultType()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression
|
||||
*/
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expression the expression to set
|
||||
*/
|
||||
public void setExpression(String expression) {
|
||||
if (StringUtils.hasText(expression)) {
|
||||
this.expression = expression;
|
||||
} else {
|
||||
this.expression = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the result
|
||||
*/
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param result the result to set
|
||||
*/
|
||||
public void setResult(String result) {
|
||||
if (StringUtils.hasText(result)) {
|
||||
this.result = result;
|
||||
} else {
|
||||
this.result = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the result type
|
||||
*/
|
||||
public String getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resultType the result type to set
|
||||
*/
|
||||
public void setResultType(String resultType) {
|
||||
if (StringUtils.hasText(resultType)) {
|
||||
this.resultType = resultType;
|
||||
} else {
|
||||
this.resultType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for exception handlers.
|
||||
* <p>
|
||||
* Handles exceptions that occur during flow execution. Exception handlers may be attached at the state or flow level.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class ExceptionHandlerModel extends AbstractModel {
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* Create an exception handler model
|
||||
* @param beanName the name of the bean to handle exceptions
|
||||
*/
|
||||
public ExceptionHandlerModel(String beanName) {
|
||||
setBeanName(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception handlers are not mergeable
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
// not mergable
|
||||
}
|
||||
|
||||
public boolean isMergeableWith(Model model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof ExceptionHandlerModel)) {
|
||||
return false;
|
||||
}
|
||||
ExceptionHandlerModel exceptionHandler = (ExceptionHandlerModel) obj;
|
||||
if (exceptionHandler == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getBeanName(), exceptionHandler.getBeanName())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getBeanName()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bean name
|
||||
*/
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param beanName the bean name to set
|
||||
*/
|
||||
public void setBeanName(String beanName) {
|
||||
if (StringUtils.hasText(beanName)) {
|
||||
this.beanName = beanName;
|
||||
} else {
|
||||
this.beanName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,705 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for flows.
|
||||
* <p>
|
||||
* Defines exactly one flow definition. A flow is composed of one or more states that define the steps of a
|
||||
* conversation. One of those steps is the start state, which defines the conversation's starting point. <br>
|
||||
* A flow may also exhibit the following characteristics:
|
||||
* <ul>
|
||||
* <li>Be annotated with attributes that define descriptive properties that may affect flow execution. (See
|
||||
* {@link AttributeModel})
|
||||
* <li>Be secured (See {@link SecuredModel})
|
||||
* <li>Be a persistence context for managing persistent objects during the course of flow execution. (See
|
||||
* {@link PersistenceContextModel})
|
||||
* <li>Instantiate a set of instance variables when started. (See {@link VarModel})
|
||||
* <li>Map input provided by callers that start it (See {@link InputModel})
|
||||
* <li>Return output to callers that end it. (See {@link OutputModel})
|
||||
* <li>Execute actions at start time and end time. (See {@link EvaluateModel}, {@link RenderModel} and
|
||||
* {@link SetModel})
|
||||
* <li>Define transitions shared by all states. (See {@link TransitionModel})
|
||||
* <li>Handle exceptions thrown by during flow execution. (See {@link ExceptionHandlerModel})
|
||||
* <li>Import one or more local bean definition files defining custom flow artifacts (such as actions, exception
|
||||
* handlers, view factories, transition criteria, etc). (See {@link BeanImportModel})
|
||||
* </ul>
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowModel extends AbstractModel {
|
||||
// private String id;
|
||||
private String parent;
|
||||
private String startStateId;
|
||||
private LinkedList attributes;
|
||||
private SecuredModel secured;
|
||||
private PersistenceContextModel persistenceContext;
|
||||
private LinkedList vars;
|
||||
private LinkedList inputs;
|
||||
private LinkedList outputs;
|
||||
private LinkedList onStartActions;
|
||||
private LinkedList states;
|
||||
private LinkedList globalTransitions;
|
||||
private LinkedList onEndActions;
|
||||
private LinkedList exceptionHandlers;
|
||||
private LinkedList beanImports;
|
||||
|
||||
/**
|
||||
* Create a flow model
|
||||
*/
|
||||
public FlowModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the flow to merge into this flow
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
FlowModel flow = (FlowModel) model;
|
||||
setParent(null);
|
||||
setStartStateId(merge(getStartStateId(), flow.getStartStateId()));
|
||||
setAttributes(merge(getAttributes(), flow.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), flow.getSecured()));
|
||||
setPersistenceContext((PersistenceContextModel) merge(getPersistenceContext(), flow.getPersistenceContext()));
|
||||
setVars(merge(getVars(), flow.getVars(), false));
|
||||
setInputs(merge(getInputs(), flow.getInputs()));
|
||||
setOutputs(merge(getOutputs(), flow.getOutputs()));
|
||||
setOnStartActions(merge(getOnStartActions(), flow.getOnStartActions(), false));
|
||||
setStates(merge(getStates(), flow.getStates()));
|
||||
setGlobalTransitions(merge(getGlobalTransitions(), flow.getGlobalTransitions()));
|
||||
setOnEndActions(merge(getOnEndActions(), flow.getOnEndActions(), false));
|
||||
setExceptionHandlers(merge(getExceptionHandlers(), flow.getExceptionHandlers()));
|
||||
setBeanImports(merge(getBeanImports(), flow.getBeanImports()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this flow
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if ((model instanceof FlowModel)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof FlowModel)) {
|
||||
return false;
|
||||
}
|
||||
FlowModel flow = (FlowModel) obj;
|
||||
if (flow == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getParent(), flow.getParent())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getStartStateId(), flow.getStartStateId())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), flow.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), flow.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getPersistenceContext(), flow.getPersistenceContext())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getVars(), flow.getVars())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getInputs(), flow.getInputs())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOutputs(), flow.getOutputs())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnStartActions(), flow.getOnStartActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getStates(), flow.getStates())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getGlobalTransitions(), flow.getGlobalTransitions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnEndActions(), flow.getOnEndActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExceptionHandlers(), flow.getExceptionHandlers())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getBeanImports(), flow.getBeanImports())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getParent()) * 27 + ObjectUtils.nullSafeHashCode(getStartStateId()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getAttributes()) * 27 + ObjectUtils.nullSafeHashCode(getSecured()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getPersistenceContext()) * 27 + ObjectUtils.nullSafeHashCode(getVars())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getInputs()) * 27 + ObjectUtils.nullSafeHashCode(getOutputs()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOnStartActions()) * 27 + ObjectUtils.nullSafeHashCode(getStates())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getGlobalTransitions()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOnEndActions()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getExceptionHandlers()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getBeanImports()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the parent
|
||||
*/
|
||||
public String getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parent the parent to set
|
||||
*/
|
||||
public void setParent(String parent) {
|
||||
if (StringUtils.hasText(parent)) {
|
||||
this.parent = parent;
|
||||
} else {
|
||||
this.parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id of the flow's start state
|
||||
*/
|
||||
public String getStartStateId() {
|
||||
return startStateId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startStateId the id of the flow's start state to set
|
||||
*/
|
||||
public void setStartStateId(String startStateId) {
|
||||
if (StringUtils.hasText(startStateId)) {
|
||||
this.startStateId = startStateId;
|
||||
} else {
|
||||
this.startStateId = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startState the flow's start state to set
|
||||
*/
|
||||
public void setStartState(AbstractStateModel startState) {
|
||||
setStartStateId(startState.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the attributes
|
||||
*/
|
||||
public LinkedList getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set
|
||||
*/
|
||||
public void setAttributes(LinkedList attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attribute the attribute to add
|
||||
*/
|
||||
public void addAttribute(AttributeModel attribute) {
|
||||
if (attribute == null) {
|
||||
return;
|
||||
}
|
||||
if (attributes == null) {
|
||||
attributes = new LinkedList();
|
||||
}
|
||||
attributes.add(attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to add
|
||||
*/
|
||||
public void addAttributes(LinkedList attributes) {
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.attributes == null) {
|
||||
this.attributes = new LinkedList();
|
||||
}
|
||||
this.attributes.addAll(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the secured
|
||||
*/
|
||||
public SecuredModel getSecured() {
|
||||
return secured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param secured the secured to set
|
||||
*/
|
||||
public void setSecured(SecuredModel secured) {
|
||||
this.secured = secured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the persistence context
|
||||
*/
|
||||
public PersistenceContextModel getPersistenceContext() {
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param persistenceContext the persistence context to set
|
||||
*/
|
||||
public void setPersistenceContext(PersistenceContextModel persistenceContext) {
|
||||
this.persistenceContext = persistenceContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vars
|
||||
*/
|
||||
public LinkedList getVars() {
|
||||
return vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vars the vars to set
|
||||
*/
|
||||
public void setVars(LinkedList vars) {
|
||||
this.vars = vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param var the var to add
|
||||
*/
|
||||
public void addVar(VarModel var) {
|
||||
if (var == null) {
|
||||
return;
|
||||
}
|
||||
if (vars == null) {
|
||||
vars = new LinkedList();
|
||||
}
|
||||
vars.add(var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vars the vars to add
|
||||
*/
|
||||
public void addVars(LinkedList vars) {
|
||||
if (vars == null || vars.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.vars == null) {
|
||||
this.vars = new LinkedList();
|
||||
}
|
||||
this.vars.addAll(vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the input mappings
|
||||
*/
|
||||
public LinkedList getInputs() {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputs the input mappings to set
|
||||
*/
|
||||
public void setInputs(LinkedList inputs) {
|
||||
this.inputs = inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param input the input mapping to add
|
||||
*/
|
||||
public void addInput(InputModel input) {
|
||||
if (input == null) {
|
||||
return;
|
||||
}
|
||||
if (inputs == null) {
|
||||
inputs = new LinkedList();
|
||||
}
|
||||
inputs.add(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputs the input mappings to add
|
||||
*/
|
||||
public void addInputs(LinkedList inputs) {
|
||||
if (inputs == null || inputs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.inputs == null) {
|
||||
this.inputs = new LinkedList();
|
||||
}
|
||||
this.inputs.addAll(inputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the output mappings
|
||||
*/
|
||||
public LinkedList getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputs the output mappings to set
|
||||
*/
|
||||
public void setOutputs(LinkedList outputs) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param output the output mapping to add
|
||||
*/
|
||||
public void addOutput(OutputModel output) {
|
||||
if (output == null) {
|
||||
return;
|
||||
}
|
||||
if (outputs == null) {
|
||||
outputs = new LinkedList();
|
||||
}
|
||||
outputs.add(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputs the output mappings to add
|
||||
*/
|
||||
public void addOutputs(LinkedList outputs) {
|
||||
if (outputs == null || outputs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.outputs == null) {
|
||||
this.outputs = new LinkedList();
|
||||
}
|
||||
this.outputs.addAll(outputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on start actions
|
||||
*/
|
||||
public LinkedList getOnStartActions() {
|
||||
return onStartActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onStartActions the on start actions to set
|
||||
*/
|
||||
public void setOnStartActions(LinkedList onStartActions) {
|
||||
this.onStartActions = onStartActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onStartAction the on start action to add
|
||||
*/
|
||||
public void addOnStartAction(AbstractActionModel onStartAction) {
|
||||
if (onStartAction == null) {
|
||||
return;
|
||||
}
|
||||
if (onStartActions == null) {
|
||||
onStartActions = new LinkedList();
|
||||
}
|
||||
onStartActions.add(onStartAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onStartActions the on start actions to add
|
||||
*/
|
||||
public void addOnStartActions(LinkedList onStartActions) {
|
||||
if (onStartActions == null || onStartActions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.onStartActions == null) {
|
||||
this.onStartActions = new LinkedList();
|
||||
}
|
||||
this.onStartActions.addAll(onStartActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the states
|
||||
*/
|
||||
public LinkedList getStates() {
|
||||
return states;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the states to set
|
||||
*/
|
||||
public void setStates(LinkedList states) {
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the state to add
|
||||
*/
|
||||
public void addState(AbstractStateModel state) {
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
if (states == null) {
|
||||
states = new LinkedList();
|
||||
}
|
||||
states.add(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the states to add
|
||||
*/
|
||||
public void addStates(LinkedList states) {
|
||||
if (states == null || states.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.states == null) {
|
||||
this.states = new LinkedList();
|
||||
}
|
||||
this.states.addAll(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the action state to add
|
||||
*/
|
||||
public void addActionState(ActionStateModel state) {
|
||||
addState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the action states to add
|
||||
*/
|
||||
public void addActionStates(LinkedList states) {
|
||||
addStates(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the view state to add
|
||||
*/
|
||||
public void addViewState(ViewStateModel state) {
|
||||
addState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the view states to add
|
||||
*/
|
||||
public void addViewStates(LinkedList states) {
|
||||
addStates(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the decision state to add
|
||||
*/
|
||||
public void addDecisionState(DecisionStateModel state) {
|
||||
addState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the decision states to add
|
||||
*/
|
||||
public void addDecisionStates(LinkedList states) {
|
||||
addStates(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the subflow state to add
|
||||
*/
|
||||
public void addSubflowState(SubflowStateModel state) {
|
||||
addState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the subflow states to add
|
||||
*/
|
||||
public void addSubflowStates(LinkedList states) {
|
||||
addStates(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state the end state to add
|
||||
*/
|
||||
public void addEndState(EndStateModel state) {
|
||||
addState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param states the end states to add
|
||||
*/
|
||||
public void addEndStates(LinkedList states) {
|
||||
addStates(states);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the global transitions
|
||||
*/
|
||||
public LinkedList getGlobalTransitions() {
|
||||
return globalTransitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param globalTransitions the global transitions to set
|
||||
*/
|
||||
public void setGlobalTransitions(LinkedList globalTransitions) {
|
||||
this.globalTransitions = globalTransitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param globalTransition the global transition to add
|
||||
*/
|
||||
public void addGlobalTransition(TransitionModel globalTransition) {
|
||||
if (globalTransition == null) {
|
||||
return;
|
||||
}
|
||||
if (globalTransitions == null) {
|
||||
globalTransitions = new LinkedList();
|
||||
}
|
||||
globalTransitions.add(globalTransition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param globalTransitions the global transitions to add
|
||||
*/
|
||||
public void addGlobalTransitions(LinkedList globalTransitions) {
|
||||
if (globalTransitions == null || globalTransitions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.globalTransitions == null) {
|
||||
this.globalTransitions = new LinkedList();
|
||||
}
|
||||
this.globalTransitions.addAll(globalTransitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on end actions
|
||||
*/
|
||||
public LinkedList getOnEndActions() {
|
||||
return onEndActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onEndActions the on end actions to set
|
||||
*/
|
||||
public void setOnEndActions(LinkedList onEndActions) {
|
||||
this.onEndActions = onEndActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onEndAction the on end action to add
|
||||
*/
|
||||
public void addOnEndAction(AbstractActionModel onEndAction) {
|
||||
if (onEndAction == null) {
|
||||
return;
|
||||
}
|
||||
if (onEndActions == null) {
|
||||
onEndActions = new LinkedList();
|
||||
}
|
||||
onEndActions.add(onEndAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onEndActions the on end actions to add
|
||||
*/
|
||||
public void addOnEndActions(LinkedList onEndActions) {
|
||||
if (onEndActions == null || onEndActions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.onEndActions == null) {
|
||||
this.onEndActions = new LinkedList();
|
||||
}
|
||||
this.onEndActions.addAll(onEndActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the exception handlers
|
||||
*/
|
||||
public LinkedList getExceptionHandlers() {
|
||||
return exceptionHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionHandlers the exception handlers to set
|
||||
*/
|
||||
public void setExceptionHandlers(LinkedList exceptionHandlers) {
|
||||
this.exceptionHandlers = exceptionHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionHandler the exception handler to add
|
||||
*/
|
||||
public void addExceptionHandler(ExceptionHandlerModel exceptionHandler) {
|
||||
if (exceptionHandler == null) {
|
||||
return;
|
||||
}
|
||||
if (exceptionHandlers == null) {
|
||||
exceptionHandlers = new LinkedList();
|
||||
}
|
||||
exceptionHandlers.add(exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionHandlers the exception handlers to add
|
||||
*/
|
||||
public void addExceptionHandlers(LinkedList exceptionHandlers) {
|
||||
if (exceptionHandlers == null || exceptionHandlers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.exceptionHandlers == null) {
|
||||
this.exceptionHandlers = new LinkedList();
|
||||
}
|
||||
this.exceptionHandlers.addAll(exceptionHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bean imports
|
||||
*/
|
||||
public LinkedList getBeanImports() {
|
||||
return beanImports;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param beanImports the bean imports to set
|
||||
*/
|
||||
public void setBeanImports(LinkedList beanImports) {
|
||||
this.beanImports = beanImports;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param beanImport the bean import to add
|
||||
*/
|
||||
public void addBeanImport(BeanImportModel beanImport) {
|
||||
if (beanImport == null) {
|
||||
return;
|
||||
}
|
||||
if (beanImports == null) {
|
||||
beanImports = new LinkedList();
|
||||
}
|
||||
beanImports.add(beanImport);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param beanImports the bean imports to add
|
||||
*/
|
||||
public void addBeanImports(LinkedList beanImports) {
|
||||
if (beanImports == null || beanImports.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.beanImports == null) {
|
||||
this.beanImports = new LinkedList();
|
||||
}
|
||||
this.beanImports.addAll(beanImports);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for if elements.
|
||||
* <p>
|
||||
* Defines a boolean expression to evaluate a target state to transition to if that expression evaluates to true.
|
||||
* Optionally, this element may define an 'else' attribute to define a state to transition to if the expression
|
||||
* evaluates to false.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class IfModel extends AbstractModel {
|
||||
private String test;
|
||||
private String then;
|
||||
private String elze;
|
||||
|
||||
/**
|
||||
* Create an if model
|
||||
* @param test the boolean condition to test
|
||||
* @param then the state to transition to if the boolean expression evaluates to true
|
||||
*/
|
||||
public IfModel(String test, String then) {
|
||||
setTest(test);
|
||||
setThen(then);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an if model
|
||||
* @param test the boolean condition to test
|
||||
* @param then the state to transition to if the boolean expression evaluates to true
|
||||
* @param elze the state to transition to if the boolean expression evaluates to false
|
||||
*/
|
||||
public IfModel(String test, String then, String elze) {
|
||||
setTest(test);
|
||||
setThen(then);
|
||||
setElse(elze);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the conditional to merge into this conditional
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
IfModel conditional = (IfModel) model;
|
||||
setThen(merge(getThen(), conditional.getThen()));
|
||||
setElse(merge(getElse(), conditional.getElse()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this if action
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof IfModel)) {
|
||||
return false;
|
||||
}
|
||||
IfModel conditional = (IfModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getTest(), conditional.getTest());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof IfModel)) {
|
||||
return false;
|
||||
}
|
||||
IfModel conditional = (IfModel) obj;
|
||||
if (conditional == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getTest(), conditional.getTest())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getThen(), conditional.getThen())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getElse(), conditional.getElse())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getTest()) * 27 + ObjectUtils.nullSafeHashCode(getThen()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getElse()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the test
|
||||
*/
|
||||
public String getTest() {
|
||||
return test;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param test the test to set
|
||||
*/
|
||||
public void setTest(String test) {
|
||||
if (StringUtils.hasText(test)) {
|
||||
this.test = test;
|
||||
} else {
|
||||
this.test = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the then
|
||||
*/
|
||||
public String getThen() {
|
||||
return then;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param then the then to set
|
||||
*/
|
||||
public void setThen(String then) {
|
||||
if (StringUtils.hasText(then)) {
|
||||
this.then = then;
|
||||
} else {
|
||||
this.then = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the else
|
||||
*/
|
||||
public String getElse() {
|
||||
return elze;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param elze the else to set
|
||||
*/
|
||||
public void setElse(String elze) {
|
||||
if (StringUtils.hasText(elze)) {
|
||||
this.elze = elze;
|
||||
} else {
|
||||
this.elze = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Model support for input mappings.
|
||||
* <p>
|
||||
* Maps a single input attribute into this flow or subflow.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class InputModel extends AbstractMappingModel {
|
||||
|
||||
/**
|
||||
* Create an input mapping model
|
||||
* @param name the name of the mapping variable
|
||||
* @param value the value to map
|
||||
*/
|
||||
public InputModel(String name, String value) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an input mapping model
|
||||
* @param name the name of the mapping variable
|
||||
* @param value the value to map
|
||||
* @param type the type of the value
|
||||
* @param required indicates if this mapping is required
|
||||
*/
|
||||
public InputModel(String name, String value, String type, String required) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
setType(type);
|
||||
setRequired(required);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the mapping to merge into this mapping
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
InputModel input = (InputModel) model;
|
||||
setValue(merge(getValue(), input.getValue()));
|
||||
setType(merge(getType(), input.getType()));
|
||||
setRequired(merge(getRequired(), input.getRequired()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this input mapping
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof InputModel)) {
|
||||
return false;
|
||||
}
|
||||
InputModel input = (InputModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getName(), input.getName());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof InputModel)) {
|
||||
return false;
|
||||
}
|
||||
InputModel input = (InputModel) obj;
|
||||
if (input == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getName(), input.getName())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getValue(), input.getValue())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getType(), input.getType())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getRequired(), input.getRequired())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getName()) * 27 + ObjectUtils.nullSafeHashCode(getValue()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getType()) * 27 + ObjectUtils.nullSafeHashCode(getRequired()) * 27;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.springframework.webflow.engine.model;
|
||||
|
||||
/**
|
||||
* Interface defining models. All models must be able to handle merging of their content with an eligible model.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface Model {
|
||||
|
||||
/**
|
||||
* Determine if the model is able to be merged into the current model
|
||||
* @param model the model to compare
|
||||
* @return true if able to merge
|
||||
*/
|
||||
public boolean isMergeableWith(Model model);
|
||||
|
||||
/**
|
||||
* Merge the model into the current model
|
||||
* @param model the model to merge with
|
||||
*/
|
||||
public void merge(Model model);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Model support for output mappings.
|
||||
* <p>
|
||||
* Maps a single output attribute out of this flow or subflow.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class OutputModel extends AbstractMappingModel {
|
||||
|
||||
/**
|
||||
* Create an output mapping model
|
||||
* @param name the name of the mapping variable
|
||||
* @param value the value to map
|
||||
*/
|
||||
public OutputModel(String name, String value) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an output mapping model
|
||||
* @param name the name of the mapping variable
|
||||
* @param value the value to map
|
||||
* @param type the type of the value
|
||||
* @param required indicates if this mapping is required
|
||||
*/
|
||||
public OutputModel(String name, String value, String type, String required) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
setType(type);
|
||||
setRequired(required);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the mapping to merge into this mapping
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
OutputModel output = (OutputModel) model;
|
||||
setValue(merge(getValue(), output.getValue()));
|
||||
setType(merge(getType(), output.getType()));
|
||||
setRequired(merge(getRequired(), output.getRequired()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this output mapping
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof OutputModel)) {
|
||||
return false;
|
||||
}
|
||||
OutputModel output = (OutputModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getName(), output.getName());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof InputModel)) {
|
||||
return false;
|
||||
}
|
||||
OutputModel output = (OutputModel) obj;
|
||||
if (output == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getName(), output.getName())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getValue(), output.getValue())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getType(), output.getType())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getRequired(), output.getRequired())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getName()) * 27 + ObjectUtils.nullSafeHashCode(getValue()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getType()) * 27 + ObjectUtils.nullSafeHashCode(getRequired()) * 27;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
/**
|
||||
* Model support for persistence context elements.
|
||||
* <p>
|
||||
* Allocates a persistence context when this flow starts. The persistence context is closed when the flow ends. If the
|
||||
* flow ends by reaching a "commit" end-state, changes made to managed persistent entities during the course of flow
|
||||
* execution are flushed to the database in a transaction.
|
||||
* <p>
|
||||
* The persistence context can be referenced from within this flow by the "entityManager" variable.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class PersistenceContextModel extends AbstractModel {
|
||||
|
||||
/**
|
||||
* Create a persistence context model
|
||||
*/
|
||||
public PersistenceContextModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistence contexts are not mergeable
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
// not mergeable
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistence contexts are not mergeable
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for render actions.
|
||||
* <p>
|
||||
* Requests that the next view render a fragment of content. Multiple fragments may be specified using a comma
|
||||
* delimiter.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class RenderModel extends AbstractActionModel {
|
||||
private String fragments;
|
||||
|
||||
/**
|
||||
* Create a render action model
|
||||
* @param fragments the fragments to render
|
||||
*/
|
||||
public RenderModel(String fragments) {
|
||||
setFragments(fragments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render action models are not mergeable
|
||||
* @param model the render action to merge into this render
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
// not mergeable
|
||||
}
|
||||
|
||||
/**
|
||||
* Render action models are not mergeable
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof RenderModel)) {
|
||||
return false;
|
||||
}
|
||||
RenderModel render = (RenderModel) obj;
|
||||
if (render == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getFragments(), render.getFragments())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getFragments()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fragments
|
||||
*/
|
||||
public String getFragments() {
|
||||
return fragments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fragments the fragments to set
|
||||
*/
|
||||
public void setFragments(String fragments) {
|
||||
if (StringUtils.hasText(fragments)) {
|
||||
this.fragments = fragments;
|
||||
} else {
|
||||
this.fragments = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.security.SecurityFlowExecutionListener;
|
||||
|
||||
/**
|
||||
* Model support for secured elements.
|
||||
* <p>
|
||||
* Secures a flow, state or transition. The user invoking this element must meet the required attributes otherwise
|
||||
* access will be denied.
|
||||
* <p>
|
||||
* <b>Warning:</b> This model will only configure a security attribute in the definition. The flow execution must also
|
||||
* be secured with a SecurityFlowExecutionListener.
|
||||
*
|
||||
* @see SecurityFlowExecutionListener
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class SecuredModel extends AbstractModel {
|
||||
private String attributes;
|
||||
private String match;
|
||||
|
||||
/**
|
||||
* Create a security settings model
|
||||
* @param attributes the security attributes
|
||||
*/
|
||||
public SecuredModel(String attributes) {
|
||||
setAttributes(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a security settings model
|
||||
* @param attributes the security attributes
|
||||
* @param match the type of matching for the attributes
|
||||
*/
|
||||
public SecuredModel(String attributes, String match) {
|
||||
setAttributes(attributes);
|
||||
setMatch(match);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the secured to merge into this secured
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
SecuredModel secured = (SecuredModel) model;
|
||||
setMatch(merge(getMatch(), secured.getMatch()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this secured attribute
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof SecuredModel)) {
|
||||
return false;
|
||||
}
|
||||
SecuredModel secured = (SecuredModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getAttributes(), secured.getAttributes());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof SecuredModel)) {
|
||||
return false;
|
||||
}
|
||||
SecuredModel secured = (SecuredModel) obj;
|
||||
if (secured == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), secured.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getMatch(), secured.getMatch())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getAttributes()) * 27 + ObjectUtils.nullSafeHashCode(getMatch()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the attributes
|
||||
*/
|
||||
public String getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set
|
||||
*/
|
||||
public void setAttributes(String attributes) {
|
||||
if (StringUtils.hasText(attributes)) {
|
||||
this.attributes = attributes;
|
||||
} else {
|
||||
this.attributes = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the match
|
||||
*/
|
||||
public String getMatch() {
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param match the match to set
|
||||
*/
|
||||
public void setMatch(String match) {
|
||||
if (StringUtils.hasText(match)) {
|
||||
this.match = match;
|
||||
} else {
|
||||
this.match = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for set actions.
|
||||
* <p>
|
||||
* Sets an attribute value in a scope.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class SetModel extends AbstractActionModel {
|
||||
private String name;
|
||||
private String value;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Create a set action model
|
||||
* @param name the name of the property to set
|
||||
* @param value the value to set
|
||||
*/
|
||||
public SetModel(String name, String value) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a set action model
|
||||
* @param name the name of the property to set
|
||||
* @param value the value to set
|
||||
* @param type the type of the property
|
||||
*/
|
||||
public SetModel(String name, String value, String type) {
|
||||
setName(name);
|
||||
setValue(value);
|
||||
setType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the set action to merge into this set
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
SetModel set = (SetModel) model;
|
||||
setValue(merge(getValue(), set.getValue()));
|
||||
setType(merge(getType(), set.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this set action
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof SetModel)) {
|
||||
return false;
|
||||
}
|
||||
SetModel set = (SetModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getName(), set.getName());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof SetModel)) {
|
||||
return false;
|
||||
}
|
||||
SetModel set = (SetModel) obj;
|
||||
if (set == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getName(), set.getName())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getValue(), set.getValue())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getType(), set.getType())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getName()) * 27 + ObjectUtils.nullSafeHashCode(getValue()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getType()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
if (StringUtils.hasText(name)) {
|
||||
this.name = name;
|
||||
} else {
|
||||
this.name = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
this.value = value;
|
||||
} else {
|
||||
this.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type the type to set
|
||||
*/
|
||||
public void setType(String type) {
|
||||
if (StringUtils.hasText(type)) {
|
||||
this.type = type;
|
||||
} else {
|
||||
this.type = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for subflow states.
|
||||
* <p>
|
||||
* Starts another flow as a subflow when entered. When the subflow ends, this state is expected to respond to its result
|
||||
* by executing a transition.
|
||||
* <p>
|
||||
* A subflow state is a transitionable state. A transition is triggered by the subflow outcome that was reached.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class SubflowStateModel extends AbstractTransitionableStateModel {
|
||||
private String subflow;
|
||||
private String subflowAttributeMapper;
|
||||
private LinkedList inputs;
|
||||
private LinkedList outputs;
|
||||
|
||||
/**
|
||||
* Create a subflow state model
|
||||
* @param id the identifier of the state
|
||||
* @param subflow the identifier of the flow to launch as a subflow
|
||||
*/
|
||||
public SubflowStateModel(String id, String subflow) {
|
||||
setId(id);
|
||||
setSubflow(subflow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a subflow state model
|
||||
* @param id the identifier of the state
|
||||
* @param subflow the identifier of the flow to launch as a subflow
|
||||
* @param subflowAttributeMapper bean name of the attribute mapping
|
||||
* @param inputs input mappings
|
||||
* @param outputs output mappings
|
||||
* @param attributes meta attributes for the state
|
||||
* @param secured security settings for the state
|
||||
* @param onEntryActions actions to be executed when entering the state
|
||||
* @param exceptionHandlers exception handlers for the state
|
||||
* @param transitions transitions for the state
|
||||
* @param onExitActions actions to be executed before leaving the state.
|
||||
*/
|
||||
public SubflowStateModel(String id, String subflow, String subflowAttributeMapper, LinkedList inputs,
|
||||
LinkedList outputs, LinkedList attributes, SecuredModel secured, LinkedList onEntryActions,
|
||||
LinkedList exceptionHandlers, LinkedList transitions, LinkedList onExitActions) {
|
||||
setId(id);
|
||||
setSubflow(subflow);
|
||||
setSubflowAttributeMapper(subflowAttributeMapper);
|
||||
setInputs(inputs);
|
||||
setOutputs(outputs);
|
||||
setAttributes(attributes);
|
||||
setSecured(secured);
|
||||
setOnEntryActions(onEntryActions);
|
||||
setExceptionHandlers(exceptionHandlers);
|
||||
setTransitions(transitions);
|
||||
setOnExitActions(onExitActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the subflow state to merge into this state
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
SubflowStateModel state = (SubflowStateModel) model;
|
||||
setAttributes(merge(getAttributes(), state.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), state.getSecured()));
|
||||
setOnEntryActions(merge(getOnEntryActions(), state.getOnEntryActions(), false));
|
||||
setExceptionHandlers(merge(getExceptionHandlers(), state.getExceptionHandlers()));
|
||||
setTransitions(merge(getTransitions(), state.getTransitions()));
|
||||
setOnExitActions(merge(getOnExitActions(), state.getOnExitActions(), false));
|
||||
setSubflow(merge(getSubflow(), state.getSubflow()));
|
||||
setSubflowAttributeMapper(merge(getSubflowAttributeMapper(), state.getSubflowAttributeMapper()));
|
||||
setInputs(merge(getInputs(), state.getInputs()));
|
||||
setOutputs(merge(getOutputs(), state.getOutputs()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this subflow state
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof SubflowStateModel)) {
|
||||
return false;
|
||||
}
|
||||
SubflowStateModel state = (SubflowStateModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getId(), state.getId());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof SubflowStateModel)) {
|
||||
return false;
|
||||
}
|
||||
SubflowStateModel state = (SubflowStateModel) obj;
|
||||
if (state == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getId(), state.getId())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), state.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), state.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnEntryActions(), state.getOnEntryActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExceptionHandlers(), state.getExceptionHandlers())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getTransitions(), state.getTransitions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnExitActions(), state.getOnExitActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSubflow(), state.getSubflow())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSubflowAttributeMapper(), state.getSubflowAttributeMapper())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getInputs(), state.getInputs())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOutputs(), state.getOutputs())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getId()) * 27 + ObjectUtils.nullSafeHashCode(getAttributes()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getSecured()) * 27 + ObjectUtils.nullSafeHashCode(getOnEntryActions())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getExceptionHandlers()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getTransitions()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOnExitActions()) * 27 + ObjectUtils.nullSafeHashCode(getSubflow())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getSubflowAttributeMapper()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getInputs()) * 27 + ObjectUtils.nullSafeHashCode(getOutputs()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the subflow
|
||||
*/
|
||||
public String getSubflow() {
|
||||
return subflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subflow the subflow to set
|
||||
*/
|
||||
public void setSubflow(String subflow) {
|
||||
if (StringUtils.hasText(subflow)) {
|
||||
this.subflow = subflow;
|
||||
} else {
|
||||
this.subflow = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the subflow attribute mapper
|
||||
*/
|
||||
public String getSubflowAttributeMapper() {
|
||||
return subflowAttributeMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subflowAttributeMapper the subflow attribute mapper to set
|
||||
*/
|
||||
public void setSubflowAttributeMapper(String subflowAttributeMapper) {
|
||||
if (StringUtils.hasText(subflowAttributeMapper)) {
|
||||
this.subflowAttributeMapper = subflowAttributeMapper;
|
||||
} else {
|
||||
this.subflowAttributeMapper = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the input mappings
|
||||
*/
|
||||
public LinkedList getInputs() {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputs the input mappings to set
|
||||
*/
|
||||
public void setInputs(LinkedList inputs) {
|
||||
this.inputs = inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param input the input mapping to add
|
||||
*/
|
||||
public void addInput(InputModel input) {
|
||||
if (input == null) {
|
||||
return;
|
||||
}
|
||||
if (inputs == null) {
|
||||
inputs = new LinkedList();
|
||||
}
|
||||
inputs.add(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inputs the input mappings to add
|
||||
*/
|
||||
public void addInputs(LinkedList inputs) {
|
||||
if (inputs == null || inputs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.inputs == null) {
|
||||
this.inputs = new LinkedList();
|
||||
}
|
||||
this.inputs.addAll(inputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the output mappings
|
||||
*/
|
||||
public LinkedList getOutputs() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputs the output mappings to set
|
||||
*/
|
||||
public void setOutputs(LinkedList outputs) {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param output the output mapping to add
|
||||
*/
|
||||
public void addOutput(OutputModel output) {
|
||||
if (output == null) {
|
||||
return;
|
||||
}
|
||||
if (outputs == null) {
|
||||
outputs = new LinkedList();
|
||||
}
|
||||
outputs.add(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outputs the output mappings to add
|
||||
*/
|
||||
public void addOutputs(LinkedList outputs) {
|
||||
if (outputs == null || outputs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.outputs == null) {
|
||||
this.outputs = new LinkedList();
|
||||
}
|
||||
this.outputs.addAll(outputs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for transitions.
|
||||
* <p>
|
||||
* A path from this state to another state triggered by an event. Transitions may execute one or more actions. All
|
||||
* transition actions must execute successfully for the transition itself to complete. If no transition target is
|
||||
* specified, the transition acts as a simple event handler and does not change the state of the flow.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class TransitionModel extends AbstractModel {
|
||||
private String on;
|
||||
private String onException;
|
||||
private String to;
|
||||
private String bind;
|
||||
private LinkedList attributes;
|
||||
private SecuredModel secured;
|
||||
private LinkedList actions;
|
||||
|
||||
/**
|
||||
* Create a transition model
|
||||
* @param on the matching criteria
|
||||
*/
|
||||
public TransitionModel(String on) {
|
||||
setOn(on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transition model
|
||||
* @param on the matching criteria
|
||||
* @param to the identifier of the state to target
|
||||
*/
|
||||
public TransitionModel(String on, String to) {
|
||||
setOn(on);
|
||||
setTo(to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transition model
|
||||
* @param on the matching criteria
|
||||
* @param to the identifier of the state to target
|
||||
* @param onException class name of the exception to handle
|
||||
* @param bind if the transition should bind to the defined model. Valid only for view state transitions
|
||||
* @param attributes meta attributes for the transition
|
||||
* @param secured security settings for the transition
|
||||
* @param actions actions to be executed after matching the transition
|
||||
*/
|
||||
public TransitionModel(String on, String to, String onException, String bind, LinkedList attributes,
|
||||
SecuredModel secured, LinkedList actions) {
|
||||
setOn(on);
|
||||
setTo(to);
|
||||
setOnException(onException);
|
||||
setBind(bind);
|
||||
setAttributes(attributes);
|
||||
setSecured(secured);
|
||||
setActions(actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the transition to merge into this transition
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
TransitionModel transition = (TransitionModel) model;
|
||||
setOnException(merge(getOnException(), transition.getOnException()));
|
||||
setTo(merge(getTo(), transition.getTo()));
|
||||
setBind(merge(getBind(), transition.getBind()));
|
||||
setAttributes(merge(getAttributes(), transition.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), transition.getSecured()));
|
||||
setActions(merge(getActions(), transition.getActions(), false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this transition
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof TransitionModel)) {
|
||||
return false;
|
||||
}
|
||||
TransitionModel transition = (TransitionModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getOn(), transition.getOn());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof TransitionModel)) {
|
||||
return false;
|
||||
}
|
||||
TransitionModel transition = (TransitionModel) obj;
|
||||
if (transition == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOn(), transition.getOn())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnException(), transition.getOnException())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getTo(), transition.getTo())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getBind(), transition.getBind())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), transition.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), transition.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getActions(), transition.getActions())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getOn()) * 27 + ObjectUtils.nullSafeHashCode(getOnException()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getTo()) * 27 + ObjectUtils.nullSafeHashCode(getBind()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getAttributes()) * 27 + ObjectUtils.nullSafeHashCode(getSecured()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getActions()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on
|
||||
*/
|
||||
public String getOn() {
|
||||
return on;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param on the on to set
|
||||
*/
|
||||
public void setOn(String on) {
|
||||
if (StringUtils.hasText(on)) {
|
||||
this.on = on;
|
||||
} else {
|
||||
this.on = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on exception
|
||||
*/
|
||||
public String getOnException() {
|
||||
return onException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onException the on exception to set
|
||||
*/
|
||||
public void setOnException(String onException) {
|
||||
if (StringUtils.hasText(onException)) {
|
||||
this.onException = onException;
|
||||
} else {
|
||||
this.onException = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the to
|
||||
*/
|
||||
public String getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param to the to to set
|
||||
*/
|
||||
public void setTo(String to) {
|
||||
if (StringUtils.hasText(to)) {
|
||||
this.to = to;
|
||||
} else {
|
||||
this.to = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bind
|
||||
*/
|
||||
public String getBind() {
|
||||
return bind;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bind the bind to set
|
||||
*/
|
||||
public void setBind(String bind) {
|
||||
if (StringUtils.hasText(bind)) {
|
||||
this.bind = bind;
|
||||
} else {
|
||||
this.bind = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the attributes
|
||||
*/
|
||||
public LinkedList getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set
|
||||
*/
|
||||
public void setAttributes(LinkedList attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attribute the attribute to add
|
||||
*/
|
||||
public void addAttribute(AttributeModel attribute) {
|
||||
if (attribute == null) {
|
||||
return;
|
||||
}
|
||||
if (attributes == null) {
|
||||
attributes = new LinkedList();
|
||||
}
|
||||
attributes.add(attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to add
|
||||
*/
|
||||
public void addAttributes(LinkedList attributes) {
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.attributes == null) {
|
||||
this.attributes = new LinkedList();
|
||||
}
|
||||
this.attributes.addAll(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the secured
|
||||
*/
|
||||
public SecuredModel getSecured() {
|
||||
return secured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param secured the secured to set
|
||||
*/
|
||||
public void setSecured(SecuredModel secured) {
|
||||
this.secured = secured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actions
|
||||
*/
|
||||
public LinkedList getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actions the actions to set
|
||||
*/
|
||||
public void setActions(LinkedList actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param action the action to add
|
||||
*/
|
||||
public void addAction(AbstractActionModel action) {
|
||||
if (action == null) {
|
||||
return;
|
||||
}
|
||||
if (actions == null) {
|
||||
actions = new LinkedList();
|
||||
}
|
||||
actions.add(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actions the actions to add
|
||||
*/
|
||||
public void addActions(LinkedList actions) {
|
||||
if (actions == null || actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.actions == null) {
|
||||
this.actions = new LinkedList();
|
||||
}
|
||||
this.actions.addAll(actions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for var elements.
|
||||
* <p>
|
||||
* An instance variable. Variables are created when the flow starts or state enters and destroyed when the flow or state
|
||||
* ends, respectively.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class VarModel extends AbstractModel {
|
||||
private String name;
|
||||
private String className;
|
||||
private String scope;
|
||||
|
||||
/**
|
||||
* Create a variable model
|
||||
* @param name the name of the variable
|
||||
* @param className the class type of the variable
|
||||
*/
|
||||
public VarModel(String name, String className) {
|
||||
setName(name);
|
||||
setClassName(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a variable model
|
||||
* @param name the name of the variable
|
||||
* @param className the class type of the variable
|
||||
* @param scope the scope to store the variable
|
||||
*/
|
||||
public VarModel(String name, String className, String scope) {
|
||||
setName(name);
|
||||
setClassName(className);
|
||||
setScope(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the var to merge into this var
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
VarModel var = (VarModel) model;
|
||||
setClassName(merge(getClassName(), var.getClassName()));
|
||||
setScope(merge(getScope(), var.getScope()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this var
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof VarModel)) {
|
||||
return false;
|
||||
}
|
||||
VarModel var = (VarModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getName(), var.getName());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof VarModel)) {
|
||||
return false;
|
||||
}
|
||||
VarModel var = (VarModel) obj;
|
||||
if (var == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getName(), var.getName())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getClassName(), var.getClassName())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getScope(), var.getScope())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getName()) * 27 + ObjectUtils.nullSafeHashCode(getClassName()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getScope()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
if (StringUtils.hasText(name)) {
|
||||
this.name = name;
|
||||
} else {
|
||||
this.name = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the class name
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param className the class name to set
|
||||
*/
|
||||
public void setClassName(String className) {
|
||||
if (StringUtils.hasText(className)) {
|
||||
this.className = className;
|
||||
} else {
|
||||
this.className = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scope
|
||||
*/
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scope the scope to set
|
||||
*/
|
||||
public void setScope(String scope) {
|
||||
if (StringUtils.hasText(scope)) {
|
||||
this.scope = scope;
|
||||
} else {
|
||||
this.scope = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Model support for view states.
|
||||
* <p>
|
||||
* A state where the user participates. When a view state is entered, this flow pauses and control goes to the user.
|
||||
* After some think time, the user resumes this flow at the view-state by signaling an event.
|
||||
* <p>
|
||||
* Once paused, a view-state may be 'refreshed' by the user. A refresh causes the response to be reissued and then
|
||||
* returns control back to the user.
|
||||
* <p>
|
||||
* A view state may be configured with one or more render-actions using the 'on-render' element. Render actions are
|
||||
* executed immediately before the view is rendered.
|
||||
* <p>
|
||||
* A view state is a transitionable state. A view state transition is triggered by a user event.
|
||||
*
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class ViewStateModel extends AbstractTransitionableStateModel {
|
||||
private String view;
|
||||
private String redirect;
|
||||
private String popup;
|
||||
private String model;
|
||||
private LinkedList vars;
|
||||
private LinkedList onRenderActions;
|
||||
|
||||
/**
|
||||
* Create a view state model
|
||||
* @param id the identifier of the state
|
||||
*/
|
||||
public ViewStateModel(String id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a view state model
|
||||
* @param id the identifier of the state
|
||||
* @param view the view to render
|
||||
*/
|
||||
public ViewStateModel(String id, String view) {
|
||||
setId(id);
|
||||
setView(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a view state model
|
||||
* @param id the identifier of the state
|
||||
* @param view the view to render
|
||||
* @param redirect request a flow execution redirect before render
|
||||
* @param popup view should render in a popup dialog
|
||||
* @param model the model object to bind for this view
|
||||
* @param vars variables for this state
|
||||
* @param onRenderActions actions to be executed before rendering
|
||||
* @param attributes meta attributes for this state
|
||||
* @param secured the security settings for this state
|
||||
* @param onEntryActions actions to be executed on entry
|
||||
* @param exceptionHandlers exception handlers for this state
|
||||
* @param transitions transitions for this state
|
||||
* @param onExitActions actions to be executed before exiting
|
||||
*/
|
||||
public ViewStateModel(String id, String view, String redirect, String popup, String model, LinkedList vars,
|
||||
LinkedList onRenderActions, LinkedList attributes, SecuredModel secured, LinkedList onEntryActions,
|
||||
LinkedList exceptionHandlers, LinkedList transitions, LinkedList onExitActions) {
|
||||
setId(id);
|
||||
setView(view);
|
||||
setRedirect(redirect);
|
||||
setPopup(popup);
|
||||
setModel(model);
|
||||
setVars(vars);
|
||||
setOnRenderActions(onRenderActions);
|
||||
setAttributes(attributes);
|
||||
setSecured(secured);
|
||||
setOnEntryActions(onEntryActions);
|
||||
setExceptionHandlers(exceptionHandlers);
|
||||
setTransitions(transitions);
|
||||
setOnExitActions(onExitActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge properties
|
||||
* @param model the view state to merge into this state
|
||||
*/
|
||||
public void merge(Model model) {
|
||||
if (isMergeableWith(model)) {
|
||||
ViewStateModel state = (ViewStateModel) model;
|
||||
setAttributes(merge(getAttributes(), state.getAttributes()));
|
||||
setSecured((SecuredModel) merge(getSecured(), state.getSecured()));
|
||||
setOnEntryActions(merge(getOnEntryActions(), state.getOnEntryActions(), false));
|
||||
setExceptionHandlers(merge(getExceptionHandlers(), state.getExceptionHandlers()));
|
||||
setTransitions(merge(getTransitions(), state.getTransitions()));
|
||||
setOnExitActions(merge(getOnExitActions(), state.getOnExitActions(), false));
|
||||
setView(merge(getView(), state.getView()));
|
||||
setRedirect(merge(getRedirect(), state.getRedirect()));
|
||||
setPopup(merge(getPopup(), state.getPopup()));
|
||||
setModel(merge(getModel(), state.getModel()));
|
||||
setVars(merge(getVars(), state.getVars(), false));
|
||||
setOnRenderActions(merge(getOnRenderActions(), state.getOnRenderActions(), false));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the model is able to be merged with this view state
|
||||
* @param model the model to test
|
||||
*/
|
||||
public boolean isMergeableWith(Model model) {
|
||||
if (model == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(model instanceof ViewStateModel)) {
|
||||
return false;
|
||||
}
|
||||
ViewStateModel state = (ViewStateModel) model;
|
||||
return ObjectUtils.nullSafeEquals(getId(), state.getId());
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (!(obj instanceof ViewStateModel)) {
|
||||
return false;
|
||||
}
|
||||
ViewStateModel state = (ViewStateModel) obj;
|
||||
if (state == null) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getId(), state.getId())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getAttributes(), state.getAttributes())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getSecured(), state.getSecured())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnEntryActions(), state.getOnEntryActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getExceptionHandlers(), state.getExceptionHandlers())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getTransitions(), state.getTransitions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnExitActions(), state.getOnExitActions())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getView(), state.getView())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getRedirect(), state.getRedirect())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getPopup(), state.getPopup())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getModel(), state.getModel())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getVars(), state.getVars())) {
|
||||
return false;
|
||||
} else if (!ObjectUtils.nullSafeEquals(getOnRenderActions(), state.getOnRenderActions())) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(getId()) * 27 + ObjectUtils.nullSafeHashCode(getAttributes()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getSecured()) * 27 + ObjectUtils.nullSafeHashCode(getOnEntryActions())
|
||||
* 27 + ObjectUtils.nullSafeHashCode(getExceptionHandlers()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getTransitions()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOnExitActions()) * 27 + ObjectUtils.nullSafeHashCode(getView()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getRedirect()) * 27 + ObjectUtils.nullSafeHashCode(getPopup()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getModel()) * 27 + ObjectUtils.nullSafeHashCode(getVars()) * 27
|
||||
+ ObjectUtils.nullSafeHashCode(getOnRenderActions()) * 27;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the view
|
||||
*/
|
||||
public String getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param view the view to set
|
||||
*/
|
||||
public void setView(String view) {
|
||||
if (StringUtils.hasText(view)) {
|
||||
this.view = view;
|
||||
} else {
|
||||
this.view = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the redirect
|
||||
*/
|
||||
public String getRedirect() {
|
||||
return redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redirect the redirect to set
|
||||
*/
|
||||
public void setRedirect(String redirect) {
|
||||
if (StringUtils.hasText(redirect)) {
|
||||
this.redirect = redirect;
|
||||
} else {
|
||||
this.redirect = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the popup
|
||||
*/
|
||||
public String getPopup() {
|
||||
return popup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param popup the popup to set
|
||||
*/
|
||||
public void setPopup(String popup) {
|
||||
if (StringUtils.hasText(popup)) {
|
||||
this.popup = popup;
|
||||
} else {
|
||||
this.popup = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the model
|
||||
*/
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param model the model to set
|
||||
*/
|
||||
public void setModel(String model) {
|
||||
if (StringUtils.hasText(model)) {
|
||||
this.model = model;
|
||||
} else {
|
||||
this.model = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vars
|
||||
*/
|
||||
public LinkedList getVars() {
|
||||
return vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vars the vars to set
|
||||
*/
|
||||
public void setVars(LinkedList vars) {
|
||||
this.vars = vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param var the var to add
|
||||
*/
|
||||
public void addVar(VarModel var) {
|
||||
if (var == null) {
|
||||
return;
|
||||
}
|
||||
if (vars == null) {
|
||||
vars = new LinkedList();
|
||||
}
|
||||
vars.add(var);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vars the vars to add
|
||||
*/
|
||||
public void addVars(LinkedList vars) {
|
||||
if (vars == null || vars.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.vars == null) {
|
||||
this.vars = new LinkedList();
|
||||
}
|
||||
this.vars.addAll(vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the on render actions
|
||||
*/
|
||||
public LinkedList getOnRenderActions() {
|
||||
return onRenderActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onRenderActions the on render actions to set
|
||||
*/
|
||||
public void setOnRenderActions(LinkedList onRenderActions) {
|
||||
this.onRenderActions = onRenderActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onRenderAction the on render action to add
|
||||
*/
|
||||
public void addOnRenderAction(AbstractActionModel onRenderAction) {
|
||||
if (onRenderAction == null) {
|
||||
return;
|
||||
}
|
||||
if (this.onRenderActions == null) {
|
||||
this.onRenderActions = new LinkedList();
|
||||
}
|
||||
this.onRenderActions.add(onRenderAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onRenderActions the on render actions to add
|
||||
*/
|
||||
public void addOnRenderActions(LinkedList onRenderActions) {
|
||||
if (onRenderActions == null || onRenderActions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.onRenderActions == null) {
|
||||
this.onRenderActions = new LinkedList();
|
||||
}
|
||||
this.onRenderActions.addAll(onRenderActions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2004-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.model.builder;
|
||||
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* Builder interface used to build a flow model. The process of building a flow model consists of the following steps:
|
||||
* <ol>
|
||||
* <li> Initialize this builder by calling {@link #init()}.
|
||||
* <li> Call {@link #build()} to create the flow model.
|
||||
* <li> Call {@link #getFlowModel()} to return the fully-built {@link FlowModel} model.
|
||||
* <li> Dispose this builder, releasing any resources allocated during the building process by calling
|
||||
* {@link #dispose()}.
|
||||
* </ol>
|
||||
* <p>
|
||||
* Implementations should encapsulate flow construction logic, either for a specific kind of flow, for example, an
|
||||
* <code>XmlFlowModelBuilder</code>, for building flows from an XML-definition.
|
||||
* <p>
|
||||
* This is a good example of the classic GoF builder pattern.
|
||||
*
|
||||
* @see FlowModel
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelBuilder {
|
||||
|
||||
/**
|
||||
* Initialize this builder. This could cause the builder to open a stream to an externalized resource representing
|
||||
* the flow definition, for example.
|
||||
* @throws FlowModelBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void init() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Builds any variables initialized by the flow when it starts.
|
||||
* @throws FlowModelBuilderException an exception occurred building the flow
|
||||
*/
|
||||
public void build() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Get the fully constructed flow model. Called by the builder's assembler (director) after assembly. When this
|
||||
* method is called by the assembler, it is expected flow construction has completed and the returned flow model is
|
||||
* ready for use.
|
||||
* @throws FlowModelBuilderException an exception occurred building this flow
|
||||
*/
|
||||
public FlowModel getFlowModel() throws FlowModelBuilderException;
|
||||
|
||||
/**
|
||||
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
|
||||
* call to the {@link #init()} method.
|
||||
* @throws FlowModelBuilderException an exception occurred disposing this flow
|
||||
*/
|
||||
public void dispose() throws FlowModelBuilderException;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2004-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.model.builder;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a problem while building a flow model.
|
||||
*
|
||||
* @see FlowModelBuilder
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowModelBuilderException extends FlowException {
|
||||
|
||||
/**
|
||||
* Create a new flow model builder exception.
|
||||
* @param message descriptive message
|
||||
*/
|
||||
public FlowModelBuilderException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new flow model builder exception.
|
||||
* @param message descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public FlowModelBuilderException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.builder.xml;
|
||||
package org.springframework.webflow.engine.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.builder.xml;
|
||||
package org.springframework.webflow.engine.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.builder.xml;
|
||||
package org.springframework.webflow.engine.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
* 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.model.builder.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
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.webflow.engine.model.AbstractActionModel;
|
||||
import org.springframework.webflow.engine.model.AbstractStateModel;
|
||||
import org.springframework.webflow.engine.model.ActionStateModel;
|
||||
import org.springframework.webflow.engine.model.AttributeModel;
|
||||
import org.springframework.webflow.engine.model.BeanImportModel;
|
||||
import org.springframework.webflow.engine.model.DecisionStateModel;
|
||||
import org.springframework.webflow.engine.model.EndStateModel;
|
||||
import org.springframework.webflow.engine.model.EvaluateModel;
|
||||
import org.springframework.webflow.engine.model.ExceptionHandlerModel;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.IfModel;
|
||||
import org.springframework.webflow.engine.model.InputModel;
|
||||
import org.springframework.webflow.engine.model.OutputModel;
|
||||
import org.springframework.webflow.engine.model.PersistenceContextModel;
|
||||
import org.springframework.webflow.engine.model.RenderModel;
|
||||
import org.springframework.webflow.engine.model.SecuredModel;
|
||||
import org.springframework.webflow.engine.model.SetModel;
|
||||
import org.springframework.webflow.engine.model.SubflowStateModel;
|
||||
import org.springframework.webflow.engine.model.TransitionModel;
|
||||
import org.springframework.webflow.engine.model.VarModel;
|
||||
import org.springframework.webflow.engine.model.ViewStateModel;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilderException;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistry;
|
||||
import org.springframework.webflow.engine.model.registry.NoSuchFlowModelException;
|
||||
import org.springframework.webflow.util.ResourceHolder;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class XmlFlowModelBuilder implements FlowModelBuilder, ResourceHolder {
|
||||
|
||||
/**
|
||||
* The resource from which the document element being parsed was read. Used as a location for relative resource
|
||||
* lookup.
|
||||
*/
|
||||
protected Resource resource;
|
||||
|
||||
/**
|
||||
* The flow model registry used to lookup other flows
|
||||
*/
|
||||
protected FlowModelRegistry registry;
|
||||
|
||||
/**
|
||||
* The loader for loading the flow definition resource XML document.
|
||||
*/
|
||||
private DocumentLoader documentLoader = new DefaultDocumentLoader();
|
||||
|
||||
/**
|
||||
* The in-memory document object model (DOM) of the XML Document read from the flow definition resource.
|
||||
*/
|
||||
private Document document;
|
||||
|
||||
/**
|
||||
* The flow model.
|
||||
*/
|
||||
private FlowModel flowModel;
|
||||
|
||||
/**
|
||||
* Create a new XML flow builder parsing the document at the specified location, using the provided service locator
|
||||
* to access externally managed flow artifacts.
|
||||
*/
|
||||
public XmlFlowModelBuilder(Resource resource, FlowModelRegistry registry) {
|
||||
this.resource = resource;
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
Assert.notNull(documentLoader, "The XML document loader is required");
|
||||
this.documentLoader = documentLoader;
|
||||
}
|
||||
|
||||
public void init() throws FlowModelBuilderException {
|
||||
try {
|
||||
document = documentLoader.loadDocument(resource);
|
||||
} catch (IOException e) {
|
||||
throw new FlowModelBuilderException("Could not access the XML flow definition resource at " + resource, e);
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new FlowModelBuilderException("Could not configure the parser to parse the XML flow definition at "
|
||||
+ resource, e);
|
||||
} catch (SAXException e) {
|
||||
throw new FlowModelBuilderException("Could not parse the XML flow definition document at " + resource, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void build() throws FlowModelBuilderException {
|
||||
if (getDocumentElement() == null) {
|
||||
throw new FlowModelBuilderException("The FlowModelBuilder must be initialized first");
|
||||
}
|
||||
flowModel = parseFlow(getDocumentElement());
|
||||
if (flowModel.getParent() != null) {
|
||||
for (Iterator parentIt = Arrays.asList(StringUtils.trimArrayElements(flowModel.getParent().split(",")))
|
||||
.iterator(); parentIt.hasNext();) {
|
||||
String parentFlowId = (String) parentIt.next();
|
||||
if (StringUtils.hasText(parentFlowId)) {
|
||||
try {
|
||||
flowModel.merge(registry.getFlowModel(parentFlowId));
|
||||
} catch (NoSuchFlowModelException e) {
|
||||
throw new FlowModelBuilderException("Unable to find flow '" + parentFlowId
|
||||
+ "' to inherit from", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FlowModel getFlowModel() throws FlowModelBuilderException {
|
||||
return flowModel;
|
||||
}
|
||||
|
||||
public void dispose() throws FlowModelBuilderException {
|
||||
document = null;
|
||||
flowModel = null;
|
||||
}
|
||||
|
||||
protected FlowModel parseFlow(Element ele) {
|
||||
FlowModel flow = new FlowModel();
|
||||
flow.setParent(ele.getAttribute("parent"));
|
||||
flow.setStartStateId(ele.getAttribute("start-state"));
|
||||
flow.addAttributes(parseAttributes(ele));
|
||||
flow.setSecured(parseSecured(ele));
|
||||
flow.setPersistenceContext(parsePersistenceContext(ele));
|
||||
flow.addVars(parseVars(ele));
|
||||
flow.addInputs(parseInputs(ele));
|
||||
flow.addOutputs(parseOutputs(ele));
|
||||
flow.addOnStartActions(parseOnStartActions(ele));
|
||||
flow.addStates(parseStates(ele));
|
||||
flow.addGlobalTransitions(parseGlobalTransitions(ele));
|
||||
flow.addOnEndActions(parseOnEndActions(ele));
|
||||
flow.addExceptionHandlers(parseExceptionHandlers(ele));
|
||||
flow.addBeanImports(parseBeanImports(ele));
|
||||
return flow;
|
||||
}
|
||||
|
||||
protected LinkedList parseAttributes(Element ele) {
|
||||
LinkedList attributes = new LinkedList();
|
||||
for (Iterator attributeIt = DomUtils.getChildElementsByTagName(ele, "attribute").iterator(); attributeIt
|
||||
.hasNext();) {
|
||||
attributes.add(parseAttribute((Element) attributeIt.next()));
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
protected LinkedList parseVars(Element ele) {
|
||||
LinkedList vars = new LinkedList();
|
||||
for (Iterator varIt = DomUtils.getChildElementsByTagName(ele, "var").iterator(); varIt.hasNext();) {
|
||||
vars.add(parseVar((Element) varIt.next()));
|
||||
}
|
||||
return vars;
|
||||
}
|
||||
|
||||
protected LinkedList parseInputs(Element ele) {
|
||||
LinkedList inputs = new LinkedList();
|
||||
for (Iterator inputIt = DomUtils.getChildElementsByTagName(ele, "input").iterator(); inputIt.hasNext();) {
|
||||
inputs.add(parseInput((Element) inputIt.next()));
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
protected LinkedList parseOutputs(Element ele) {
|
||||
LinkedList outputs = new LinkedList();
|
||||
for (Iterator outputIt = DomUtils.getChildElementsByTagName(ele, "output").iterator(); outputIt.hasNext();) {
|
||||
outputs.add(parseOutput((Element) outputIt.next()));
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
||||
protected LinkedList parseActions(Element ele) {
|
||||
LinkedList actions = new LinkedList();
|
||||
for (Iterator actionIt = getChildElementsByTagNames(ele, new String[] { "evaluate", "render", "set" })
|
||||
.iterator(); actionIt.hasNext();) {
|
||||
actions.add(parseAction((Element) actionIt.next()));
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
protected LinkedList parseStates(Element ele) {
|
||||
LinkedList states = new LinkedList();
|
||||
for (Iterator stateIt = getChildElementsByTagNames(ele,
|
||||
new String[] { "action-state", "view-state", "decision-state", "subflow-state", "end-state" })
|
||||
.iterator(); stateIt.hasNext();) {
|
||||
states.add(parseState((Element) stateIt.next()));
|
||||
}
|
||||
return states;
|
||||
}
|
||||
|
||||
protected LinkedList parseTransitions(Element ele) {
|
||||
LinkedList transitions = new LinkedList();
|
||||
for (Iterator transitionIt = DomUtils.getChildElementsByTagName(ele, "transition").iterator(); transitionIt
|
||||
.hasNext();) {
|
||||
transitions.add(parseTransition((Element) transitionIt.next()));
|
||||
}
|
||||
return transitions;
|
||||
|
||||
}
|
||||
|
||||
protected LinkedList parseExceptionHandlers(Element ele) {
|
||||
LinkedList exceptionHandlers = new LinkedList();
|
||||
for (Iterator exceptionHandlerIt = DomUtils.getChildElementsByTagName(ele, "exception-handler").iterator(); exceptionHandlerIt
|
||||
.hasNext();) {
|
||||
exceptionHandlers.add(parseExceptionHandler((Element) exceptionHandlerIt.next()));
|
||||
}
|
||||
return exceptionHandlers;
|
||||
}
|
||||
|
||||
protected LinkedList parseBeanImports(Element ele) {
|
||||
LinkedList beanImports = new LinkedList();
|
||||
for (Iterator beanImportIt = DomUtils.getChildElementsByTagName(ele, "bean-import").iterator(); beanImportIt
|
||||
.hasNext();) {
|
||||
beanImports.add(parseBeanImport((Element) beanImportIt.next()));
|
||||
}
|
||||
return beanImports;
|
||||
}
|
||||
|
||||
protected LinkedList parseIfs(Element ele) {
|
||||
LinkedList ifs = new LinkedList();
|
||||
for (Iterator ifIt = DomUtils.getChildElementsByTagName(ele, "if").iterator(); ifIt.hasNext();) {
|
||||
ifs.add(parseIf((Element) ifIt.next()));
|
||||
}
|
||||
return ifs;
|
||||
}
|
||||
|
||||
protected AbstractActionModel parseAction(Element ele) {
|
||||
if (DomUtils.nodeNameEquals(ele, "evaluate")) {
|
||||
return parseEvaluate(ele);
|
||||
} else if (DomUtils.nodeNameEquals(ele, "render")) {
|
||||
return parseRender(ele);
|
||||
} else if (DomUtils.nodeNameEquals(ele, "set")) {
|
||||
return parseSet(ele);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unknown action element encountered '" + ele.getLocalName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
protected AbstractStateModel parseState(Element ele) {
|
||||
if (DomUtils.nodeNameEquals(ele, "action-state")) {
|
||||
return parseActionState(ele);
|
||||
} else if (DomUtils.nodeNameEquals(ele, "view-state")) {
|
||||
return parseViewState(ele);
|
||||
} else if (DomUtils.nodeNameEquals(ele, "decision-state")) {
|
||||
return parseDecisionState(ele);
|
||||
} else if (DomUtils.nodeNameEquals(ele, "subflow-state")) {
|
||||
return parseSubflowState(ele);
|
||||
} else if (DomUtils.nodeNameEquals(ele, "end-state")) {
|
||||
return parseEndState(ele);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unknown state element encountered '" + ele.getLocalName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkedList parseGlobalTransitions(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "global-transitions")) {
|
||||
return parseGlobalTransitions(DomUtils.getChildElementByTagName(ele, "global-transitions"));
|
||||
} else {
|
||||
return parseTransitions(ele);
|
||||
}
|
||||
}
|
||||
|
||||
protected AttributeModel parseAttribute(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "attribute")) {
|
||||
return parseAttribute(DomUtils.getChildElementByTagName(ele, "attribute"));
|
||||
} else {
|
||||
return new AttributeModel(ele.getAttribute("name"), parseValue(ele), ele.getAttribute("type"));
|
||||
}
|
||||
}
|
||||
|
||||
protected String parseValue(Element ele) {
|
||||
if (ele.hasAttribute("value")) {
|
||||
return ele.getAttribute("value");
|
||||
} else {
|
||||
Element valueEle = DomUtils.getChildElementByTagName(ele, "value");
|
||||
return valueEle != null ? DomUtils.getTextValue(valueEle) : null;
|
||||
}
|
||||
}
|
||||
|
||||
protected SecuredModel parseSecured(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "secured")) {
|
||||
return parseSecured(DomUtils.getChildElementByTagName(ele, "secured"));
|
||||
} else {
|
||||
return new SecuredModel(ele.getAttribute("attributes"), ele.getAttribute("match"));
|
||||
}
|
||||
}
|
||||
|
||||
protected PersistenceContextModel parsePersistenceContext(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "persistence-context")) {
|
||||
return parsePersistenceContext(DomUtils.getChildElementByTagName(ele, "persistence-context"));
|
||||
} else {
|
||||
return new PersistenceContextModel();
|
||||
}
|
||||
}
|
||||
|
||||
protected VarModel parseVar(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "var")) {
|
||||
return parseVar(DomUtils.getChildElementByTagName(ele, "var"));
|
||||
} else {
|
||||
return new VarModel(ele.getAttribute("name"), ele.getAttribute("class"), ele.getAttribute("scope"));
|
||||
}
|
||||
}
|
||||
|
||||
protected InputModel parseInput(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "input")) {
|
||||
return parseInput(DomUtils.getChildElementByTagName(ele, "input"));
|
||||
} else {
|
||||
return new InputModel(ele.getAttribute("name"), ele.getAttribute("value"), ele.getAttribute("type"), ele
|
||||
.getAttribute("required"));
|
||||
}
|
||||
}
|
||||
|
||||
protected OutputModel parseOutput(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "output")) {
|
||||
return parseOutput(DomUtils.getChildElementByTagName(ele, "output"));
|
||||
} else {
|
||||
return new OutputModel(ele.getAttribute("name"), ele.getAttribute("value"), ele.getAttribute("type"), ele
|
||||
.getAttribute("required"));
|
||||
}
|
||||
}
|
||||
|
||||
protected TransitionModel parseTransition(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "transition")) {
|
||||
return parseTransition(DomUtils.getChildElementByTagName(ele, "transition"));
|
||||
} else {
|
||||
return new TransitionModel(ele.getAttribute("on"), ele.getAttribute("to"),
|
||||
ele.getAttribute("on-exception"), ele.getAttribute("bind"), parseAttributes(ele),
|
||||
parseSecured(ele), parseActions(ele));
|
||||
}
|
||||
}
|
||||
|
||||
protected ExceptionHandlerModel parseExceptionHandler(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "exception-handler")) {
|
||||
return parseExceptionHandler(DomUtils.getChildElementByTagName(ele, "exception-handler"));
|
||||
} else {
|
||||
return new ExceptionHandlerModel(ele.getAttribute("bean-name"));
|
||||
}
|
||||
}
|
||||
|
||||
protected BeanImportModel parseBeanImport(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "bean-import")) {
|
||||
return parseBeanImport(DomUtils.getChildElementByTagName(ele, "bean-import"));
|
||||
} else {
|
||||
return new BeanImportModel(ele.getAttribute("resource"));
|
||||
}
|
||||
}
|
||||
|
||||
protected IfModel parseIf(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "if")) {
|
||||
return parseIf(DomUtils.getChildElementByTagName(ele, "if"));
|
||||
} else {
|
||||
return new IfModel(ele.getAttribute("test"), ele.getAttribute("then"), ele.getAttribute("else"));
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkedList parseOnStartActions(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "on-start")) {
|
||||
return parseOnStartActions(DomUtils.getChildElementByTagName(ele, "on-start"));
|
||||
} else {
|
||||
return parseActions(ele);
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkedList parseOnEntryActions(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "on-entry")) {
|
||||
return parseOnEntryActions(DomUtils.getChildElementByTagName(ele, "on-entry"));
|
||||
} else {
|
||||
return parseActions(ele);
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkedList parseOnExitActions(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "on-exit")) {
|
||||
return parseOnExitActions(DomUtils.getChildElementByTagName(ele, "on-exit"));
|
||||
} else {
|
||||
return parseActions(ele);
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkedList parseOnRenderActions(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "on-render")) {
|
||||
return parseOnRenderActions(DomUtils.getChildElementByTagName(ele, "on-render"));
|
||||
} else {
|
||||
return parseActions(ele);
|
||||
}
|
||||
}
|
||||
|
||||
protected LinkedList parseOnEndActions(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "on-end")) {
|
||||
return parseOnEndActions(DomUtils.getChildElementByTagName(ele, "on-end"));
|
||||
} else {
|
||||
return parseActions(ele);
|
||||
}
|
||||
}
|
||||
|
||||
protected EvaluateModel parseEvaluate(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "evaluate")) {
|
||||
return parseEvaluate(DomUtils.getChildElementByTagName(ele, "evaluate"));
|
||||
} else {
|
||||
return new EvaluateModel(ele.getAttribute("expression"), ele.getAttribute("result"), ele
|
||||
.getAttribute("result-type"));
|
||||
}
|
||||
}
|
||||
|
||||
protected RenderModel parseRender(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "render")) {
|
||||
return parseRender(DomUtils.getChildElementByTagName(ele, "render"));
|
||||
} else {
|
||||
return new RenderModel(ele.getAttribute("fragments"));
|
||||
}
|
||||
}
|
||||
|
||||
protected SetModel parseSet(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "set")) {
|
||||
return parseSet(DomUtils.getChildElementByTagName(ele, "set"));
|
||||
} else {
|
||||
return new SetModel(ele.getAttribute("name"), ele.getAttribute("value"), ele.getAttribute("type"));
|
||||
}
|
||||
}
|
||||
|
||||
protected ActionStateModel parseActionState(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "action-state")) {
|
||||
return parseActionState(DomUtils.getChildElementByTagName(ele, "action-state"));
|
||||
} else {
|
||||
return new ActionStateModel(ele.getAttribute("id"), parseAttributes(ele), parseSecured(ele),
|
||||
parseOnEntryActions(ele), parseTransitions(ele), parseOnExitActions(ele), parseActions(ele),
|
||||
parseExceptionHandlers(ele));
|
||||
}
|
||||
}
|
||||
|
||||
protected ViewStateModel parseViewState(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "view-state")) {
|
||||
return parseViewState(DomUtils.getChildElementByTagName(ele, "view-state"));
|
||||
} else {
|
||||
return new ViewStateModel(ele.getAttribute("id"), ele.getAttribute("view"), ele.getAttribute("redirect"),
|
||||
ele.getAttribute("popup"), ele.getAttribute("model"), parseVars(ele), parseOnRenderActions(ele),
|
||||
parseAttributes(ele), parseSecured(ele), parseOnEntryActions(ele), parseExceptionHandlers(ele),
|
||||
parseTransitions(ele), parseOnExitActions(ele));
|
||||
}
|
||||
}
|
||||
|
||||
protected DecisionStateModel parseDecisionState(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "decision-state")) {
|
||||
return parseDecisionState(DomUtils.getChildElementByTagName(ele, "decision-state"));
|
||||
} else {
|
||||
return new DecisionStateModel(ele.getAttribute("id"), parseIfs(ele), parseOnExitActions(ele),
|
||||
parseAttributes(ele), parseSecured(ele), parseOnEntryActions(ele), parseExceptionHandlers(ele));
|
||||
}
|
||||
}
|
||||
|
||||
protected SubflowStateModel parseSubflowState(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "subflow-state")) {
|
||||
return parseSubflowState(DomUtils.getChildElementByTagName(ele, "subflow-state"));
|
||||
} else {
|
||||
return new SubflowStateModel(ele.getAttribute("id"), ele.getAttribute("subflow"), ele
|
||||
.getAttribute("subflow-attribute-mapper"), parseInputs(ele), parseOutputs(ele),
|
||||
parseAttributes(ele), parseSecured(ele), parseOnEntryActions(ele), parseExceptionHandlers(ele),
|
||||
parseTransitions(ele), parseOnExitActions(ele));
|
||||
}
|
||||
}
|
||||
|
||||
protected EndStateModel parseEndState(Element ele) {
|
||||
if (ele == null) {
|
||||
return null;
|
||||
} else if (!DomUtils.nodeNameEquals(ele, "end-state")) {
|
||||
return parseEndState(DomUtils.getChildElementByTagName(ele, "end-state"));
|
||||
} else {
|
||||
return new EndStateModel(ele.getAttribute("id"), ele.getAttribute("view-factory"), ele
|
||||
.getAttribute("commit"), parseOutputs(ele), parseAttributes(ele), parseSecured(ele),
|
||||
parseOnEntryActions(ele), parseExceptionHandlers(ele));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: submit this to DomUtils
|
||||
private static List getChildElementsByTagNames(Element ele, String[] childEleNames) {
|
||||
List names = Arrays.asList(childEleNames);
|
||||
NodeList nl = ele.getChildNodes();
|
||||
List childEles = new LinkedList();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && (names.contains(node.getLocalName()) || names.contains(node.getNodeName()))) {
|
||||
childEles.add(node);
|
||||
}
|
||||
}
|
||||
return childEles;
|
||||
}
|
||||
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DOM document parsed from the XML file.
|
||||
*/
|
||||
protected Document getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root document element.
|
||||
*/
|
||||
protected Element getDocumentElement() {
|
||||
return document != null ? document.getDocumentElement() : null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("location", resource).toString();
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2004-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.model.registry;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilderException;
|
||||
import org.springframework.webflow.util.ResourceHolder;
|
||||
|
||||
/**
|
||||
* A flow model holder that can detect changes on an underlying flow model resource and refresh that resource
|
||||
* automatically.
|
||||
* <p>
|
||||
* This class is thread-safe.
|
||||
* <p>
|
||||
* Note that this {@link FlowModel} holder uses a {@link FlowModelBuilder}.
|
||||
*
|
||||
* @see FlowModel
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class DefaultFlowModelHolder implements FlowModelHolder {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultFlowModelHolder.class);
|
||||
|
||||
/**
|
||||
* The flow model assembled by this assembler.
|
||||
*/
|
||||
private FlowModel flowModel;
|
||||
|
||||
/**
|
||||
* The flow mode identifier
|
||||
*/
|
||||
private String flowModelId;
|
||||
|
||||
/**
|
||||
* The flow model builder.
|
||||
*/
|
||||
private FlowModelBuilder builder;
|
||||
|
||||
/**
|
||||
* A last modified date for the backing flow definition resource, used to support automatic reassembly on resource
|
||||
* change.
|
||||
*/
|
||||
private long lastModified;
|
||||
|
||||
/**
|
||||
* Creates a new refreshable flow model holder that uses the configured assembler (GOF director) to drive flow
|
||||
* assembly, on initial use and on any resource change or refresh.
|
||||
* @param builder the flow model builder to use
|
||||
* @param flowModelId the identifier of the flow model
|
||||
*/
|
||||
public DefaultFlowModelHolder(FlowModelBuilder builder, String flowModelId) {
|
||||
this.builder = builder;
|
||||
this.flowModelId = flowModelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new static flow model holder
|
||||
* @param flowModel the flow model to hold
|
||||
* @param flowModelId the identifier of the flow model
|
||||
*/
|
||||
public DefaultFlowModelHolder(FlowModel flowModel, String flowModelId) {
|
||||
this.flowModel = flowModel;
|
||||
this.flowModelId = flowModelId;
|
||||
}
|
||||
|
||||
public String getFlowModelId() {
|
||||
return flowModelId;
|
||||
}
|
||||
|
||||
public synchronized FlowModel getFlowModel() throws FlowModelConstructionException {
|
||||
if (flowModel == null) {
|
||||
lastModified = calculateLastModified();
|
||||
logger.debug("Assembling the flow model for the first time");
|
||||
assembleFlow();
|
||||
} else {
|
||||
refreshIfChanged();
|
||||
}
|
||||
return flowModel;
|
||||
}
|
||||
|
||||
public synchronized void refresh() throws FlowModelConstructionException {
|
||||
assembleFlow();
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
/**
|
||||
* Helper that retrieves the last modified date by querying the backing flow resource.
|
||||
* @return the last modified date, or 0L if it could not be retrieved
|
||||
*/
|
||||
private long calculateLastModified() {
|
||||
if (getFlowModelBuilder() instanceof ResourceHolder) {
|
||||
Resource resource = ((ResourceHolder) getFlowModelBuilder()).getResource();
|
||||
try {
|
||||
long lastModified = resource.getFile().lastModified();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Flow definition [" + resource + "] was last modified on " + lastModified);
|
||||
}
|
||||
return lastModified;
|
||||
} catch (IOException e) {
|
||||
// ignore, last modified checks not supported
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble the held flow definition, delegating to the configured FlowAssembler (director).
|
||||
*/
|
||||
private void assembleFlow() throws FlowModelConstructionException {
|
||||
try {
|
||||
builder.init();
|
||||
builder.build();
|
||||
flowModel = builder.getFlowModel();
|
||||
} catch (FlowModelBuilderException e) {
|
||||
throw new FlowModelConstructionException(flowModelId, e);
|
||||
} finally {
|
||||
builder.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reassemble the flow if its underlying resource has changed.
|
||||
*/
|
||||
private void refreshIfChanged() {
|
||||
long calculatedLastModified = calculateLastModified();
|
||||
if (calculatedLastModified > lastModified) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing flow definition [" + flowModelId + "]");
|
||||
}
|
||||
assembleFlow();
|
||||
lastModified = calculatedLastModified;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flow builder that actually builds the Flow definition.
|
||||
*/
|
||||
private FlowModelBuilder getFlowModelBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "'" + getFlowModelId() + "'";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.model.registry;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Thrown when a flow model was found during a lookup operation but could not be constructed.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowModelConstructionException extends FlowException {
|
||||
|
||||
/**
|
||||
* The id of the flow that could not be constructed.
|
||||
*/
|
||||
private String flowModelId;
|
||||
|
||||
/**
|
||||
* Creates an exception indicating a flow model could not be constructed.
|
||||
* @param flowModelId the flow model identifier
|
||||
* @param cause the underlying cause of the exception
|
||||
*/
|
||||
public FlowModelConstructionException(String flowModelId, Throwable cause) {
|
||||
super("An exception occurred constructing the flow '" + flowModelId + "'", cause);
|
||||
this.flowModelId = flowModelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the flow model that could not be constructed.
|
||||
* @return the flow id
|
||||
*/
|
||||
public String getFlowModelId() {
|
||||
return flowModelId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.model.registry;
|
||||
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A holder holding a reference to a Flow model. Provides a layer of indirection, enabling things like "hot-reloadable"
|
||||
* flow models.
|
||||
*
|
||||
* @see FlowModelRegistry#registerFlowModel(FlowModelHolder)
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelHolder {
|
||||
|
||||
/**
|
||||
* Returns the <code>id</code> of the flow model held by this holder. This is a <i>lightweight</i> method callers
|
||||
* may call to obtain the id of the flow without triggering full flow definition assembly (which may be an expensive
|
||||
* operation).
|
||||
*/
|
||||
public String getFlowModelId();
|
||||
|
||||
/**
|
||||
* Returns the flow model held by this holder. Calling this method the first time may trigger flow assembly (which
|
||||
* may be expensive).
|
||||
* @throws FlowModelConstructionException if there is a problem constructing the target flow model
|
||||
*/
|
||||
public FlowModel getFlowModel() throws FlowModelConstructionException;
|
||||
|
||||
/**
|
||||
* Refresh the flow model held by this holder. Calling this method typically triggers flow re-assembly, which may
|
||||
* include a refresh from an externalized resource such as a file.
|
||||
* @throws FlowModelConstructionException if there is a problem constructing the target flow model
|
||||
*/
|
||||
public void refresh() throws FlowModelConstructionException;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.model.registry;
|
||||
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A runtime service locator interface for retrieving flow definitions by <code>id</code>. Flow locators are needed
|
||||
* by flow executors at runtime to retrieve flow models to support loading flow definitions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelLocator {
|
||||
|
||||
/**
|
||||
* Lookup the flow model with the specified id.
|
||||
* @param id the flow model identifier
|
||||
* @return the flow mode
|
||||
* @throws NoSuchFlowModelException when the flow model with the specified id does not exist
|
||||
* @throws FlowModelConstructionException if there is a problem constructing the identified flow model
|
||||
*/
|
||||
public FlowModel getFlowModel(String id) throws NoSuchFlowModelException, FlowModelConstructionException;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.model.registry;
|
||||
|
||||
/**
|
||||
* A container of flow models. Extends {@link FlowModelLocator} for accessing registered Flow models for conversion to
|
||||
* flow definitions.
|
||||
* <p>
|
||||
* Flow model registries can be configured with a "parent" registry to provide a hook into a larger flow model registry
|
||||
* hierarchy.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowModelRegistry extends FlowModelLocator {
|
||||
|
||||
/**
|
||||
* Sets this registry's parent registry. When asked by a client to locate a flow model this registry will query it's
|
||||
* parent if it cannot fulfill the lookup request itself.
|
||||
* @param parent the parent flow model registry, may be null
|
||||
*/
|
||||
public void setParent(FlowModelRegistry parent);
|
||||
|
||||
/**
|
||||
* Register a flow model in this registry. Registers a "holder", not the Flow model itself. This allows the actual
|
||||
* Flow model to be loaded lazily only when needed, and also rebuilt at runtime when its underlying resource changes
|
||||
* without re-deploy.
|
||||
* @param modelHolder a holder holding the flow model to register
|
||||
*/
|
||||
public void registerFlowModel(FlowModelHolder modelHolder);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.model.registry;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
/**
|
||||
* A generic registry implementation for housing one or more flow models.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class FlowModelRegistryImpl implements FlowModelRegistry {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FlowModelRegistryImpl.class);
|
||||
|
||||
/**
|
||||
* The map of loaded Flow models maintained in this registry.
|
||||
*/
|
||||
private Map flowModels;
|
||||
|
||||
/**
|
||||
* An optional parent flow model registry.
|
||||
*/
|
||||
private FlowModelRegistry parent;
|
||||
|
||||
public FlowModelRegistryImpl() {
|
||||
flowModels = new TreeMap();
|
||||
}
|
||||
|
||||
// implementing FlowModelLocator
|
||||
|
||||
public FlowModel getFlowModel(String id) throws NoSuchFlowModelException, FlowModelConstructionException {
|
||||
try {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("The id of the flow to lookup is required");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Getting flow model with id '" + id + "'");
|
||||
}
|
||||
return getFlowModelHolder(id).getFlowModel();
|
||||
|
||||
} catch (NoSuchFlowModelException e) {
|
||||
if (parent != null) {
|
||||
// try parent
|
||||
return parent.getFlowModel(id);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// implementing FlowModelRegistry
|
||||
|
||||
public void setParent(FlowModelRegistry parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void registerFlowModel(FlowModelHolder modelHolder) {
|
||||
Assert.notNull(modelHolder, "The holder of the flow model to register is required");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registering flow model " + modelHolder);
|
||||
}
|
||||
flowModels.put(modelHolder.getFlowModelId(), modelHolder);
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
/**
|
||||
* Returns the identified flow model holder. Throws an exception if it cannot be found.
|
||||
*/
|
||||
private FlowModelHolder getFlowModelHolder(String id) throws NoSuchFlowModelException {
|
||||
FlowModelHolder holder = (FlowModelHolder) flowModels.get(id);
|
||||
if (holder == null) {
|
||||
throw new NoSuchFlowModelException(id);
|
||||
}
|
||||
return holder;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("flowModels", flowModels).append("parent", parent).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.model.registry;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
|
||||
/**
|
||||
* Thrown when no flow model was found during a lookup operation by a flow locator.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class NoSuchFlowModelException extends FlowException {
|
||||
|
||||
/**
|
||||
* The id of the flow model that could not be located.
|
||||
*/
|
||||
private String flowModelId;
|
||||
|
||||
/**
|
||||
* Creates an exception indicating a flow model could not be found.
|
||||
* @param flowModelId the flow model id
|
||||
*/
|
||||
public NoSuchFlowModelException(String flowModelId) {
|
||||
super("No flow model '" + flowModelId + "' found");
|
||||
this.flowModelId = flowModelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the id of the flow model that could not be found.
|
||||
*/
|
||||
public String getFlowModelId() {
|
||||
return flowModelId;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.webflow.test.execution;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.config.FlowDefinitionResource;
|
||||
import org.springframework.webflow.config.FlowDefinitionResourceFactory;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
@@ -33,6 +32,7 @@ import org.springframework.webflow.test.MockFlowBuilderContext;
|
||||
* caching of the flow definition built from an externalized resource to speed up test execution.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractExternalizedFlowExecutionTests extends AbstractFlowExecutionTests {
|
||||
|
||||
@@ -145,7 +145,7 @@ public abstract class AbstractExternalizedFlowExecutionTests extends AbstractFlo
|
||||
FlowDefinitionResource resource = getResource(resourceFactory);
|
||||
MockFlowBuilderContext builderContext = new MockFlowBuilderContext(resource.getId(), resource.getAttributes());
|
||||
configureFlowBuilderContext(builderContext);
|
||||
FlowBuilder builder = createFlowBuilder(resource.getPath());
|
||||
FlowBuilder builder = createFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, builderContext);
|
||||
return assembler.assembleFlow();
|
||||
}
|
||||
@@ -168,9 +168,9 @@ public abstract class AbstractExternalizedFlowExecutionTests extends AbstractFlo
|
||||
|
||||
/**
|
||||
* Create the flow builder to build the flow at the specified resource location.
|
||||
* @param path the location of the flow definition
|
||||
* @param resource the resource location of the flow definition
|
||||
* @return the flow builder that can build the flow definition
|
||||
*/
|
||||
protected abstract FlowBuilder createFlowBuilder(Resource path);
|
||||
protected abstract FlowBuilder createFlowBuilder(FlowDefinitionResource resource);
|
||||
|
||||
}
|
||||
@@ -16,9 +16,15 @@
|
||||
package org.springframework.webflow.test.execution;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.config.FlowDefinitionResource;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.FlowModelFlowBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistry;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
|
||||
|
||||
/**
|
||||
* Base class for flow integration tests that verify an XML flow definition executes as expected.
|
||||
@@ -47,15 +53,19 @@ import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder;
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalizedFlowExecutionTests {
|
||||
|
||||
private FlowModelRegistry flowModelRegistry;
|
||||
|
||||
/**
|
||||
* Constructs a default XML flow execution test.
|
||||
* @see #setName(String)
|
||||
*/
|
||||
public AbstractXmlFlowExecutionTests() {
|
||||
super();
|
||||
flowModelRegistry = new FlowModelRegistryImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,10 +74,14 @@ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalized
|
||||
*/
|
||||
public AbstractXmlFlowExecutionTests(String name) {
|
||||
super(name);
|
||||
flowModelRegistry = new FlowModelRegistryImpl();
|
||||
}
|
||||
|
||||
protected FlowBuilder createFlowBuilder(Resource resource) {
|
||||
return new XmlFlowBuilder(resource) {
|
||||
protected FlowBuilder createFlowBuilder(FlowDefinitionResource resource) {
|
||||
FlowModelBuilder modelBuilder = new XmlFlowModelBuilder(resource.getPath(), flowModelRegistry);
|
||||
FlowModelHolder modelHolder = new DefaultFlowModelHolder(modelBuilder, resource.getId());
|
||||
flowModelRegistry.registerFlowModel(modelHolder);
|
||||
return new FlowModelFlowBuilder(modelHolder, resource.getPath()) {
|
||||
protected void registerFlowBeans(ConfigurableBeanFactory flowBeanFactory) {
|
||||
registerMockFlowBeans(flowBeanFactory);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
package org.springframework.webflow.engine.builder;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.webflow.action.ExternalRedirectAction;
|
||||
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.FlowInputMappingException;
|
||||
import org.springframework.webflow.engine.FlowOutputMappingException;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.springframework.webflow.engine.builder.support.ActionExecutingViewFactory;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.engine.model.AttributeModel;
|
||||
import org.springframework.webflow.engine.model.EndStateModel;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.InputModel;
|
||||
import org.springframework.webflow.engine.model.OutputModel;
|
||||
import org.springframework.webflow.engine.model.PersistenceContextModel;
|
||||
import org.springframework.webflow.engine.model.SecuredModel;
|
||||
import org.springframework.webflow.engine.model.TransitionModel;
|
||||
import org.springframework.webflow.engine.model.VarModel;
|
||||
import org.springframework.webflow.engine.model.ViewStateModel;
|
||||
import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilderTests;
|
||||
import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.security.SecurityRule;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
import org.springframework.webflow.test.MockFlowBuilderContext;
|
||||
|
||||
public class FlowModelFlowBuilderTests extends TestCase {
|
||||
private FlowModel model;
|
||||
|
||||
protected void setUp() {
|
||||
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
|
||||
beanFactory.addBean("bean", new Object());
|
||||
model = new FlowModel();
|
||||
}
|
||||
|
||||
public void testBuildIncompleteFlow() {
|
||||
try {
|
||||
getFlow(model);
|
||||
fail("Should have failed");
|
||||
} catch (FlowBuilderException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildFlowWithEndState() {
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testBuildFlowWithDefaultStartState() {
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testBuildFlowWithStartStateAttribute() {
|
||||
model.setStartStateId("end");
|
||||
model.addEndState(new EndStateModel("foo"));
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testCustomFlowAttribute() {
|
||||
model.addAttribute(new AttributeModel("foo", "bar"));
|
||||
model.addAttribute(new AttributeModel("number", "1", "integer"));
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
assertEquals("bar", flow.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(1), flow.getAttributes().get("number"));
|
||||
}
|
||||
|
||||
public void testPersistenceContextFlow() {
|
||||
model.setPersistenceContext(new PersistenceContextModel());
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
assertNotNull(flow.getAttributes().get("persistenceContext"));
|
||||
assertTrue(((Boolean) flow.getAttributes().get("persistenceContext")).booleanValue());
|
||||
}
|
||||
|
||||
public void testFlowInputOutputMapping() {
|
||||
model.addInput(new InputModel("foo", "flowScope.foo"));
|
||||
model.addInput(new InputModel("foo", "flowScope.bar"));
|
||||
model.addInput(new InputModel("number", "flowScope.baz", "integer", null));
|
||||
model.addInput(new InputModel("required", "flowScope.boop", null, "true"));
|
||||
EndStateModel end = new EndStateModel("end");
|
||||
end.addOutput(new OutputModel("foo", "flowScope.foo"));
|
||||
model.addEndState(end);
|
||||
EndStateModel notReached = new EndStateModel("notReached");
|
||||
notReached.addOutput(new OutputModel("notReached", "flowScope.foo"));
|
||||
model.addEndState(notReached);
|
||||
model.addOutput(new OutputModel("differentName", "flowScope.bar"));
|
||||
model.addOutput(new OutputModel("number", "flowScope.baz", "integer", null));
|
||||
model.addOutput(new OutputModel("required", "flowScope.baz", "integer", "true"));
|
||||
model.addOutput(new OutputModel("literal", "'a literal'"));
|
||||
Flow flow = getFlow(model);
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
MutableAttributeMap input = new LocalAttributeMap();
|
||||
input.put("foo", "bar");
|
||||
input.put("number", "3");
|
||||
input.put("required", "9");
|
||||
execution.start(input, context);
|
||||
Event outcome = execution.getOutcome();
|
||||
assertEquals("end", outcome.getId());
|
||||
assertEquals("bar", outcome.getAttributes().get("foo"));
|
||||
assertEquals("bar", outcome.getAttributes().get("differentName"));
|
||||
assertEquals(new Integer(3), outcome.getAttributes().get("number"));
|
||||
assertEquals(new Integer(3), outcome.getAttributes().get("required"));
|
||||
assertEquals("a literal", outcome.getAttributes().get("literal"));
|
||||
assertNull(outcome.getAttributes().get("notReached"));
|
||||
}
|
||||
|
||||
public void testFlowRequiredInputMapping() {
|
||||
model.addInput(new InputModel("foo", "flowScope.foo"));
|
||||
model.addInput(new InputModel("foo", "flowScope.bar"));
|
||||
model.addInput(new InputModel("number", "flowScope.baz", "integer", null));
|
||||
model.addInput(new InputModel("required", "flowScope.boop", null, "true"));
|
||||
EndStateModel end = new EndStateModel("end");
|
||||
end.addOutput(new OutputModel("foo", "flowScope.foo"));
|
||||
model.addEndState(end);
|
||||
EndStateModel notReached = new EndStateModel("notReached");
|
||||
notReached.addOutput(new OutputModel("notReached", "flowScope.foo"));
|
||||
model.addEndState(notReached);
|
||||
model.addOutput(new OutputModel("differentName", "flowScope.bar"));
|
||||
model.addOutput(new OutputModel("number", "flowScope.baz", "integer", null));
|
||||
model.addOutput(new OutputModel("required", "flowScope.baz", "integer", "true"));
|
||||
model.addOutput(new OutputModel("literal", "'a literal'"));
|
||||
Flow flow = getFlow(model);
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
MutableAttributeMap input = new LocalAttributeMap();
|
||||
try {
|
||||
execution.start(input, context);
|
||||
fail("Should have failed");
|
||||
} catch (FlowInputMappingException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testFlowRequiredOutputMapping() {
|
||||
model.addInput(new InputModel("foo", "flowScope.foo"));
|
||||
model.addInput(new InputModel("foo", "flowScope.bar"));
|
||||
model.addInput(new InputModel("number", "flowScope.baz", "integer", null));
|
||||
model.addInput(new InputModel("required", "flowScope.boop", null, "true"));
|
||||
EndStateModel end = new EndStateModel("end");
|
||||
end.addOutput(new OutputModel("foo", "flowScope.foo"));
|
||||
model.addEndState(end);
|
||||
EndStateModel notReached = new EndStateModel("notReached");
|
||||
notReached.addOutput(new OutputModel("notReached", "flowScope.foo"));
|
||||
model.addEndState(notReached);
|
||||
model.addOutput(new OutputModel("differentName", "flowScope.bar"));
|
||||
model.addOutput(new OutputModel("number", "flowScope.baz", "integer", null));
|
||||
model.addOutput(new OutputModel("required", "flowScope.baz", "integer", "true"));
|
||||
model.addOutput(new OutputModel("literal", "'a literal'"));
|
||||
Flow flow = getFlow(model);
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
MutableAttributeMap input = new LocalAttributeMap();
|
||||
input.put("required", "yo");
|
||||
try {
|
||||
execution.start(input, context);
|
||||
fail("Should have failed");
|
||||
} catch (FlowOutputMappingException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testFlowSecured() {
|
||||
model.setSecured(new SecuredModel("ROLE_USER"));
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
SecurityRule rule = (SecurityRule) flow.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
assertNotNull(rule);
|
||||
assertEquals(SecurityRule.COMPARISON_ANY, rule.getComparisonType());
|
||||
assertEquals(1, rule.getAttributes().size());
|
||||
assertTrue(rule.getAttributes().contains("ROLE_USER"));
|
||||
}
|
||||
|
||||
public void testFlowSecuredState() {
|
||||
EndStateModel end = new EndStateModel("end");
|
||||
end.setSecured(new SecuredModel("ROLE_USER"));
|
||||
model.addEndState(end);
|
||||
Flow flow = getFlow(model);
|
||||
SecurityRule rule = (SecurityRule) flow.getState("end").getAttributes().get(
|
||||
SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
assertNotNull(rule);
|
||||
assertEquals(SecurityRule.COMPARISON_ANY, rule.getComparisonType());
|
||||
assertEquals(1, rule.getAttributes().size());
|
||||
assertTrue(rule.getAttributes().contains("ROLE_USER"));
|
||||
}
|
||||
|
||||
public void testFlowSecuredTransition() {
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
TransitionModel transition = new TransitionModel(null, "end");
|
||||
transition.setSecured(new SecuredModel("ROLE_USER"));
|
||||
model.addGlobalTransition(transition);
|
||||
Flow flow = getFlow(model);
|
||||
SecurityRule rule = (SecurityRule) flow.getGlobalTransitionSet().toArray()[0].getAttributes().get(
|
||||
SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
assertNotNull(rule);
|
||||
assertEquals(SecurityRule.COMPARISON_ANY, rule.getComparisonType());
|
||||
assertEquals(1, rule.getAttributes().size());
|
||||
assertTrue(rule.getAttributes().contains("ROLE_USER"));
|
||||
}
|
||||
|
||||
public void testFlowVariable() {
|
||||
model.addVar(new VarModel("flow-foo", "org.springframework.webflow.TestBean"));
|
||||
model.addVar(new VarModel("conversation-foo", "org.springframework.webflow.TestBean", "conversation"));
|
||||
model.addEndState(new EndStateModel("end"));
|
||||
Flow flow = getFlow(model);
|
||||
assertEquals("flow-foo", flow.getVariable("flow-foo").getName());
|
||||
assertEquals(true, flow.getVariable("flow-foo").isLocal());
|
||||
assertEquals("conversation-foo", flow.getVariables()[1].getName());
|
||||
assertEquals(false, flow.getVariables()[1].isLocal());
|
||||
}
|
||||
|
||||
public void testViewStateVariable() {
|
||||
ViewStateModel view = new ViewStateModel("view");
|
||||
view.addVar(new VarModel("foo", "org.springframework.webflow.TestBean"));
|
||||
model.addViewState(view);
|
||||
Flow flow = getFlow(model);
|
||||
assertNotNull(((ViewState) flow.getStateInstance("view")).getVariable("foo"));
|
||||
}
|
||||
|
||||
public void testViewStateRedirect() {
|
||||
ViewStateModel view = new ViewStateModel("view");
|
||||
view.setRedirect("true");
|
||||
model.addViewState(view);
|
||||
Flow flow = getFlow(model);
|
||||
assertTrue(((ViewState) flow.getStateInstance("view")).getRedirect());
|
||||
}
|
||||
|
||||
public void testViewStatePopup() {
|
||||
ViewStateModel view = new ViewStateModel("view");
|
||||
view.setPopup("true");
|
||||
model.addViewState(view);
|
||||
Flow flow = getFlow(model);
|
||||
assertTrue(((ViewState) flow.getStateInstance("view")).getPopup());
|
||||
}
|
||||
|
||||
public void testViewStateFlowRedirect() {
|
||||
model.addViewState(new ViewStateModel("view", "flowRedirect:myFlow?input=#{flowScope.foo}"));
|
||||
Flow flow = getFlow(model);
|
||||
ViewFactory vf = ((ViewState) flow.getStateInstance("view")).getViewFactory();
|
||||
assertTrue(vf instanceof ActionExecutingViewFactory);
|
||||
ActionExecutingViewFactory avf = (ActionExecutingViewFactory) vf;
|
||||
assertTrue(avf.getAction() instanceof FlowDefinitionRedirectAction);
|
||||
}
|
||||
|
||||
public void testViewStateExternalRedirect() {
|
||||
model.addViewState(new ViewStateModel("view",
|
||||
"externalRedirect:http://www.paypal.com?_callbackUrl=#{flowExecutionUri}"));
|
||||
Flow flow = getFlow(model);
|
||||
ViewFactory vf = ((ViewState) flow.getStateInstance("view")).getViewFactory();
|
||||
assertTrue(vf instanceof ActionExecutingViewFactory);
|
||||
ActionExecutingViewFactory avf = (ActionExecutingViewFactory) vf;
|
||||
assertTrue(avf.getAction() instanceof ExternalRedirectAction);
|
||||
}
|
||||
|
||||
public void testResourceBackedFlowBuilder() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-endstate.xml", XmlFlowModelBuilderTests.class);
|
||||
Flow flow = getFlow(resource);
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
private Flow getFlow(FlowModel model) {
|
||||
FlowModelHolder holder = new DefaultFlowModelHolder(model, "flow");
|
||||
FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
return assembler.assembleFlow();
|
||||
}
|
||||
|
||||
private Flow getFlow(ClassPathResource resource) {
|
||||
FlowModelHolder holder = new DefaultFlowModelHolder(new XmlFlowModelBuilder(resource,
|
||||
new FlowModelRegistryImpl()), "flow");
|
||||
FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder, resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
return assembler.assembleFlow();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
package org.springframework.webflow.engine.builder.xml;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.webflow.action.ExternalRedirectAction;
|
||||
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.FlowInputMappingException;
|
||||
import org.springframework.webflow.engine.FlowOutputMappingException;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.springframework.webflow.engine.builder.FlowAssembler;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderException;
|
||||
import org.springframework.webflow.engine.builder.support.ActionExecutingViewFactory;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.security.SecurityRule;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
import org.springframework.webflow.test.MockFlowBuilderContext;
|
||||
|
||||
public class XmlFlowBuilderTests extends TestCase {
|
||||
private XmlFlowBuilder builder;
|
||||
|
||||
protected void setUp() {
|
||||
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
|
||||
beanFactory.addBean("bean", new Object());
|
||||
}
|
||||
|
||||
public void testBuildIncompleteFlow() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-incomplete.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
try {
|
||||
assembler.assembleFlow();
|
||||
fail("Should have failed");
|
||||
} catch (FlowBuilderException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testBuildFlowWithEndState() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-endstate.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testBuildFlowWithDefaultStartState() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-startstate-default.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testBuildFlowWithStartStateAttribute() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-startstate-attribute.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("end", flow.getStartState().getId());
|
||||
}
|
||||
|
||||
public void testCustomFlowAttribute() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-custom-attribute.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("bar", flow.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(1), flow.getAttributes().get("number"));
|
||||
}
|
||||
|
||||
public void testPersistenceContextFlow() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-persistencecontext.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertNotNull(flow.getAttributes().get("persistenceContext"));
|
||||
assertTrue(((Boolean) flow.getAttributes().get("persistenceContext")).booleanValue());
|
||||
}
|
||||
|
||||
public void testFlowInputOutputMapping() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-inputoutput.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
MutableAttributeMap input = new LocalAttributeMap();
|
||||
input.put("foo", "bar");
|
||||
input.put("number", "3");
|
||||
input.put("required", "9");
|
||||
execution.start(input, context);
|
||||
Event outcome = execution.getOutcome();
|
||||
assertEquals("end", outcome.getId());
|
||||
assertEquals("bar", outcome.getAttributes().get("foo"));
|
||||
assertEquals("bar", outcome.getAttributes().get("differentName"));
|
||||
assertEquals(new Integer(3), outcome.getAttributes().get("number"));
|
||||
assertEquals(new Integer(3), outcome.getAttributes().get("required"));
|
||||
assertEquals("a literal", outcome.getAttributes().get("literal"));
|
||||
assertNull(outcome.getAttributes().get("notReached"));
|
||||
}
|
||||
|
||||
public void testFlowRequiredInputMapping() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-inputoutput.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
MutableAttributeMap input = new LocalAttributeMap();
|
||||
try {
|
||||
execution.start(input, context);
|
||||
fail("Should have failed");
|
||||
} catch (FlowInputMappingException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testFlowRequiredOutputMapping() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-inputoutput.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
MutableAttributeMap input = new LocalAttributeMap();
|
||||
input.put("required", "yo");
|
||||
try {
|
||||
execution.start(input, context);
|
||||
fail("Should have failed");
|
||||
} catch (FlowOutputMappingException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testFlowSecured() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-secured.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
SecurityRule rule = (SecurityRule) flow.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
assertNotNull(rule);
|
||||
assertEquals(SecurityRule.COMPARISON_ANY, rule.getComparisonType());
|
||||
assertEquals(1, rule.getAttributes().size());
|
||||
assertTrue(rule.getAttributes().contains("ROLE_USER"));
|
||||
}
|
||||
|
||||
public void testFlowSecuredState() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-secured-state.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
SecurityRule rule = (SecurityRule) flow.getState("end").getAttributes().get(
|
||||
SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
assertNotNull(rule);
|
||||
assertEquals(SecurityRule.COMPARISON_ANY, rule.getComparisonType());
|
||||
assertEquals(1, rule.getAttributes().size());
|
||||
assertTrue(rule.getAttributes().contains("ROLE_USER"));
|
||||
}
|
||||
|
||||
public void testFlowSecuredTransition() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-secured-transition.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
SecurityRule rule = (SecurityRule) flow.getGlobalTransitionSet().toArray()[0].getAttributes().get(
|
||||
SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
assertNotNull(rule);
|
||||
assertEquals(SecurityRule.COMPARISON_ANY, rule.getComparisonType());
|
||||
assertEquals(1, rule.getAttributes().size());
|
||||
assertTrue(rule.getAttributes().contains("ROLE_USER"));
|
||||
}
|
||||
|
||||
public void testFlowVariable() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-var.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("flow-foo", flow.getVariable("flow-foo").getName());
|
||||
assertEquals(true, flow.getVariable("flow-foo").isLocal());
|
||||
assertEquals("conversation-foo", flow.getVariables()[1].getName());
|
||||
assertEquals(false, flow.getVariables()[1].isLocal());
|
||||
}
|
||||
|
||||
public void testViewStateVariable() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-var.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertNotNull(((ViewState) flow.getStateInstance("view")).getVariable("foo"));
|
||||
}
|
||||
|
||||
public void testViewStateRedirect() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-redirect.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertTrue(((ViewState) flow.getStateInstance("view")).getRedirect());
|
||||
}
|
||||
|
||||
public void testViewStatePopup() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-popup.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertTrue(((ViewState) flow.getStateInstance("view")).getPopup());
|
||||
}
|
||||
|
||||
public void testViewStateFlowRedirect() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-flowredirect.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
ViewFactory vf = ((ViewState) flow.getStateInstance("view")).getViewFactory();
|
||||
assertTrue(vf instanceof ActionExecutingViewFactory);
|
||||
ActionExecutingViewFactory avf = (ActionExecutingViewFactory) vf;
|
||||
assertTrue(avf.getAction() instanceof FlowDefinitionRedirectAction);
|
||||
}
|
||||
|
||||
public void testViewStateExternalRedirect() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-externalredirect.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
ViewFactory vf = ((ViewState) flow.getStateInstance("view")).getViewFactory();
|
||||
assertTrue(vf instanceof ActionExecutingViewFactory);
|
||||
ActionExecutingViewFactory avf = (ActionExecutingViewFactory) vf;
|
||||
assertTrue(avf.getAction() instanceof ExternalRedirectAction);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractModel}.
|
||||
*/
|
||||
public class AbstractModelTests extends TestCase {
|
||||
|
||||
public void testStringMerge() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
String child = "child";
|
||||
String parent = "parent";
|
||||
assertEquals("child", obj.merge(child, parent));
|
||||
}
|
||||
|
||||
public void testStringMergeNullParent() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
String child = "child";
|
||||
String parent = null;
|
||||
assertEquals("child", obj.merge(child, parent));
|
||||
}
|
||||
|
||||
public void testStringMergeNullChild() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
String child = null;
|
||||
String parent = "parent";
|
||||
assertEquals("parent", obj.merge(child, parent));
|
||||
}
|
||||
|
||||
public void testStringMergeNulls() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
String child = null;
|
||||
String parent = null;
|
||||
assertEquals(null, obj.merge(child, parent));
|
||||
}
|
||||
|
||||
public void testListMerge() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
LinkedList child = new LinkedList();
|
||||
child.add(new SecuredModel("1"));
|
||||
LinkedList parent = new LinkedList();
|
||||
parent.add(new SecuredModel("2"));
|
||||
LinkedList result = obj.merge(child, parent);
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("1", ((SecuredModel) result.get(0)).getAttributes());
|
||||
assertEquals("2", ((SecuredModel) result.get(1)).getAttributes());
|
||||
}
|
||||
|
||||
public void testListMergeNullParent() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
LinkedList child = new LinkedList();
|
||||
child.add("1");
|
||||
LinkedList parent = null;
|
||||
LinkedList result = obj.merge(child, parent);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("1", result.get(0));
|
||||
}
|
||||
|
||||
public void testListMergeNullChild() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
LinkedList child = null;
|
||||
LinkedList parent = new LinkedList();
|
||||
parent.add("2");
|
||||
LinkedList result = obj.merge(child, parent);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("2", result.get(0));
|
||||
}
|
||||
|
||||
public void testListMergeNulls() {
|
||||
AbstractModel obj = new PersistenceContextModel();
|
||||
LinkedList child = null;
|
||||
LinkedList parent = null;
|
||||
LinkedList result = obj.merge(child, parent);
|
||||
assertEquals(null, result);
|
||||
}
|
||||
}
|
||||
@@ -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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.ActionStateModel;
|
||||
import org.springframework.webflow.engine.model.EvaluateModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ActionStateModel}.
|
||||
*/
|
||||
public class ActionStateModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
ActionStateModel child = new ActionStateModel("child");
|
||||
ActionStateModel parent = new ActionStateModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
ActionStateModel child = new ActionStateModel("child");
|
||||
ActionStateModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
ActionStateModel child = new ActionStateModel("child");
|
||||
ActionStateModel parent = new ActionStateModel("child");
|
||||
parent.addAction(new EvaluateModel("eval1"));
|
||||
child.merge(parent);
|
||||
assertEquals(1, child.getActions().size());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
ActionStateModel child = new ActionStateModel("child");
|
||||
ActionStateModel parent = new ActionStateModel("parent");
|
||||
parent.addAction(new EvaluateModel("eval1"));
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getActions());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.AttributeModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AttributeModel}.
|
||||
*/
|
||||
public class AttributeModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
AttributeModel child = new AttributeModel("child", "childvalue");
|
||||
AttributeModel parent = new AttributeModel("parent", "parentvalue");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getName());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
AttributeModel child = new AttributeModel("child", "childvalue");
|
||||
AttributeModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getName());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
AttributeModel child = new AttributeModel("child", "childvalue");
|
||||
AttributeModel parent = new AttributeModel("child", "childvalue", "string");
|
||||
child.merge(parent);
|
||||
assertEquals("string", child.getType());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
AttributeModel child = new AttributeModel("child", "childvalue");
|
||||
AttributeModel parent = new AttributeModel("parent", "parentvalue", "string");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.BeanImportModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BeanImportModel}.
|
||||
*/
|
||||
public class BeanImportModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
BeanImportModel child = new BeanImportModel("child");
|
||||
BeanImportModel parent = new BeanImportModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getResource());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
BeanImportModel child = new BeanImportModel("child");
|
||||
BeanImportModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getResource());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
// bean import will never merge
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
// bean import will never merge
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.DecisionStateModel;
|
||||
import org.springframework.webflow.engine.model.IfModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DecisionStateModel}.
|
||||
*/
|
||||
public class DecisionStateModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
DecisionStateModel child = new DecisionStateModel("child");
|
||||
DecisionStateModel parent = new DecisionStateModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
DecisionStateModel child = new DecisionStateModel("child");
|
||||
DecisionStateModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
DecisionStateModel child = new DecisionStateModel("child");
|
||||
DecisionStateModel parent = new DecisionStateModel("child");
|
||||
parent.addIf(new IfModel("test", "then"));
|
||||
child.merge(parent);
|
||||
assertEquals(1, child.getIfs().size());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
DecisionStateModel child = new DecisionStateModel("child");
|
||||
DecisionStateModel parent = new DecisionStateModel("parent");
|
||||
parent.addIf(new IfModel("test", "then"));
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getIfs());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.EndStateModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EndStateModel}.
|
||||
*/
|
||||
public class EndStateModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
EndStateModel child = new EndStateModel("child");
|
||||
EndStateModel parent = new EndStateModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
EndStateModel child = new EndStateModel("child");
|
||||
EndStateModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
EndStateModel child = new EndStateModel("child");
|
||||
EndStateModel parent = new EndStateModel("child");
|
||||
parent.setCommit("true");
|
||||
child.merge(parent);
|
||||
assertEquals("true", child.getCommit());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
EndStateModel child = new EndStateModel("child");
|
||||
EndStateModel parent = new EndStateModel("parent");
|
||||
parent.setCommit("true");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getCommit());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.EvaluateModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EvaluateModel}.
|
||||
*/
|
||||
public class EvaluateModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
EvaluateModel child = new EvaluateModel("child");
|
||||
EvaluateModel parent = new EvaluateModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getExpression());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
EvaluateModel child = new EvaluateModel("child");
|
||||
EvaluateModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getExpression());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
EvaluateModel child = new EvaluateModel("child");
|
||||
EvaluateModel parent = new EvaluateModel("child", "end");
|
||||
child.merge(parent);
|
||||
assertEquals("end", child.getResult());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
EvaluateModel child = new EvaluateModel("child");
|
||||
EvaluateModel parent = new EvaluateModel("parent", "end");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getResult());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.ExceptionHandlerModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ExceptionHandlerModel}.
|
||||
*/
|
||||
public class ExceptionHandlerModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
ExceptionHandlerModel child = new ExceptionHandlerModel("child");
|
||||
ExceptionHandlerModel parent = new ExceptionHandlerModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getBeanName());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
ExceptionHandlerModel child = new ExceptionHandlerModel("child");
|
||||
ExceptionHandlerModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getBeanName());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
// exception handler will never merge
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
// exception handler will never merge
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link FlowModel}.
|
||||
*/
|
||||
public class FlowModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
FlowModel child = new FlowModel();
|
||||
child.setStartStateId("child");
|
||||
FlowModel parent = new FlowModel();
|
||||
parent.setStartStateId("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getStartStateId());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
FlowModel child = new FlowModel();
|
||||
child.setStartStateId("child");
|
||||
FlowModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getStartStateId());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
parent.addViewState(new ViewStateModel("view"));
|
||||
child.merge(parent);
|
||||
assertEquals(1, child.getStates().size());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
parent.addViewState(new ViewStateModel("view"));
|
||||
child.merge(parent);
|
||||
// flows will always merge, regardless of likeness
|
||||
assertEquals(1, child.getStates().size());
|
||||
}
|
||||
|
||||
public void testIntegrationAttributes() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addAttribute(new AttributeModel("name", "value"));
|
||||
parent.addAttribute(new AttributeModel("name", "value", "type"));
|
||||
parent.addAttribute(new AttributeModel("name2", "value2", "type2"));
|
||||
child.merge(parent);
|
||||
assertEquals(2, child.getAttributes().size());
|
||||
assertEquals("name", ((AttributeModel) child.getAttributes().get(0)).getName());
|
||||
assertEquals("type", ((AttributeModel) child.getAttributes().get(0)).getType());
|
||||
assertEquals("name2", ((AttributeModel) child.getAttributes().get(1)).getName());
|
||||
assertEquals("type2", ((AttributeModel) child.getAttributes().get(1)).getType());
|
||||
}
|
||||
|
||||
public void testIntegrationSecured() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.setSecured(new SecuredModel("secured"));
|
||||
parent.setSecured(new SecuredModel("secured", "all"));
|
||||
child.merge(parent);
|
||||
assertEquals("all", child.getSecured().getMatch());
|
||||
}
|
||||
|
||||
public void testIntegrationPersistenceContext() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
parent.setPersistenceContext(new PersistenceContextModel());
|
||||
child.merge(parent);
|
||||
assertNotNull(child.getPersistenceContext());
|
||||
}
|
||||
|
||||
public void testIntegrationVars() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addVar(new VarModel("name", "value"));
|
||||
parent.addVar(new VarModel("name", "", "scope"));
|
||||
parent.addVar(new VarModel("name2", "value2"));
|
||||
child.merge(parent);
|
||||
assertEquals(2, child.getVars().size());
|
||||
assertEquals("scope", ((VarModel) child.getVars().get(1)).getScope());
|
||||
}
|
||||
|
||||
public void testIntegrationMappings() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addInput(new InputModel("name", "value"));
|
||||
child.addInput(new InputModel("name2", "value2", "type2", "required2"));
|
||||
child.addInput(new InputModel("name3", "value3", "type3", "required3"));
|
||||
parent.addInput(new InputModel("name", "value", "type", "required"));
|
||||
parent.addInput(new InputModel("name3", "value3", "type3", "required3"));
|
||||
child.merge(parent);
|
||||
assertEquals(3, child.getInputs().size());
|
||||
}
|
||||
|
||||
public void testIntegrationOnStart() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addOnStartAction(new EvaluateModel("expression"));
|
||||
child.addOnStartAction(new RenderModel("expression"));
|
||||
child.addOnStartAction(new SetModel("expression", "value"));
|
||||
parent.addOnStartAction(new EvaluateModel("expression", "result"));
|
||||
parent.addOnStartAction(new RenderModel("expression"));
|
||||
parent.addOnStartAction(new SetModel("expression", "value"));
|
||||
child.merge(parent);
|
||||
assertEquals(3, child.getOnStartActions().size());
|
||||
assertEquals("result", ((EvaluateModel) child.getOnStartActions().get(0)).getResult());
|
||||
}
|
||||
|
||||
public void testIntegrationStates() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addViewState(new ViewStateModel("view"));
|
||||
child.addEndState(new EndStateModel("end"));
|
||||
parent.addViewState(new ViewStateModel("view", "jsp"));
|
||||
parent.addState(new DecisionStateModel("decider"));
|
||||
parent.addActionState(new ActionStateModel("end"));
|
||||
child.merge(parent);
|
||||
assertEquals(4, child.getStates().size());
|
||||
assertEquals("jsp", ((ViewStateModel) child.getStates().get(0)).getView());
|
||||
}
|
||||
|
||||
public void testIntegrationGlobalTransitions() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addGlobalTransition(new TransitionModel("end"));
|
||||
child.addGlobalTransition(new TransitionModel("start"));
|
||||
parent.addGlobalTransition(new TransitionModel("search"));
|
||||
parent.addGlobalTransition(new TransitionModel("end", "theend"));
|
||||
child.merge(parent);
|
||||
assertEquals(3, child.getGlobalTransitions().size());
|
||||
assertEquals("theend", ((TransitionModel) child.getGlobalTransitions().get(0)).getTo());
|
||||
}
|
||||
|
||||
public void testIntegrationOnEnd() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addOnEndAction(new EvaluateModel("expression"));
|
||||
child.addOnEndAction(new RenderModel("expression"));
|
||||
child.addOnEndAction(new SetModel("expression", "value"));
|
||||
parent.addOnEndAction(new EvaluateModel("expression", "result"));
|
||||
parent.addOnEndAction(new RenderModel("expression"));
|
||||
parent.addOnEndAction(new SetModel("expression", "value"));
|
||||
child.merge(parent);
|
||||
assertEquals(3, child.getOnEndActions().size());
|
||||
assertEquals("result", ((EvaluateModel) child.getOnEndActions().get(0)).getResult());
|
||||
}
|
||||
|
||||
public void testIntegrationExceptionHandlers() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addExceptionHandler(new ExceptionHandlerModel("bean1"));
|
||||
child.addExceptionHandler(new ExceptionHandlerModel("bean2"));
|
||||
parent.addExceptionHandler(new ExceptionHandlerModel("bean2"));
|
||||
parent.addExceptionHandler(new ExceptionHandlerModel("bean3"));
|
||||
child.merge(parent);
|
||||
assertEquals(3, child.getExceptionHandlers().size());
|
||||
}
|
||||
|
||||
public void testIntegrationBeanImports() {
|
||||
FlowModel child = new FlowModel();
|
||||
FlowModel parent = new FlowModel();
|
||||
child.addBeanImport(new BeanImportModel("path1"));
|
||||
child.addBeanImport(new BeanImportModel("path2"));
|
||||
parent.addBeanImport(new BeanImportModel("path2"));
|
||||
parent.addBeanImport(new BeanImportModel("path3"));
|
||||
child.merge(parent);
|
||||
assertEquals(3, child.getBeanImports().size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.IfModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link IfModel}.
|
||||
*/
|
||||
public class IfModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
IfModel child = new IfModel("child", "childthen");
|
||||
IfModel parent = new IfModel("parent", "parentthen");
|
||||
child.merge(parent);
|
||||
assertEquals("childthen", child.getThen());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
IfModel child = new IfModel("child", "childthen");
|
||||
IfModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("childthen", child.getThen());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
IfModel child = new IfModel("child", "childthen");
|
||||
IfModel parent = new IfModel("child", "childthen", "childelse");
|
||||
child.merge(parent);
|
||||
assertEquals("childelse", child.getElse());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
IfModel child = new IfModel("child", "childthen");
|
||||
IfModel parent = new IfModel("parent", "parentthen", "parentelse");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getElse());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.InputModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link InputModel}.
|
||||
*/
|
||||
public class InputModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
InputModel child = new InputModel("child", "childvalue");
|
||||
InputModel parent = new InputModel("parent", "parentvalue");
|
||||
child.merge(parent);
|
||||
assertEquals("childvalue", child.getValue());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
InputModel child = new InputModel("child", "childvalue");
|
||||
InputModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("childvalue", child.getValue());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
InputModel child = new InputModel("child", "childvalue");
|
||||
InputModel parent = new InputModel("child", "childvalue");
|
||||
parent.setType("long");
|
||||
child.merge(parent);
|
||||
assertEquals("long", child.getType());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
InputModel child = new InputModel("child", "childvalue");
|
||||
InputModel parent = new InputModel("parent", "parentvalue");
|
||||
parent.setType("long");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.OutputModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link OutputModel}.
|
||||
*/
|
||||
public class OutputModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
OutputModel child = new OutputModel("child", "childvalue");
|
||||
OutputModel parent = new OutputModel("parent", "parentvalue");
|
||||
child.merge(parent);
|
||||
assertEquals("childvalue", child.getValue());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
OutputModel child = new OutputModel("child", "childvalue");
|
||||
OutputModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("childvalue", child.getValue());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
OutputModel child = new OutputModel("child", "childvalue");
|
||||
OutputModel parent = new OutputModel("child", "childvalue");
|
||||
parent.setType("long");
|
||||
child.merge(parent);
|
||||
assertEquals("long", child.getType());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
OutputModel child = new OutputModel("child", "childvalue");
|
||||
OutputModel parent = new OutputModel("parent", "parentvalue");
|
||||
parent.setType("long");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.PersistenceContextModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PersistenceContextModel}.
|
||||
*/
|
||||
public class PersistenceContextModelTests extends TestCase {
|
||||
|
||||
public void test() {
|
||||
// no op
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.RenderModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RenderModel}.
|
||||
*/
|
||||
public class RenderModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
RenderModel child = new RenderModel("child");
|
||||
RenderModel parent = new RenderModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getFragments());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
RenderModel child = new RenderModel("child");
|
||||
RenderModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getFragments());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
// render will never merge
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
// render will never merge
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.SecuredModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SecuredModel}.
|
||||
*/
|
||||
public class SecuredModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
SecuredModel child = new SecuredModel("child");
|
||||
SecuredModel parent = new SecuredModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getAttributes());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
SecuredModel child = new SecuredModel("child");
|
||||
SecuredModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getAttributes());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
SecuredModel child = new SecuredModel("child");
|
||||
SecuredModel parent = new SecuredModel("child", "all");
|
||||
child.merge(parent);
|
||||
assertEquals("all", child.getMatch());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
SecuredModel child = new SecuredModel("child");
|
||||
SecuredModel parent = new SecuredModel("parent", "all");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getMatch());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.SetModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SetModel}.
|
||||
*/
|
||||
public class SetModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
SetModel child = new SetModel("child", "childvalue");
|
||||
SetModel parent = new SetModel("parent", "parentvalue");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getName());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
SetModel child = new SetModel("child", "childvalue");
|
||||
SetModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getName());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
SetModel child = new SetModel("child", "childvalue");
|
||||
SetModel parent = new SetModel("child", "childvalue", "childtype");
|
||||
child.merge(parent);
|
||||
assertEquals("childtype", child.getType());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
SetModel child = new SetModel("child", "childvalue");
|
||||
SetModel parent = new SetModel("parent", "parentvalue", "parenttype");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SubflowStateModel}.
|
||||
*/
|
||||
public class SubflowStateModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
SubflowStateModel child = new SubflowStateModel("child", "childflow");
|
||||
SubflowStateModel parent = new SubflowStateModel("parent", "parentflow");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
SubflowStateModel child = new SubflowStateModel("child", "childflow");
|
||||
SubflowStateModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getId());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
SubflowStateModel child = new SubflowStateModel("child", "childflow");
|
||||
SubflowStateModel parent = new SubflowStateModel("child", "parentflow");
|
||||
parent.addInput(new InputModel("inname", "invalue"));
|
||||
child.merge(parent);
|
||||
assertEquals(1, child.getInputs().size());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
SubflowStateModel child = new SubflowStateModel("child", "childflow");
|
||||
SubflowStateModel parent = new SubflowStateModel("parent", "parentflow");
|
||||
parent.addInput(new InputModel("inname", "invalue"));
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getInputs());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.TransitionModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TransitionModel}.
|
||||
*/
|
||||
public class TransitionModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
TransitionModel child = new TransitionModel("child");
|
||||
TransitionModel parent = new TransitionModel("parent");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getOn());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
TransitionModel child = new TransitionModel("child");
|
||||
TransitionModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getOn());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
TransitionModel child = new TransitionModel("child");
|
||||
TransitionModel parent = new TransitionModel("child", "end");
|
||||
child.merge(parent);
|
||||
assertEquals("end", child.getTo());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
TransitionModel child = new TransitionModel("child");
|
||||
TransitionModel parent = new TransitionModel("parent", "end");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getTo());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.VarModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link VarModel}.
|
||||
*/
|
||||
public class VarModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
VarModel child = new VarModel("child", "childclass");
|
||||
VarModel parent = new VarModel("parent", "parentclass");
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getName());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
VarModel child = new VarModel("child", "childclass");
|
||||
VarModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("child", child.getName());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
VarModel child = new VarModel("child", "childclass");
|
||||
VarModel parent = new VarModel("child", "childclass", "childscope");
|
||||
child.merge(parent);
|
||||
assertEquals("childscope", child.getScope());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
VarModel child = new VarModel("child", "childclass");
|
||||
VarModel parent = new VarModel("parent", "parentclass", "parentscope");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getScope());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.model;
|
||||
|
||||
import org.springframework.webflow.engine.model.ViewStateModel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ViewStateModel}.
|
||||
*/
|
||||
public class ViewStateModelTests extends TestCase {
|
||||
|
||||
public void testMerge() {
|
||||
ViewStateModel child = new ViewStateModel("child", "childview");
|
||||
ViewStateModel parent = new ViewStateModel("parent", "parentview");
|
||||
child.merge(parent);
|
||||
assertEquals("childview", child.getView());
|
||||
}
|
||||
|
||||
public void testMergeNullParent() {
|
||||
ViewStateModel child = new ViewStateModel("child", "childview");
|
||||
ViewStateModel parent = null;
|
||||
child.merge(parent);
|
||||
assertEquals("childview", child.getView());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatch() {
|
||||
ViewStateModel child = new ViewStateModel("child");
|
||||
ViewStateModel parent = new ViewStateModel("child", "parentview");
|
||||
child.merge(parent);
|
||||
assertEquals("parentview", child.getView());
|
||||
}
|
||||
|
||||
public void testMergeOverrideMatchFailed() {
|
||||
ViewStateModel child = new ViewStateModel("child");
|
||||
ViewStateModel parent = new ViewStateModel("parent", "parentview");
|
||||
child.merge(parent);
|
||||
assertEquals(null, child.getView());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
package org.springframework.webflow.engine.model.builder.xml;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.webflow.engine.model.AbstractStateModel;
|
||||
import org.springframework.webflow.engine.model.AttributeModel;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.SecuredModel;
|
||||
import org.springframework.webflow.engine.model.TransitionModel;
|
||||
import org.springframework.webflow.engine.model.VarModel;
|
||||
import org.springframework.webflow.engine.model.ViewStateModel;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelConstructionException;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistry;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
|
||||
|
||||
public class XmlFlowModelBuilderTests extends TestCase {
|
||||
|
||||
private FlowModelRegistry registry;
|
||||
|
||||
protected void setUp() {
|
||||
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
|
||||
beanFactory.addBean("bean", new Object());
|
||||
registry = new FlowModelRegistryImpl();
|
||||
}
|
||||
|
||||
// public void testBuildIncompleteFlow() {
|
||||
// ClassPathResource resource = new ClassPathResource("flow-incomplete.xml", getClass());
|
||||
// builder = new XmlModelBuilder(resource);
|
||||
// try {
|
||||
// builder.parse();
|
||||
// fail("Should have failed");
|
||||
// } catch (FlowBuilderException e) {
|
||||
// }
|
||||
// }
|
||||
|
||||
public void testBuildFlowWithEndState() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-endstate.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertNull(flow.getStartStateId());
|
||||
assertEquals("end", ((AbstractStateModel) flow.getStates().get(0)).getId());
|
||||
}
|
||||
|
||||
public void testBuildFlowWithDefaultStartState() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-startstate-default.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertNull(flow.getStartStateId());
|
||||
assertEquals("end", ((AbstractStateModel) flow.getStates().get(0)).getId());
|
||||
}
|
||||
|
||||
public void testBuildFlowWithStartStateAttribute() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-startstate-attribute.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertEquals("end", flow.getStartStateId());
|
||||
}
|
||||
|
||||
public void testCustomFlowAttribute() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-custom-attribute.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertEquals("bar", ((AttributeModel) flow.getAttributes().get(0)).getValue());
|
||||
assertEquals("number", ((AttributeModel) flow.getAttributes().get(1)).getName());
|
||||
}
|
||||
|
||||
public void testPersistenceContextFlow() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-persistencecontext.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertNotNull(flow.getPersistenceContext());
|
||||
}
|
||||
|
||||
// public void testFlowInputOutputMapping() {
|
||||
// ClassPathResource resource = new ClassPathResource("flow-inputoutput.xml", getClass());
|
||||
// FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
// builder.init();
|
||||
// builder.build();
|
||||
// FlowModel flow = builder.getFlowModel();
|
||||
// FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
// FlowExecution execution = factory.createFlowExecution(flow);
|
||||
// MockExternalContext context = new MockExternalContext();
|
||||
// MutableAttributeMap input = new LocalAttributeMap();
|
||||
// input.put("foo", "bar");
|
||||
// input.put("number", "3");
|
||||
// input.put("required", "9");
|
||||
// execution.start(input, context);
|
||||
// Event outcome = execution.getOutcome();
|
||||
// assertEquals("end", outcome.getId());
|
||||
// assertEquals("bar", outcome.getAttributes().get("foo"));
|
||||
// assertEquals("bar", outcome.getAttributes().get("differentName"));
|
||||
// assertEquals(new Integer(3), outcome.getAttributes().get("number"));
|
||||
// assertEquals(new Integer(3), outcome.getAttributes().get("required"));
|
||||
// assertEquals("a literal", outcome.getAttributes().get("literal"));
|
||||
// assertNull(outcome.getAttributes().get("notReached"));
|
||||
// }
|
||||
|
||||
// public void testFlowRequiredInputMapping() {
|
||||
// ClassPathResource resource = new ClassPathResource("flow-inputoutput.xml", getClass());
|
||||
// FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
// builder.init();
|
||||
// builder.build();
|
||||
// FlowModel flow = builder.getFlowModel();
|
||||
// FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
// FlowExecution execution = factory.createFlowExecution(flow);
|
||||
// MockExternalContext context = new MockExternalContext();
|
||||
// MutableAttributeMap input = new LocalAttributeMap();
|
||||
// try {
|
||||
// execution.start(input, context);
|
||||
// fail("Should have failed");
|
||||
// } catch (FlowExecutionException e) {
|
||||
// RequiredMappingException me = (RequiredMappingException) e.getRootCause();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void testFlowRequiredOutputMapping() {
|
||||
// ClassPathResource resource = new ClassPathResource("flow-inputoutput.xml", getClass());
|
||||
// FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
// builder.init();
|
||||
// builder.build();
|
||||
// FlowModel flow = builder.getFlowModel();
|
||||
// FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
// FlowExecution execution = factory.createFlowExecution(flow);
|
||||
// MockExternalContext context = new MockExternalContext();
|
||||
// MutableAttributeMap input = new LocalAttributeMap();
|
||||
// input.put("required", "yo");
|
||||
// try {
|
||||
// execution.start(input, context);
|
||||
// fail("Should have failed");
|
||||
// } catch (FlowExecutionException e) {
|
||||
// RequiredMappingException me = (RequiredMappingException) e.getRootCause();
|
||||
// }
|
||||
// }
|
||||
|
||||
public void testFlowSecured() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-secured.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
SecuredModel secured = flow.getSecured();
|
||||
assertNotNull(secured);
|
||||
assertEquals("ROLE_USER", secured.getAttributes());
|
||||
}
|
||||
|
||||
public void testFlowSecuredState() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-secured-state.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
SecuredModel secured = ((AbstractStateModel) flow.getStates().get(0)).getSecured();
|
||||
assertNotNull(secured);
|
||||
assertEquals("ROLE_USER", secured.getAttributes());
|
||||
}
|
||||
|
||||
public void testFlowSecuredTransition() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-secured-transition.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
SecuredModel secured = ((TransitionModel) flow.getGlobalTransitions().get(0)).getSecured();
|
||||
assertNotNull(secured);
|
||||
assertEquals("ROLE_USER", secured.getAttributes());
|
||||
}
|
||||
|
||||
public void testFlowVariable() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-var.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertEquals("flow-foo", ((VarModel) flow.getVars().get(0)).getName());
|
||||
assertEquals(null, ((VarModel) flow.getVars().get(0)).getScope());
|
||||
assertEquals("conversation-foo", ((VarModel) flow.getVars().get(1)).getName());
|
||||
assertEquals("conversation", ((VarModel) flow.getVars().get(1)).getScope());
|
||||
}
|
||||
|
||||
public void testViewStateVariable() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-var.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertEquals("foo", ((VarModel) ((ViewStateModel) flow.getStates().get(0)).getVars().get(0)).getName());
|
||||
}
|
||||
|
||||
public void testViewStateRedirect() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-redirect.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertEquals("true", ((ViewStateModel) flow.getStates().get(0)).getRedirect());
|
||||
}
|
||||
|
||||
public void testViewStatePopup() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-viewstate-popup.xml", getClass());
|
||||
FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
builder.init();
|
||||
builder.build();
|
||||
FlowModel flow = builder.getFlowModel();
|
||||
assertEquals("true", ((ViewStateModel) flow.getStates().get(0)).getPopup());
|
||||
}
|
||||
|
||||
// public void testViewStateFlowRedirect() {
|
||||
// ClassPathResource resource = new ClassPathResource("flow-viewstate-flowredirect.xml",
|
||||
// getClass());
|
||||
// FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
// builder.init();
|
||||
// builder.build();
|
||||
// FlowModel flow = builder.getFlowModel();
|
||||
// ViewFactory vf = ((ViewState) flow.getStateInstance("view")).getViewFactory();
|
||||
// assertTrue(vf instanceof ActionExecutingViewFactory);
|
||||
// ActionExecutingViewFactory avf = (ActionExecutingViewFactory) vf;
|
||||
// assertTrue(avf.getAction() instanceof FlowDefinitionRedirectAction);
|
||||
// }
|
||||
|
||||
// public void testViewStateExternalRedirect() {
|
||||
// ClassPathResource resource = new ClassPathResource("flow-viewstate-externalredirect.xml",
|
||||
// getClass());
|
||||
// FlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry);
|
||||
// builder.init();
|
||||
// builder.build();
|
||||
// FlowModel flow = builder.getFlowModel();
|
||||
// ViewFactory vf = ((ViewState) flow.getStateInstance("view")).getViewFactory();
|
||||
// assertTrue(vf instanceof ActionExecutingViewFactory);
|
||||
// ActionExecutingViewFactory avf = (ActionExecutingViewFactory) vf;
|
||||
// assertTrue(avf.getAction() instanceof ExternalRedirectAction);
|
||||
// }
|
||||
|
||||
public void testMerge() {
|
||||
ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-child.xml", getClass());
|
||||
ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-parent.xml", getClass());
|
||||
registry
|
||||
.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child"));
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry),
|
||||
"parent"));
|
||||
FlowModel flow = registry.getFlowModel("child");
|
||||
assertEquals(1, flow.getGlobalTransitions().size());
|
||||
assertEquals(2, flow.getStates().size());
|
||||
assertEquals("view", ((AbstractStateModel) flow.getStates().get(0)).getId());
|
||||
}
|
||||
|
||||
public void testMergeParentNotFound() {
|
||||
ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-child.xml", getClass());
|
||||
ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-parent.xml", getClass());
|
||||
registry
|
||||
.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child"));
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry),
|
||||
"parent-id-not-matching"));
|
||||
try {
|
||||
registry.getFlowModel("child");
|
||||
fail("A FlowModelConstructionException was expected");
|
||||
} catch (FlowModelConstructionException e) {
|
||||
// we want this
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,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-2.0.xsd"
|
||||
parent="parent">
|
||||
|
||||
<view-state id="view" view="myCustomView" />
|
||||
|
||||
</flow>
|
||||
@@ -0,0 +1,13 @@
|
||||
<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-2.0.xsd">
|
||||
|
||||
<end-state id="end"/>
|
||||
|
||||
<global-transitions>
|
||||
<transition to="end">
|
||||
<secured attributes="ROLE_USER"/>
|
||||
</transition>
|
||||
</global-transitions>
|
||||
|
||||
</flow>
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.springframework.webflow.engine.model.registry;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.webflow.engine.model.AbstractStateModel;
|
||||
import org.springframework.webflow.engine.model.EndStateModel;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilderException;
|
||||
import org.springframework.webflow.util.ResourceHolder;
|
||||
|
||||
public class DefaultFlowModelHolderTests extends TestCase {
|
||||
private DefaultFlowModelHolder holder;
|
||||
private FlowModelBuilder builder;
|
||||
|
||||
protected void setUp() {
|
||||
builder = new SimpleFlowBuilder();
|
||||
holder = new DefaultFlowModelHolder(builder, "flowId");
|
||||
}
|
||||
|
||||
public void testGetFlowDefinition() {
|
||||
FlowModel flow = holder.getFlowModel();
|
||||
assertNull(flow.getStartStateId());
|
||||
assertEquals("end", ((AbstractStateModel) flow.getStates().get(0)).getId());
|
||||
}
|
||||
|
||||
public void testGetFlowDefinitionWithChangesRefreshed() {
|
||||
FlowModel flow = holder.getFlowModel();
|
||||
holder.refresh();
|
||||
flow = holder.getFlowModel();
|
||||
assertNull(flow.getStartStateId());
|
||||
assertEquals("end", ((AbstractStateModel) flow.getStates().get(0)).getId());
|
||||
}
|
||||
|
||||
public class SimpleFlowBuilder implements FlowModelBuilder {
|
||||
|
||||
public FlowModel getFlowModel() throws FlowModelBuilderException {
|
||||
FlowModel flow = new FlowModel();
|
||||
flow.addEndState(new EndStateModel("end"));
|
||||
return flow;
|
||||
}
|
||||
|
||||
public void build() throws FlowModelBuilderException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void mergeParent() throws FlowModelBuilderException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void dispose() throws FlowModelBuilderException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void init() throws FlowModelBuilderException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ChangeDetectableFlowBuilder extends SimpleFlowBuilder implements ResourceHolder {
|
||||
private FileSystemResource resource = new FileSystemResource("file.txt");
|
||||
|
||||
public Resource getResource() {
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.springframework.webflow.engine.model.registry;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
|
||||
public class FlowModelRegistryImplTests extends TestCase {
|
||||
|
||||
private FlowModelRegistryImpl registry = new FlowModelRegistryImpl();
|
||||
|
||||
private FlowModel fooFlow;
|
||||
|
||||
private FlowModel barFlow;
|
||||
|
||||
protected void setUp() {
|
||||
fooFlow = new FlowModel();
|
||||
barFlow = new FlowModel();
|
||||
}
|
||||
|
||||
public void testNoSuchFlowDefinition() {
|
||||
try {
|
||||
registry.getFlowModel("bogus");
|
||||
fail("Should've bombed with NoSuchFlow");
|
||||
} catch (NoSuchFlowModelException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testRegisterFlow() {
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo"));
|
||||
assertEquals(fooFlow, registry.getFlowModel("foo"));
|
||||
}
|
||||
|
||||
public void testRegisterFlowSameIds() {
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo"));
|
||||
FlowModel newFlow = new FlowModel();
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(newFlow, "foo"));
|
||||
assertSame(newFlow, registry.getFlowModel("foo"));
|
||||
}
|
||||
|
||||
public void testRegisterMultipleFlows() {
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo"));
|
||||
registry.registerFlowModel(new DefaultFlowModelHolder(barFlow, "bar"));
|
||||
assertEquals(fooFlow, registry.getFlowModel("foo"));
|
||||
assertEquals(barFlow, registry.getFlowModel("bar"));
|
||||
}
|
||||
|
||||
public void testParentHierarchy() {
|
||||
testRegisterMultipleFlows();
|
||||
FlowModelRegistryImpl child = new FlowModelRegistryImpl();
|
||||
child.setParent(registry);
|
||||
FlowModel fooFlow = new FlowModel();
|
||||
child.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo"));
|
||||
assertSame(fooFlow, child.getFlowModel("foo"));
|
||||
assertEquals(barFlow, child.getFlowModel("bar"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
a changeable file
|
||||
Reference in New Issue
Block a user