KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > webflow > engine > builder > AbstractFlowBuilder


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.webflow.engine.builder;
17
18 import org.springframework.binding.expression.Expression;
19 import org.springframework.binding.mapping.AttributeMapper;
20 import org.springframework.binding.mapping.Mapping;
21 import org.springframework.binding.mapping.MappingBuilder;
22 import org.springframework.binding.method.MethodSignature;
23 import org.springframework.webflow.action.AbstractBeanInvokingAction;
24 import org.springframework.webflow.action.ActionResultExposer;
25 import org.springframework.webflow.action.BeanInvokingActionFactory;
26 import org.springframework.webflow.action.EvaluateAction;
27 import org.springframework.webflow.action.MultiAction;
28 import org.springframework.webflow.core.collection.AttributeMap;
29 import org.springframework.webflow.core.collection.CollectionUtils;
30 import org.springframework.webflow.engine.AnnotatedAction;
31 import org.springframework.webflow.engine.Flow;
32 import org.springframework.webflow.engine.FlowAttributeMapper;
33 import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
34 import org.springframework.webflow.engine.State;
35 import org.springframework.webflow.engine.TargetStateResolver;
36 import org.springframework.webflow.engine.Transition;
37 import org.springframework.webflow.engine.TransitionCriteria;
38 import org.springframework.webflow.engine.ViewSelector;
39 import org.springframework.webflow.engine.support.ActionTransitionCriteria;
40 import org.springframework.webflow.execution.Action;
41 import org.springframework.webflow.execution.ScopeType;
42 import org.springframework.webflow.execution.support.EventFactorySupport;
43
44 /**
45  * Base class for flow builders that programmatically build flows in Java
46  * configuration code.
47  * <p>
48  * To give you an example of what a simple Java-based web flow builder
49  * definition might look like, the following example defines the 'dynamic' web
50  * flow roughly equivalent to the work flow statically implemented in Spring
51  * MVC's simple form controller:
52  *
53  * <pre class="code">
54  * public class CustomerDetailFlowBuilder extends AbstractFlowBuilder {
55  * public void buildStates() {
56  * // get customer information
57  * addActionState(&quot;getDetails&quot;, action(&quot;customerAction&quot;), transition(on(success()), to(&quot;displayDetails&quot;)));
58  *
59  * // view customer information
60  * addViewState(&quot;displayDetails&quot;, &quot;customerDetails&quot;, transition(on(submit()), to(&quot;bindAndValidate&quot;)));
61  *
62  * // bind and validate customer information updates
63  * addActionState(&quot;bindAndValidate&quot;, action(&quot;customerAction&quot;), new Transition[] {
64  * transition(on(error()), to(&quot;displayDetails&quot;)), transition(on(success()), to(&quot;finish&quot;)) });
65  *
66  * // finish
67  * addEndState(&quot;finish&quot;);
68  * }
69  * }
70  * </pre>
71  *
72  * What this Java-based FlowBuilder implementation does is add four states to a
73  * flow. These include a "get" <code>ActionState</code> (the start state), a
74  * <code>ViewState</code> state, a "bind and validate"
75  * <code>ActionState</code>, and an end marker state (<code>EndState</code>).
76  * <p>
77  * The first state, an action state, will be assigned the indentifier
78  * <code>getDetails</code>. This action state will automatically be
79  * configured with the following defaults:
80  * <ol>
81  * <li>The action instance with id <code>customerAction</code>. This is the
82  * <code>Action</code> implementation that will execute when this state is
83  * entered. In this example, that <code>Action</code> will go out to the DB,
84  * load the Customer, and put it in the Flow's request context.
85  * <li>A <code>success</code> transition to a default view state, called
86  * <code>displayDetails</code>. This means when the <code>Action</code>
87  * returns a <code>success</code> result event (aka outcome), the
88  * <code>displayDetails</code> state will be entered.
89  * <li>It will act as the start state for this flow (by default, the first
90  * state added to a flow during the build process is treated as the start
91  * state).
92  * </ol>
93  * <p>
94  * The second state, a view state, will be identified as
95  * <code>displayDetails</code>. This view state will automatically be
96  * configured with the following defaults:
97  * <ol>
98  * <li>A view name called <code>customerDetails</code>. This is the logical
99  * name of a view resource. This logical view name gets mapped to a physical
100  * view resource (jsp, etc.) by the calling front controller (via a Spring view
101  * resolver, or a Struts action forward, for example).
102  * <li>A <code>submit</code> transition to a bind and validate action state,
103  * indentified by the default id <code>bindAndValidate</code>. This means
104  * when a <code>submit</code> event is signaled by the view (for example, on a
105  * submit button click), the bindAndValidate action state will be entered and
106  * the <code>bindAndValidate</code> method of the
107  * <code>customerAction</code> <code>Action</code> implementation will be
108  * executed.
109  * </ol>
110  * <p>
111  * The third state, an action state, will be indentified as
112  * <code>bindAndValidate</code>. This action state will automatically be
113  * configured with the following defaults:
114  * <ol>
115  * <li>An action bean named <code>customerAction</code> -- this is the name
116  * of the <code>Action</code> implementation exported in the application
117  * context that will execute when this state is entered. In this example, the
118  * <code>Action</code> has a "bindAndValidate" method that will bind form
119  * input in the HTTP request to a backing Customer form object, validate it, and
120  * update the DB.
121  * <li>A <code>success</code> transition to a default end state, called
122  * <code>finish</code>. This means if the <code>Action</code> returns a
123  * <code>success</code> result, the <code>finish</code> end state will be
124  * transitioned to and the flow will terminate.
125  * <li>An <code>error</code> transition back to the form view. This means if
126  * the <code>Action</code> returns an <code>error</code> event, the <code>
127  * displayDetails</code> view state will be transitioned back to.
128  * </ol>
129  * <p>
130  * The fourth and last state, an end state, will be indentified with the default
131  * end state id <code>finish</code>. This end state is a marker that signals
132  * the end of the flow. When entered, the flow session terminates, and if this
133  * flow is acting as a root flow in the current flow execution, any
134  * flow-allocated resources will be cleaned up. An end state can optionally be
135  * configured with a logical view name to forward to when entered. It will also
136  * trigger a state transition in a resuming parent flow if this flow was
137  * participating as a spawned 'subflow' within a suspended parent flow.
138  *
139  * @author Keith Donald
140  * @author Erwin Vervaet
141  */

142 public abstract class AbstractFlowBuilder extends BaseFlowBuilder {
143
144     /**
145      * A helper for creating commonly used event identifiers that drive
146      * transitions created by this builder.
147      */

148     private EventFactorySupport eventFactorySupport = new EventFactorySupport();
149
150     /**
151      * Default constructor for subclassing.
152      */

153     protected AbstractFlowBuilder() {
154         super();
155     }
156
157     /**
158      * Create an instance of an abstract flow builder, using the specified
159      * locator to obtain needed flow services at build time.
160      * @param flowServiceLocator the locator for services needed by this builder
161      * to build its Flow
162      */

163     protected AbstractFlowBuilder(FlowServiceLocator flowServiceLocator) {
164         super(flowServiceLocator);
165     }
166
167     /**
168      * Returns the configured event factory support helper for creating commonly
169      * used event identifiers that drive transitions created by this builder.
170      */

171     public EventFactorySupport getEventFactorySupport() {
172         return eventFactorySupport;
173     }
174
175     /**
176      * Sets the event factory support helper to use to create commonly used
177      * event identifiers that drive transitions created by this builder.
178      */

179     public void setEventFactorySupport(EventFactorySupport eventFactorySupport) {
180         this.eventFactorySupport = eventFactorySupport;
181     }
182
183     public void init(String JavaDoc flowId, AttributeMap attributes) throws FlowBuilderException {
184         setFlow(getFlowArtifactFactory().createFlow(flowId, flowAttributes().union(attributes)));
185     }
186
187     /**
188      * Hook subclasses may override to provide additional properties for the
189      * flow built by this builder. Returns a empty collection by default.
190      * @return additional properties describing the flow being built, should not
191      * return null
192      */

193     protected AttributeMap flowAttributes() {
194         return CollectionUtils.EMPTY_ATTRIBUTE_MAP;
195     }
196
197     // view state
198

199     /**
200      * Adds a view state to the flow built by this builder.
201      * @param stateId the state identifier
202      * @param viewName the string-encoded view selector
203      * @param transition the sole transition (path) out of this state
204      * @return the fully constructed view state instance
205      */

206     protected State addViewState(String JavaDoc stateId, String JavaDoc viewName, Transition transition) {
207         return getFlowArtifactFactory().createViewState(stateId, getFlow(), null, viewSelector(viewName), null,
208                 new Transition[] { transition }, null, null, null);
209     }
210
211     /**
212      * Adds a view state to the flow built by this builder.
213      * @param stateId the state identifier
214      * @param viewName the string-encoded view selector
215      * @param transitions the transitions (paths) out of this state
216      * @return the fully constructed view state instance
217      */

218     protected State addViewState(String JavaDoc stateId, String JavaDoc viewName, Transition[] transitions) {
219         return getFlowArtifactFactory().createViewState(stateId, getFlow(), null, viewSelector(viewName), null,
220                 transitions, null, null, null);
221     }
222
223     /**
224      * Adds a view state to the flow built by this builder.
225      * @param stateId the state identifier
226      * @param viewName the string-encoded view selector
227      * @param renderAction the action to execute on state entry and refresh; may
228      * be null
229      * @param transition the sole transition (path) out of this state
230      * @return the fully constructed view state instance
231      */

232     protected State addViewState(String JavaDoc stateId, String JavaDoc viewName, Action renderAction, Transition transition) {
233         return getFlowArtifactFactory().createViewState(stateId, getFlow(), null, viewSelector(viewName),
234                 new Action[] { renderAction }, new Transition[] { transition }, null, null, null);
235     }
236
237     /**
238      * Adds a view state to the flow built by this builder.
239      * @param stateId the state identifier
240      * @param viewName the string-encoded view selector
241      * @param renderAction the action to execute on state entry and refresh; may
242      * be null
243      * @param transitions the transitions (paths) out of this state
244      * @return the fully constructed view state instance
245      */

246     protected State addViewState(String JavaDoc stateId, String JavaDoc viewName, Action renderAction, Transition[] transitions) {
247         return getFlowArtifactFactory().createViewState(stateId, getFlow(), null, viewSelector(viewName),
248                 new Action[] { renderAction }, transitions, null, null, null);
249     }
250
251     /**
252      * Adds a view state to the flow built by this builder.
253      * @param stateId the state identifier
254      * @param entryActions the actions to execute when the state is entered
255      * @param viewSelector the view selector that will make the view selection
256      * when the state is entered
257      * @param renderActions any 'render actions' to execute on state entry and
258      * refresh; may be null
259      * @param transitions the transitions (path) out of this state
260      * @param exceptionHandlers any exception handlers to attach to the state
261      * @param exitActions the actions to execute when the state exits
262      * @param attributes attributes to assign to the state that may be used to
263      * affect state construction and execution
264      * @return the fully constructed view state instance
265      */

266     protected State addViewState(String JavaDoc stateId, Action[] entryActions, ViewSelector viewSelector,
267             Action[] renderActions, Transition[] transitions, FlowExecutionExceptionHandler[] exceptionHandlers,
268             Action[] exitActions, AttributeMap attributes) {
269         return getFlowArtifactFactory().createViewState(stateId, getFlow(), entryActions, viewSelector, renderActions,
270                 transitions, exceptionHandlers, exitActions, attributes);
271     }
272
273     // action state
274

275     /**
276      * Adds an action state to the flow built by this builder.
277      * @param stateId the state identifier
278      * @param action the single action to execute when the state is entered
279      * @param transition the single transition (path) out of this state
280      * @return the fully constructed action state instance
281      */

282     protected State addActionState(String JavaDoc stateId, Action action, Transition transition) {
283         return getFlowArtifactFactory().createActionState(stateId, getFlow(), null, new Action[] { action },
284                 new Transition[] { transition }, null, null, null);
285     }
286
287     /**
288      * Adds an action state to the flow built by this builder.
289      * @param stateId the state identifier
290      * @param action the single action to execute when the state is entered
291      * @param transitions the transitions (paths) out of this state
292      * @return the fully constructed action state instance
293      */

294     protected State addActionState(String JavaDoc stateId, Action action, Transition[] transitions) {
295         return getFlowArtifactFactory().createActionState(stateId, getFlow(), null, new Action[] { action },
296                 transitions, null, null, null);
297     }
298
299     /**
300      * Adds an action state to the flow built by this builder.
301      * @param stateId the state identifier
302      * @param action the single action to execute when the state is entered
303      * @param transition the single transition (path) out of this state
304      * @param exceptionHandler the exception handler to handle exceptions thrown
305      * by the action
306      * @return the fully constructed action state instance
307      */

308     protected State addActionState(String JavaDoc stateId, Action action, Transition transition,
309             FlowExecutionExceptionHandler exceptionHandler) {
310         return getFlowArtifactFactory().createActionState(stateId, getFlow(), null, new Action[] { action },
311                 new Transition[] { transition }, new FlowExecutionExceptionHandler[] { exceptionHandler }, null, null);
312     }
313
314     /**
315      * Adds an action state to the flow built by this builder.
316      * @param stateId the state identifier
317      * @param entryActions any generic entry actions to add to the state
318      * @param actions the actions to execute in a chain when the state is
319      * entered
320      * @param transitions the transitions (paths) out of this state
321      * @param exceptionHandlers the exception handlers to handle exceptions
322      * thrown by the actions
323      * @param exitActions the exit actions to execute when the state exits
324      * @param attributes attributes to assign to the state that may be used to
325      * affect state construction and execution
326      * @return the fully constructed action state instance
327      */

328     protected State addActionState(String JavaDoc stateId, Action[] entryActions, Action[] actions, Transition[] transitions,
329             FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap attributes) {
330         return getFlowArtifactFactory().createActionState(stateId, getFlow(), entryActions, actions, transitions,
331                 exceptionHandlers, exitActions, attributes);
332     }
333
334     // decision state
335

336     /**
337      * Adds a decision state to the flow built by this builder.
338      * @param stateId the state identifier
339      * @param transitions the transitions (paths) out of this state
340      * @return the fully constructed decision state instance
341      */

342     protected State addDecisionState(String JavaDoc stateId, Transition[] transitions) {
343         return getFlowArtifactFactory().createDecisionState(stateId, getFlow(), null, transitions, null, null, null);
344     }
345
346     /**
347      * Adds a decision state to the flow built by this builder.
348      * @param stateId the state identifier
349      * @param decisionCriteria the criteria that defines the decision
350      * @param trueStateId the target state on a "true" decision
351      * @param falseStateId the target state on a "false" decision
352      * @return the fully constructed decision state instance
353      */

354     protected State addDecisionState(String JavaDoc stateId, TransitionCriteria decisionCriteria, String JavaDoc trueStateId,
355             String JavaDoc falseStateId) {
356         Transition thenTransition = getFlowArtifactFactory()
357                 .createTransition(to(trueStateId), decisionCriteria, null, null);
358         Transition elseTransition = getFlowArtifactFactory().createTransition(to(falseStateId), null, null, null);
359         return getFlowArtifactFactory().createDecisionState(stateId, getFlow(), null,
360                 new Transition[] { thenTransition, elseTransition }, null, null, null);
361     }
362
363     /**
364      * Adds a decision state to the flow built by this builder.
365      * @param stateId the state identifier
366      * @param entryActions the entry actions to execute when the state enters
367      * @param transitions the transitions (paths) out of this state
368      * @param exceptionHandlers the exception handlers to handle exceptions
369      * thrown by the state
370      * @param exitActions the exit actions to execute when the state exits
371      * @param attributes attributes to assign to the state that may be used to
372      * affect state construction and execution
373      * @return the fully constructed decision state instance
374      */

375     protected State addDecisionState(String JavaDoc stateId, Action[] entryActions, Transition[] transitions,
376             FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap attributes) {
377         return getFlowArtifactFactory().createDecisionState(stateId, getFlow(), entryActions, transitions,
378                 exceptionHandlers, exitActions, attributes);
379     }
380
381     // subflow state
382

383     /**
384      * Adds a subflow state to the flow built by this builder.
385      * @param stateId the state identifier
386      * @param subflow the flow that will act as the subflow
387      * @param attributeMapper the mapper to map subflow input and output
388      * attributes
389      * @param transition the single transition (path) out of the state
390      * @return the fully constructed subflow state instance
391      */

392     protected State addSubflowState(String JavaDoc stateId, Flow subflow, FlowAttributeMapper attributeMapper,
393             Transition transition) {
394         return getFlowArtifactFactory().createSubflowState(stateId, getFlow(), null, subflow, attributeMapper,
395                 new Transition[] { transition }, null, null, null);
396     }
397
398     /**
399      * Adds a subflow state to the flow built by this builder.
400      * @param stateId the state identifier
401      * @param subflow the flow that will act as the subflow
402      * @param attributeMapper the mapper to map subflow input and output
403      * attributes
404      * @param transitions the transitions (paths) out of the state
405      * @return the fully constructed subflow state instance
406      */

407     protected State addSubflowState(String JavaDoc stateId, Flow subflow, FlowAttributeMapper attributeMapper,
408             Transition[] transitions) {
409         return getFlowArtifactFactory().createSubflowState(stateId, getFlow(), null, subflow, attributeMapper,
410                 transitions, null, null, null);
411     }
412
413     /**
414      * Adds a subflow state to the flow built by this builder.
415      * @param stateId the state identifier
416      * @param entryActions the entry actions to execute when the state enters
417      * @param subflow the flow that will act as the subflow
418      * @param attributeMapper the mapper to map subflow input and output
419      * attributes
420      * @param transitions the transitions (paths) out of this state
421      * @param exceptionHandlers the exception handlers to handle exceptions
422      * thrown by the state
423      * @param exitActions the exit actions to execute when the state exits
424      * @param attributes attributes to assign to the state that may be used to
425      * affect state construction and execution
426      * @return the fully constructed subflow state instance
427      */

428     protected State addSubflowState(String JavaDoc stateId, Action[] entryActions, Flow subflow,
429             FlowAttributeMapper attributeMapper, Transition[] transitions,
430             FlowExecutionExceptionHandler[] exceptionHandlers, Action[] exitActions, AttributeMap attributes) {
431         return getFlowArtifactFactory().createSubflowState(stateId, getFlow(), entryActions, subflow, attributeMapper,
432                 transitions, exceptionHandlers, exitActions, attributes);
433     }
434
435     // end state
436

437     /**
438      * Adds an end state to the flow built by this builder.
439      * @param stateId the state identifier
440      * @return the fully constructed end state instance
441      */

442     protected State addEndState(String JavaDoc stateId) {
443         return getFlowArtifactFactory().createEndState(stateId, getFlow(), null, null, null, null, null);
444     }
445
446     /**
447      * Adds an end state to the flow built by this builder.
448      * @param stateId the state identifier
449      * @param viewName the string-encoded view selector
450      * @return the fully constructed end state instance
451      */

452     protected State addEndState(String JavaDoc stateId, String JavaDoc viewName) {
453         return getFlowArtifactFactory().createEndState(stateId, getFlow(), null, viewSelector(viewName), null,
454                 null, null);
455     }
456
457     /**
458      * Adds an end state to the flow built by this builder.
459      * @param stateId the state identifier
460      * @param viewName the string-encoded view selector
461      * @param outputMapper the output mapper to map output attributes for the
462      * end state (a flow outcome)
463      * @return the fully constructed end state instance
464      */

465     protected State addEndState(String JavaDoc stateId, String JavaDoc viewName, AttributeMapper outputMapper) {
466         return getFlowArtifactFactory().createEndState(stateId, getFlow(), null, viewSelector(viewName),
467                 outputMapper, null, null);
468     }
469
470     /**
471      * Adds an end state to the flow built by this builder.
472      * @param stateId the state identifier
473      * @param entryActions the actions to execute when the state is entered
474      * @param viewSelector the view selector that will make the view selection
475      * when the state is entered
476      * @param outputMapper the output mapper to map output attributes for the
477      * end state (a flow outcome)
478      * @param exceptionHandlers any exception handlers to attach to the state
479      * @param attributes attributes to assign to the state that may be used to
480      * affect state construction and execution
481      * @return the fully constructed end state instance
482      */

483     protected State addEndState(String JavaDoc stateId, Action[] entryActions, ViewSelector viewSelector,
484             AttributeMapper outputMapper, FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap attributes) {
485         return getFlowArtifactFactory().createEndState(stateId, getFlow(), entryActions, viewSelector, outputMapper,
486                 exceptionHandlers, attributes);
487     }
488
489     // helpers to create misc. flow artifacts
490

491     /**
492      * Factory method that creates a view selector from an encoded
493      * view name. See {@link TextToViewSelector} for information on the
494      * conversion rules.
495      * @param viewName the encoded view selector
496      * @return the view selector
497      */

498     public ViewSelector viewSelector(String JavaDoc viewName) {
499         return (ViewSelector)fromStringTo(ViewSelector.class).execute(viewName);
500     }
501
502     /**
503      * Resolves the action with the specified id. Simply looks the action up by
504      * id and returns it.
505      * @param id the action id
506      * @return the action
507      * @throws FlowArtifactLookupException the action could not be resolved
508      */

509     protected Action action(String JavaDoc id) throws FlowArtifactLookupException {
510         return getFlowServiceLocator().getAction(id);
511     }
512
513     /**
514      * Creates a bean invoking action that invokes the method identified by the
515      * signature on the bean associated with the action identifier.
516      * @param beanId the id identifying an arbitrary
517      * <code>java.lang.Object</code> to be used as an action
518      * @param methodSignature the signature of the method to invoke on the POJO
519      * @return the adapted bean invoking action
520      * @throws FlowArtifactLookupException the action could not be resolved
521      */

522     protected Action action(String JavaDoc beanId, MethodSignature methodSignature) throws FlowArtifactLookupException {
523         return getBeanInvokingActionFactory().createBeanInvokingAction(beanId,
524                 getFlowServiceLocator().getBeanFactory(), methodSignature, null,
525                 getFlowServiceLocator().getConversionService(), null);
526     }
527
528     /**
529      * Creates a bean invoking action that invokes the method identified by the
530      * signature on the bean associated with the action identifier.
531      * @param beanId the id identifying an arbitrary
532      * <code>java.lang.Object</code> to be used as an action
533      * @param methodSignature the signature of the method to invoke on the POJO
534      * @return the adapted bean invoking action
535      * @throws FlowArtifactLookupException the action could not be resolved
536      */

537     protected Action action(String JavaDoc beanId, MethodSignature methodSignature, ActionResultExposer resultExposer)
538             throws FlowArtifactLookupException {
539         return getBeanInvokingActionFactory().createBeanInvokingAction(beanId,
540                 getFlowServiceLocator().getBeanFactory(), methodSignature, resultExposer,
541                 getFlowServiceLocator().getConversionService(), null);
542     }
543
544     /**
545      * Creates an evaluate action that evaluates the expression when executed.
546      * @param expression the expression to evaluate
547      */

548     protected Action action(Expression expression) {
549         return action(expression, null);
550     }
551
552     /**
553      * Creates an evaluate action that evaluates the expression when executed.
554      * @param expression the expression to evaluate
555      * @param resultExposer the evaluation result exposer
556      */

557     protected Action action(Expression expression, ActionResultExposer resultExposer) {
558         return new EvaluateAction(expression, resultExposer);
559     }
560
561     /**
562      * Parses the expression string into a evaluatable {@link Expression}
563      * object.
564      * @param expressionString the expression string, e.g. flowScope.order.number
565      * @return the evaluatable expression
566      */

567     protected Expression expression(String JavaDoc expressionString) {
568         return getFlowServiceLocator().getExpressionParser().parseExpression(expressionString);
569     }
570
571     /**
572      * Convert the encoded method signature string to a {@link MethodSignature}
573      * object. Method signatures are used to match methods on POJO services to
574      * invoke on a {@link AbstractBeanInvokingAction bean invoking action}.
575      * <p>
576      * Encoded method signature format:
577      *
578      * Method without arguments:
579      * <pre>
580      * ${methodName}
581      * </pre>
582      *
583      * Method with arguments:
584      * <pre>
585      * ${methodName}(${arg1}, ${arg2}, ${arg n})
586      * </pre>
587      *
588      * @param method the encoded method signature
589      * @return the method signature
590      * @see #action(String, MethodSignature, ActionResultExposer)
591      */

592     protected MethodSignature method(String JavaDoc method) {
593         return (MethodSignature)fromStringTo(MethodSignature.class).execute(method);
594     }
595
596     /**
597      * Factory method for a {@link ActionResultExposer result exposer}. A
598      * result exposer is used to expose an action result such as a method return
599      * value or expression evaluation result to the calling flow.
600      * @param resultName the result name
601      * @return the result exposer
602      * @see #action(String, MethodSignature, ActionResultExposer)
603      */

604     protected ActionResultExposer result(String JavaDoc resultName) {
605         return result(resultName, ScopeType.REQUEST);
606     }
607
608     /**
609      * Factory method for a {@link ActionResultExposer result exposer}. A
610      * result exposer is used to expose an action result such as a method return
611      * value or expression evaluation result to the calling flow.
612      * @param resultName the result name
613      * @param resultScope the scope of the result
614      * @return the result exposer
615      * @see #action(String, MethodSignature, ActionResultExposer)
616      */

617     protected ActionResultExposer result(String JavaDoc resultName, ScopeType resultScope) {
618         return new ActionResultExposer(resultName, resultScope);
619     }
620
621     /**
622      * Creates an annotated action decorator that instructs the specified method
623      * be invoked on the multi action when it is executed. Use this when working
624      * with MultiActions to specify the method on the MultiAction to invoke for
625      * a particular usage scenario. Use the {@link #method(String)} factory
626      * method when working with
627      * {@link AbstractBeanInvokingAction bean invoking actions}.
628      * @param methodName the name of the method on the multi action instance
629      * @param multiAction the multi action
630      * @return the annotated action that when invoked sets up a context property
631      * used by the multi action to instruct it with what method to invoke
632      */

633     protected AnnotatedAction invoke(String JavaDoc methodName, MultiAction multiAction) throws FlowArtifactLookupException {
634         AnnotatedAction action = new AnnotatedAction(multiAction);
635         action.setMethod(methodName);
636         return action;
637     }
638
639     /**
640      * Request that the attribute mapper with the specified name be used to map
641      * attributes between a parent flow and a spawning subflow when the subflow
642      * state being constructed is entered.
643      * @param id the id of the attribute mapper that will map attributes between
644      * the flow built by this builder and the subflow
645      * @return the attribute mapper
646      * @throws FlowArtifactLookupException no FlowAttributeMapper implementation
647      * was exported with the specified id
648      */

649     protected FlowAttributeMapper attributeMapper(String JavaDoc id) throws FlowArtifactLookupException {
650         return getFlowServiceLocator().getAttributeMapper(id);
651     }
652
653     /**
654      * Request that the <code>Flow</code> with the specified flowId be spawned
655      * as a subflow when the subflow state being built is entered. Simply
656      * resolves the subflow definition by id and returns it; throwing a
657      * fail-fast exception if it does not exist.
658      * @param id the flow definition id
659      * @return the flow to be used as a subflow, this should be passed to a
660      * addSubflowState call
661      * @throws FlowArtifactLookupException when the flow cannot be resolved
662      */

663     protected Flow flow(String JavaDoc id) throws FlowArtifactLookupException {
664         return getFlowServiceLocator().getSubflow(id);
665     }
666
667     /**
668      * Creates a transition criteria that is used to match a Transition. The
669      * criteria is based on the provided expression string.
670      * @param transitionCriteriaExpression the transition criteria expression,
671      * typically simply a static event identifier (e.g. "submit")
672      * @return the transition criteria
673      */

674     protected TransitionCriteria on(String JavaDoc transitionCriteriaExpression) {
675         return (TransitionCriteria)fromStringTo(TransitionCriteria.class).execute(transitionCriteriaExpression);
676     }
677
678     /**
679      * Creates a target state resolver for the given state id expression.
680      * @param targetStateIdExpression the target state id expression
681      * @return the target state resolver
682      */

683     protected TargetStateResolver to(String JavaDoc targetStateIdExpression) {
684         return (TargetStateResolver)fromStringTo(TargetStateResolver.class).execute(targetStateIdExpression);
685     }
686
687     /**
688      * Creates a new transition.
689      * @param matchingCriteria the criteria that determines when the transition
690      * matches
691      * @param targetStateResolver the resolver of the transition's target state
692      * @return the transition
693      */

694     protected Transition transition(TransitionCriteria matchingCriteria, TargetStateResolver targetStateResolver) {
695         return getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria, null, null);
696     }
697
698     /**
699      * Creates a new transition.
700      * @param matchingCriteria the criteria that determines when the transition
701      * matches
702      * @param targetStateResolver the resolver of the transition's target state
703      * @param executionCriteria the criteria that determines if a matched
704      * transition is allowed to execute
705      * @return the transition
706      */

707     protected Transition transition(TransitionCriteria matchingCriteria, TargetStateResolver targetStateResolver,
708             TransitionCriteria executionCriteria) {
709         return getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria, executionCriteria, null);
710     }
711
712     /**
713      * Creates a new transition.
714      * @param matchingCriteria the criteria that determines when the transition
715      * matches
716      * @param targetStateResolver the resolver of the transition's target state
717      * @param executionCriteria the criteria that determines if a matched
718      * transition is allowed to execute
719      * @param attributes transition attributes
720      * @return the transition
721      */

722     protected Transition transition(TransitionCriteria matchingCriteria, TargetStateResolver targetStateResolver,
723             TransitionCriteria executionCriteria, AttributeMap attributes) {
724         return getFlowArtifactFactory()
725                 .createTransition(targetStateResolver, matchingCriteria, executionCriteria, attributes);
726     }
727
728     /**
729      * Creates a <code>TransitionCriteria</code> that will execute the
730      * specified action when the Transition is executed but before the
731      * transition's target state is entered.
732      * <p>
733      * This criteria will only allow the Transition to complete execution if the
734      * Action completes successfully.
735      * @param action the action to execute after a transition is matched but
736      * before it transitions to its target state
737      * @return the transition execution criteria
738      */

739     protected TransitionCriteria ifReturnedSuccess(Action action) {
740         return new ActionTransitionCriteria(action);
741     }
742
743     /**
744      * Creates the <code>success</code> event id. "Success" indicates that an
745      * action completed successfuly.
746      * @return the event id
747      */

748     protected String JavaDoc success() {
749         return eventFactorySupport.getSuccessEventId();
750     }
751
752     /**
753      * Creates the <code>error</code> event id. "Error" indicates that an
754      * action completed with an error status.
755      * @return the event id
756      */

757     protected String JavaDoc error() {
758         return eventFactorySupport.getErrorEventId();
759     }
760
761     /**
762      * Creates the <code>submit</code> event id. "Submit" indicates the user
763      * submitted a request (form) for processing.
764      * @return the event id
765      */

766     protected String JavaDoc submit() {
767         return "submit";
768     }
769
770     /**
771      * Creates the <code>back</code> event id. "Back" indicates the user wants
772      * to go to the previous step in the flow.
773      * @return the event id
774      */

775     protected String JavaDoc back() {
776         return "back";
777     }
778
779     /**
780      * Creates the <code>cancel</code> event id. "Cancel" indicates the flow
781      * was aborted because the user changed their mind.
782      * @return the event id
783      */

784     protected String JavaDoc cancel() {
785         return "cancel";
786     }
787
788     /**
789      * Creates the <code>finish</code> event id. "Finish" indicates the flow
790      * has finished processing.
791      * @return the event id
792      */

793     protected String JavaDoc finish() {
794         return "finish";
795     }
796
797     /**
798      * Creates the <code>select</code> event id. "Select" indicates an object
799      * was selected for processing or display.
800      * @return the event id
801      */

802     protected String JavaDoc select() {
803         return "select";
804     }
805
806     /**
807      * Creates the <code>edit</code> event id. "Edit" indicates an object was
808      * selected for creation or updating.
809      * @return the event id
810      */

811     protected String JavaDoc edit() {
812         return "edit";
813     }
814
815     /**
816      * Creates the <code>add</code> event id. "Add" indicates a child object
817      * is being added to a parent collection.
818      * @return the event id
819      */

820     protected String JavaDoc add() {
821         return "add";
822     }
823
824     /**
825      * Creates the <code>delete</code> event id. "Delete" indicates a object
826      * is being removed.
827      * @return the event id
828      */

829     protected String JavaDoc delete() {
830         return "delete";
831     }
832
833     /**
834      * Creates the <code>yes</code> event id. "Yes" indicates a true result
835      * was returned.
836      * @return the event id
837      */

838     protected String JavaDoc yes() {
839         return eventFactorySupport.getYesEventId();
840     }
841
842     /**
843      * Creates the <code>no</code> event id. "False" indicates a false result
844      * was returned.
845      * @return the event id
846      */

847     protected String JavaDoc no() {
848         return eventFactorySupport.getNoEventId();
849     }
850
851     /**
852      * Factory method that returns a new, fully configured mapping builder to
853      * assist with building {@link Mapping} objects used by a
854      * {@link FlowAttributeMapper} to map attributes.
855      * @return the mapping builder
856      */

857     protected MappingBuilder mapping() {
858         MappingBuilder mapping = new MappingBuilder(getFlowServiceLocator().getExpressionParser());
859         mapping.setConversionService(getFlowServiceLocator().getConversionService());
860         return mapping;
861     }
862
863     // internal helpers
864

865     private FlowArtifactFactory getFlowArtifactFactory() {
866         return getFlowServiceLocator().getFlowArtifactFactory();
867     }
868
869     private BeanInvokingActionFactory getBeanInvokingActionFactory() {
870         return getFlowServiceLocator().getBeanInvokingActionFactory();
871     }
872 }
Popular Tags