Source Code Cross Referenced for Flow.java in  » Workflow-Engines » spring-webflow-1.0.4 » org » springframework » webflow » engine » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » spring webflow 1.0.4 » org.springframework.webflow.engine 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2004-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.springframework.webflow.engine;
017:
018:        import java.util.Iterator;
019:        import java.util.Set;
020:
021:        import org.apache.commons.logging.Log;
022:        import org.apache.commons.logging.LogFactory;
023:        import org.springframework.binding.mapping.AttributeMapper;
024:        import org.springframework.core.CollectionFactory;
025:        import org.springframework.core.style.StylerUtils;
026:        import org.springframework.core.style.ToStringCreator;
027:        import org.springframework.util.Assert;
028:        import org.springframework.util.StringUtils;
029:        import org.springframework.webflow.core.collection.MutableAttributeMap;
030:        import org.springframework.webflow.definition.FlowDefinition;
031:        import org.springframework.webflow.definition.StateDefinition;
032:        import org.springframework.webflow.execution.FlowExecutionException;
033:        import org.springframework.webflow.execution.RequestContext;
034:        import org.springframework.webflow.execution.ViewSelection;
035:
036:        /**
037:         * A single flow definition. A Flow definition is a reusable, self-contained
038:         * controller module that provides the blue print for a user dialog or
039:         * conversation. Flows typically orchestrate controlled navigations within web
040:         * applications to guide users through fulfillment of a business process/goal
041:         * that takes place over a series of steps, modeled as states.
042:         * <p>
043:         * A simple Flow definition could do nothing more than execute an action and
044:         * display a view all in one request. A more elaborate Flow definition may be
045:         * long-lived and execute across a series of requests, invoking many possible
046:         * paths, actions, and subflows.
047:         * <p>
048:         * Especially in Intranet applications there are often "controlled navigations"
049:         * where the user is not free to do what he or she wants but must follow the
050:         * guidelines provided by the system to complete a process that is transactional
051:         * in nature (the quinessential example would be a 'checkout' flow of a shopping
052:         * cart application). This is a typical use case appropriate to model as a flow.
053:         * <p>
054:         * Structurally a Flow is composed of a set of states. A {@link State} is a
055:         * point in a flow where a behavior is executed; for example, showing a view,
056:         * executing an action, spawning a subflow, or terminating the flow. Different
057:         * types of states execute different behaviors in a polymorphic fashion.
058:         * <p>
059:         * Each {@link TransitionableState} type has one or more transitions that when
060:         * executed move a flow to another state. These transitions define the supported
061:         * paths through the flow.
062:         * <p>
063:         * A state transition is triggered by the occurence of an event. An event is
064:         * something that happens the flow should respond to, for example a user input
065:         * event like ("submit") or an action execution result event like ("success").
066:         * When an event occurs in a state of a Flow that event drives a state
067:         * transition that decides what to do next.
068:         * <p>
069:         * Each Flow has exactly one start state. A start state is simply a marker
070:         * noting the state executions of this Flow definition should start in. The
071:         * first state added to the flow will become the start state by default.
072:         * <p>
073:         * Flow definitions may have one or more flow exception handlers. A
074:         * {@link FlowExecutionExceptionHandler} can execute custom behavior in response
075:         * to a specific exception (or set of exceptions) that occur in a state of one
076:         * of this flow's executions.
077:         * <p>
078:         * Instances of this class are typically built by
079:         * {@link org.springframework.webflow.engine.builder.FlowBuilder}
080:         * implementations but may also be directly instantiated.
081:         * <p>
082:         * This class and the rest of the Spring Web Flow (SWF) engine have been designed
083:         * with minimal dependencies on other libraries. Spring Web Flow is usable in a
084:         * standalone fashion (as well as in the context of other frameworks like Spring
085:         * MVC, Struts, or JSF, for example). The engine system is fully usable outside an
086:         * HTTP servlet environment, for example in portlets, tests, or standalone
087:         * applications. One of the major architectural benefits of Spring Web Flow is
088:         * the ability to design reusable, high-level controller modules that may be
089:         * executed in <i>any</i> environment.
090:         * <p>
091:         * Note: flows are singleton definition objects so they should be thread-safe.
092:         * You can think a flow definition as analagous somewhat to a Java class,
093:         * defining all the behavior of an application module. The core behaviors
094:         * {@link #start(RequestControlContext, MutableAttributeMap) start},
095:         * {@link #onEvent(RequestControlContext) on event}, and
096:         * {@link #end(RequestControlContext, MutableAttributeMap) end} each accept a
097:         * {@link RequestContext request context} that allows for this flow to access
098:         * execution state in a thread safe manner. A flow execution is what models a
099:         * running instance of this flow definition, somewhat analgous to a java object
100:         * that is an instance of a class.
101:         * 
102:         * @see org.springframework.webflow.engine.State
103:         * @see org.springframework.webflow.engine.TransitionableState
104:         * @see org.springframework.webflow.engine.ActionState
105:         * @see org.springframework.webflow.engine.ViewState
106:         * @see org.springframework.webflow.engine.SubflowState
107:         * @see org.springframework.webflow.engine.EndState
108:         * @see org.springframework.webflow.engine.DecisionState
109:         * @see org.springframework.webflow.engine.Transition
110:         * @see org.springframework.webflow.engine.FlowExecutionExceptionHandler
111:         * 
112:         * @author Keith Donald
113:         * @author Erwin Vervaet
114:         * @author Colin Sampaleanu
115:         */
116:        public class Flow extends AnnotatedObject implements  FlowDefinition {
117:
118:            /**
119:             * Logger, can be used in subclasses.
120:             */
121:            protected final Log logger = LogFactory.getLog(getClass());
122:
123:            /**
124:             * An assigned flow identifier uniquely identifying this flow among all
125:             * other flows.
126:             */
127:            private String id;
128:
129:            /**
130:             * The set of state definitions for this flow.
131:             */
132:            private Set states = CollectionFactory.createLinkedSetIfPossible(9);
133:
134:            /**
135:             * The default start state for this flow.
136:             */
137:            private State startState;
138:
139:            /**
140:             * The set of flow variables created by this flow.
141:             */
142:            private Set variables = CollectionFactory
143:                    .createLinkedSetIfPossible(3);
144:
145:            /**
146:             * The mapper to map flow input attributes.
147:             */
148:            private AttributeMapper inputMapper;
149:
150:            /**
151:             * The list of actions to execute when this flow starts.
152:             * <p>
153:             * Start actions should execute with care as during startup a flow session
154:             * has not yet fully initialized and some properties like its "currentState"
155:             * have not yet been set.
156:             */
157:            private ActionList startActionList = new ActionList();
158:
159:            /**
160:             * The set of global transitions that are shared by all states of this flow.
161:             */
162:            private TransitionSet globalTransitionSet = new TransitionSet();
163:
164:            /**
165:             * The list of actions to execute when this flow ends.
166:             */
167:            private ActionList endActionList = new ActionList();
168:
169:            /**
170:             * The mapper to map flow output attributes.
171:             */
172:            private AttributeMapper outputMapper;
173:
174:            /**
175:             * The set of exception handlers for this flow.
176:             */
177:            private FlowExecutionExceptionHandlerSet exceptionHandlerSet = new FlowExecutionExceptionHandlerSet();
178:
179:            /**
180:             * The set of inline flows contained by this flow.
181:             */
182:            private Set inlineFlows = CollectionFactory
183:                    .createLinkedSetIfPossible(3);
184:
185:            /**
186:             * Construct a new flow definition with the given id. The id should be
187:             * unique among all flows.
188:             * @param id the flow identifier
189:             */
190:            public Flow(String id) {
191:                setId(id);
192:            }
193:
194:            // implementing FlowDefinition
195:
196:            public String getId() {
197:                return id;
198:            }
199:
200:            public StateDefinition getStartState() {
201:                if (startState == null) {
202:                    throw new IllegalStateException(
203:                            "No start state has been set for this flow ('"
204:                                    + getId()
205:                                    + "') -- flow builder configuration error?");
206:                }
207:                return startState;
208:            }
209:
210:            public StateDefinition getState(String stateId) {
211:                return getStateInstance(stateId);
212:            }
213:
214:            /**
215:             * Set the unique id of this flow.
216:             */
217:            protected void setId(String id) {
218:                Assert.hasText(id,
219:                        "This flow must have a unique, non-blank identifier");
220:                this .id = id;
221:            }
222:
223:            /**
224:             * Add given state definition to this flow definition. Marked protected, as
225:             * this method is to be called by the (privileged) state definition classes
226:             * themselves during state construction as part of a FlowBuilder invocation.
227:             * @param state the state to add
228:             * @throws IllegalArgumentException when the state cannot be added to the
229:             * flow; for instance if another state shares the same id as the one
230:             * provided or if given state already belongs to another flow
231:             */
232:            protected void add(State state) throws IllegalArgumentException {
233:                if (this  != state.getFlow() && state.getFlow() != null) {
234:                    throw new IllegalArgumentException("State " + state
235:                            + " cannot be added to this flow '" + getId()
236:                            + "' -- it already belongs to a different flow: '"
237:                            + state.getFlow().getId() + "'");
238:                }
239:                if (this .states.contains(state)
240:                        || this .containsState(state.getId())) {
241:                    throw new IllegalArgumentException(
242:                            "This flow '"
243:                                    + getId()
244:                                    + "' already contains a state with id '"
245:                                    + state.getId()
246:                                    + "' -- state ids must be locally unique to the flow definition; "
247:                                    + "existing state-ids of this flow include: "
248:                                    + StylerUtils.style(getStateIds()));
249:                }
250:                boolean firstAdd = states.isEmpty();
251:                states.add(state);
252:                if (firstAdd) {
253:                    setStartState(state);
254:                }
255:            }
256:
257:            /**
258:             * Returns the number of states defined in this flow.
259:             * @return the state count
260:             */
261:            public int getStateCount() {
262:                return states.size();
263:            }
264:
265:            /**
266:             * Is a state with the provided id present in this flow?
267:             * @param stateId the state id
268:             * @return true if yes, false otherwise
269:             */
270:            public boolean containsState(String stateId) {
271:                Iterator it = states.iterator();
272:                while (it.hasNext()) {
273:                    State state = (State) it.next();
274:                    if (state.getId().equals(stateId)) {
275:                        return true;
276:                    }
277:                }
278:                return false;
279:            }
280:
281:            /**
282:             * Set the start state for this flow to the state with the provided
283:             * <code>stateId</code>; a state must exist by the provided
284:             * <code>stateId</code>.
285:             * @param stateId the id of the new start state
286:             * @throws IllegalArgumentException when no state exists with the id you
287:             * provided
288:             */
289:            public void setStartState(String stateId)
290:                    throws IllegalArgumentException {
291:                setStartState(getStateInstance(stateId));
292:            }
293:
294:            /**
295:             * Set the start state for this flow to the state provided; any state may be
296:             * the start state.
297:             * @param state the new start state
298:             * @throws IllegalArgumentException given state has not been added to this
299:             * flow
300:             */
301:            public void setStartState(State state)
302:                    throws IllegalArgumentException {
303:                if (!states.contains(state)) {
304:                    throw new IllegalArgumentException("State '" + state
305:                            + "' is not a state of flow '" + getId() + "'");
306:                }
307:                startState = state;
308:            }
309:
310:            /**
311:             * Return the <code>TransitionableState</code> with given <code>stateId</code>.
312:             * @param stateId id of the state to look up
313:             * @return the transitionable state
314:             * @throws IllegalArgumentException if the identified state cannot be found
315:             * @throws ClassCastException when the identified state is not
316:             * transitionable
317:             */
318:            public TransitionableState getTransitionableState(String stateId)
319:                    throws IllegalArgumentException, ClassCastException {
320:                State state = getStateInstance(stateId);
321:                if (state != null && !(state instanceof  TransitionableState)) {
322:                    throw new ClassCastException("The state '" + stateId
323:                            + "' of flow '" + getId()
324:                            + "' must be transitionable");
325:                }
326:                return (TransitionableState) state;
327:            }
328:
329:            /**
330:             * Lookup the identified state instance of this flow.
331:             * @param stateId the state id
332:             * @return the state
333:             * @throws IllegalArgumentException if the identified state cannot be found
334:             */
335:            public State getStateInstance(String stateId)
336:                    throws IllegalArgumentException {
337:                if (!StringUtils.hasText(stateId)) {
338:                    throw new IllegalArgumentException(
339:                            "The specified stateId is invalid: state identifiers must be non-blank");
340:                }
341:                Iterator it = states.iterator();
342:                while (it.hasNext()) {
343:                    State state = (State) it.next();
344:                    if (state.getId().equals(stateId)) {
345:                        return state;
346:                    }
347:                }
348:                throw new IllegalArgumentException(
349:                        "Cannot find state with id '" + stateId + "' in flow '"
350:                                + getId() + "' -- " + "Known state ids are '"
351:                                + StylerUtils.style(getStateIds()) + "'");
352:            }
353:
354:            /**
355:             * Convenience accessor that returns an ordered array of the String
356:             * <code>ids</code> for the state definitions associated with this flow
357:             * definition.
358:             * @return the state ids
359:             */
360:            public String[] getStateIds() {
361:                String[] stateIds = new String[getStateCount()];
362:                int i = 0;
363:                Iterator it = states.iterator();
364:                while (it.hasNext()) {
365:                    stateIds[i++] = ((State) it.next()).getId();
366:                }
367:                return stateIds;
368:            }
369:
370:            /**
371:             * Adds a flow variable.
372:             * @param variable the variable
373:             */
374:            public void addVariable(FlowVariable variable) {
375:                variables.add(variable);
376:            }
377:
378:            /**
379:             * Adds flow variables.
380:             * @param variables the variables
381:             */
382:            public void addVariables(FlowVariable[] variables) {
383:                if (variables == null) {
384:                    return;
385:                }
386:                for (int i = 0; i < variables.length; i++) {
387:                    addVariable(variables[i]);
388:                }
389:            }
390:
391:            /**
392:             * Returns the flow variables.
393:             */
394:            public FlowVariable[] getVariables() {
395:                return (FlowVariable[]) variables
396:                        .toArray(new FlowVariable[variables.size()]);
397:            }
398:
399:            /**
400:             * Returns the configured flow input mapper, or null if none.
401:             * @return the input mapper
402:             */
403:            public AttributeMapper getInputMapper() {
404:                return inputMapper;
405:            }
406:
407:            /**
408:             * Sets the mapper to map flow input attributes.
409:             * @param inputMapper the input mapper
410:             */
411:            public void setInputMapper(AttributeMapper inputMapper) {
412:                this .inputMapper = inputMapper;
413:            }
414:
415:            /**
416:             * Returns the list of actions executed by this flow when an execution of
417:             * the flow <i>starts</i>. The returned list is mutable.
418:             * @return the start action list
419:             */
420:            public ActionList getStartActionList() {
421:                return startActionList;
422:            }
423:
424:            /**
425:             * Returns the list of actions executed by this flow when an execution of
426:             * the flow <i>ends</i>. The returned list is mutable.
427:             * @return the end action list
428:             */
429:            public ActionList getEndActionList() {
430:                return endActionList;
431:            }
432:
433:            /**
434:             * Returns the configured flow output mapper, or null if none.
435:             * @return the output mapper
436:             */
437:            public AttributeMapper getOutputMapper() {
438:                return outputMapper;
439:            }
440:
441:            /**
442:             * Sets the mapper to map flow output attributes.
443:             * @param outputMapper the output mapper
444:             */
445:            public void setOutputMapper(AttributeMapper outputMapper) {
446:                this .outputMapper = outputMapper;
447:            }
448:
449:            /**
450:             * Returns the set of exception handlers, allowing manipulation of how
451:             * exceptions are handled when thrown during flow execution. Exception
452:             * handlers are invoked when an exception occurs at execution time
453:             * and can execute custom exception handling logic as well as select an
454:             * error view to display. Exception handlers attached at the flow
455:             * level have an opportunity to handle exceptions that aren't handled at the
456:             * state level.
457:             * @return the exception handler set
458:             */
459:            public FlowExecutionExceptionHandlerSet getExceptionHandlerSet() {
460:                return exceptionHandlerSet;
461:            }
462:
463:            /**
464:             * Adds an inline flow to this flow.
465:             * @param flow the inline flow to add
466:             */
467:            public void addInlineFlow(Flow flow) {
468:                inlineFlows.add(flow);
469:            }
470:
471:            /**
472:             * Returns the list of inline flow ids.
473:             * @return a string array of inline flow identifiers
474:             */
475:            public String[] getInlineFlowIds() {
476:                String[] flowIds = new String[getInlineFlowCount()];
477:                int i = 0;
478:                Iterator it = inlineFlows.iterator();
479:                while (it.hasNext()) {
480:                    flowIds[i++] = ((Flow) it.next()).getId();
481:                }
482:                return flowIds;
483:            }
484:
485:            /**
486:             * Returns the list of inline flows.
487:             * @return the list of inline flows
488:             */
489:            public Flow[] getInlineFlows() {
490:                return (Flow[]) inlineFlows
491:                        .toArray(new Flow[inlineFlows.size()]);
492:            }
493:
494:            /**
495:             * Returns the count of registered inline flows.
496:             * @return the count
497:             */
498:            public int getInlineFlowCount() {
499:                return inlineFlows.size();
500:            }
501:
502:            /**
503:             * Tests if this flow contains an in-line flow with the specified id.
504:             * @param id the inline flow id
505:             * @return true if this flow contains a inline flow with that id, false
506:             * otherwise
507:             */
508:            public boolean containsInlineFlow(String id) {
509:                return getInlineFlow(id) != null;
510:            }
511:
512:            /**
513:             * Returns the inline flow with the provided id, or <code>null</code> if
514:             * no such inline flow exists.
515:             * @param id the inline flow id
516:             * @return the inline flow
517:             * @throws IllegalArgumentException when an invalid flow id is provided
518:             */
519:            public Flow getInlineFlow(String id)
520:                    throws IllegalArgumentException {
521:                if (!StringUtils.hasText(id)) {
522:                    throw new IllegalArgumentException(
523:                            "The specified inline flowId is invalid: flow identifiers must be non-blank");
524:                }
525:                Iterator it = inlineFlows.iterator();
526:                while (it.hasNext()) {
527:                    Flow flow = (Flow) it.next();
528:                    if (flow.getId().equals(id)) {
529:                        return flow;
530:                    }
531:                }
532:                return null;
533:            }
534:
535:            /**
536:             * Returns the set of transitions eligible for execution by this flow if no
537:             * state-level transition is matched. The returned set is mutable.
538:             * @return the global transition set
539:             */
540:            public TransitionSet getGlobalTransitionSet() {
541:                return globalTransitionSet;
542:            }
543:
544:            // id based equality
545:
546:            public boolean equals(Object o) {
547:                if (!(o instanceof  Flow)) {
548:                    return false;
549:                }
550:                Flow other = (Flow) o;
551:                return id.equals(other.id);
552:            }
553:
554:            public int hashCode() {
555:                return id.hashCode();
556:            }
557:
558:            // behavioral code, could be overridden in subclasses
559:
560:            /**
561:             * Start a new session for this flow in its start state. This boils down to
562:             * the following:
563:             * <ol>
564:             * <li>Create (setup) all registered flow variables ({@link #addVariable(FlowVariable)})
565:             * in flow scope.</li>
566:             * <li>Map provided input data into the flow execution control context.
567:             * Typically data will be mapped into flow scope using the registered input
568:             * mapper ({@link #setInputMapper(AttributeMapper)}).</li>
569:             * <li>Execute all registered start actions ({@link #getStartActionList()}).</li>
570:             * <li>Enter the configured start state ({@link #setStartState(State)})</li>
571:             * </ol>
572:             * @param context the flow execution control context
573:             * @param input eligible input into the session
574:             * @throws FlowExecutionException when an exception occurs starting the flow
575:             */
576:            public ViewSelection start(RequestControlContext context,
577:                    MutableAttributeMap input) throws FlowExecutionException {
578:                createVariables(context);
579:                if (inputMapper != null) {
580:                    inputMapper.map(input, context, null);
581:                }
582:                startActionList.execute(context);
583:                return startState.enter(context);
584:            }
585:
586:            /**
587:             * Inform this flow definition that an event was signaled in the current
588:             * state of an active flow execution. The signaled event is the last event
589:             * available in given request context ({@link RequestContext#getLastEvent()}).
590:             * @param context the flow execution control context
591:             * @return the selected view
592:             * @throws FlowExecutionException when an exception occurs processing the
593:             * event
594:             */
595:            public ViewSelection onEvent(RequestControlContext context)
596:                    throws FlowExecutionException {
597:                TransitionableState currentState = getCurrentTransitionableState(context);
598:                try {
599:                    return currentState.onEvent(context);
600:                } catch (NoMatchingTransitionException e) {
601:                    // try the flow level transition set for a match
602:                    Transition transition = globalTransitionSet
603:                            .getTransition(context);
604:                    if (transition != null) {
605:                        return transition.execute(currentState, context);
606:                    } else {
607:                        // no matching global transition => let the original exception
608:                        // propagate
609:                        throw e;
610:                    }
611:                }
612:            }
613:
614:            /**
615:             * Inform this flow definition that an execution session of itself has
616:             * ended. As a result, the flow will do the following:
617:             * <ol>
618:             * <li>Execute all registered end actions ({@link #getEndActionList()}).</li>
619:             * <li>Map data available in the flow execution control context into
620:             * provided output map using a registered output mapper
621:             * ({@link #setOutputMapper(AttributeMapper)}).</li>
622:             * </ol>
623:             * @param context the flow execution control context
624:             * @param output initial output produced by the session that is eligible for
625:             * modification by this method
626:             * @throws FlowExecutionException when an exception occurs ending this flow
627:             */
628:            public void end(RequestControlContext context,
629:                    MutableAttributeMap output) throws FlowExecutionException {
630:                endActionList.execute(context);
631:                if (outputMapper != null) {
632:                    outputMapper.map(context, output, null);
633:                }
634:            }
635:
636:            /**
637:             * Handle an exception that occured during an execution of this flow.
638:             * @param exception the exception that occured
639:             * @param context the flow execution control context
640:             * @return the selected error view, or <code>null</code> if no handler
641:             * matched or returned a non-null view selection
642:             */
643:            public ViewSelection handleException(
644:                    FlowExecutionException exception,
645:                    RequestControlContext context)
646:                    throws FlowExecutionException {
647:                return getExceptionHandlerSet().handleException(exception,
648:                        context);
649:            }
650:
651:            // internal helpers
652:
653:            /**
654:             * Create (setup) all known flow variables in flow scope.
655:             */
656:            private void createVariables(RequestContext context) {
657:                Iterator it = variables.iterator();
658:                while (it.hasNext()) {
659:                    FlowVariable variable = (FlowVariable) it.next();
660:                    if (logger.isDebugEnabled()) {
661:                        logger.debug("Creating " + variable);
662:                    }
663:                    variable.create(context);
664:                }
665:            }
666:
667:            /**
668:             * Returns the current state and makes sure it is transitionable.
669:             */
670:            private TransitionableState getCurrentTransitionableState(
671:                    RequestControlContext context) {
672:                State currentState = (State) context.getCurrentState();
673:                if (!(currentState instanceof  TransitionableState)) {
674:                    throw new IllegalStateException(
675:                            "You can only signal events in transitionable states, and state "
676:                                    + context.getCurrentState()
677:                                    + " is not transitionable - programmer error");
678:                }
679:                return (TransitionableState) currentState;
680:            }
681:
682:            public String toString() {
683:                return new ToStringCreator(this ).append("id", id).append(
684:                        "states", states).append("startState", startState)
685:                        .append("variables", variables).append("inputMapper",
686:                                inputMapper).append("startActionList",
687:                                startActionList).append("exceptionHandlerSet",
688:                                exceptionHandlerSet).append(
689:                                "globalTransitionSet", globalTransitionSet)
690:                        .append("endActionList", endActionList).append(
691:                                "outputMapper", outputMapper).append(
692:                                "inlineFlows", inlineFlows).toString();
693:            }
694:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.