Source Code Cross Referenced for FlowExecutionImpl.java in  » Workflow-Engines » spring-webflow-1.0.4 » org » springframework » webflow » engine » impl » 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.impl 
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.impl;
017:
018:        import java.io.Externalizable;
019:        import java.io.IOException;
020:        import java.io.ObjectInput;
021:        import java.io.ObjectOutput;
022:        import java.util.LinkedList;
023:        import java.util.ListIterator;
024:
025:        import org.apache.commons.logging.Log;
026:        import org.apache.commons.logging.LogFactory;
027:        import org.springframework.core.style.ToStringCreator;
028:        import org.springframework.util.Assert;
029:        import org.springframework.webflow.context.ExternalContext;
030:        import org.springframework.webflow.core.collection.AttributeMap;
031:        import org.springframework.webflow.core.collection.CollectionUtils;
032:        import org.springframework.webflow.core.collection.LocalAttributeMap;
033:        import org.springframework.webflow.core.collection.MutableAttributeMap;
034:        import org.springframework.webflow.definition.FlowDefinition;
035:        import org.springframework.webflow.engine.Flow;
036:        import org.springframework.webflow.engine.RequestControlContext;
037:        import org.springframework.webflow.engine.State;
038:        import org.springframework.webflow.engine.ViewState;
039:        import org.springframework.webflow.execution.Event;
040:        import org.springframework.webflow.execution.FlowExecution;
041:        import org.springframework.webflow.execution.FlowExecutionException;
042:        import org.springframework.webflow.execution.FlowExecutionListener;
043:        import org.springframework.webflow.execution.FlowSession;
044:        import org.springframework.webflow.execution.FlowSessionStatus;
045:        import org.springframework.webflow.execution.ViewSelection;
046:
047:        /**
048:         * Default implementation of FlowExecution that uses a stack-based data
049:         * structure to manage spawned flow sessions. This class is closely coupled with
050:         * package-private <code>FlowSessionImpl</code> and
051:         * <code>RequestControlContextImpl</code>. The three classes work together to
052:         * form a complete flow execution implementation based on a finite state
053:         * machine.
054:         * <p>
055:         * This implementation of FlowExecution is serializable so it can be safely
056:         * stored in an HTTP session or other persistent store such as a file, database,
057:         * or client-side form field. Once deserialized, the
058:         * {@link FlowExecutionImplStateRestorer} strategy is expected to be used to
059:         * restore the execution to a usable state.
060:         *
061:         * @see FlowExecutionImplFactory
062:         * @see FlowExecutionImplStateRestorer
063:         *
064:         * @author Keith Donald
065:         * @author Erwin Vervaet
066:         * @author Ben Hale
067:         */
068:        public class FlowExecutionImpl implements  FlowExecution, Externalizable {
069:
070:            private static final Log logger = LogFactory
071:                    .getLog(FlowExecutionImpl.class);
072:
073:            /**
074:             * The execution's root flow; the top level flow that acts as the starting
075:             * point for this flow execution.
076:             * <p>
077:             * Transient to support restoration by the {@link FlowExecutionImplStateRestorer}.
078:             */
079:            private transient Flow flow;
080:
081:            /**
082:             * The stack of active, currently executing flow sessions. As subflows are
083:             * spawned, they are pushed onto the stack. As they end, they are popped off
084:             * the stack.
085:             */
086:            private LinkedList flowSessions;
087:
088:            /**
089:             * A thread-safe listener list, holding listeners monitoring the lifecycle
090:             * of this flow execution.
091:             * <p>
092:             * Transient to support restoration by the {@link FlowExecutionImplStateRestorer}.
093:             */
094:            private transient FlowExecutionListeners listeners;
095:
096:            /**
097:             * A data structure for attributes shared by all flow sessions.
098:             * <p>
099:             * Transient to support restoration by the {@link FlowExecutionImplStateRestorer}.
100:             */
101:            private transient MutableAttributeMap conversationScope;
102:
103:            /**
104:             * A data structure for runtime system execution attributes.
105:             * <p>
106:             * Transient to support restoration by the {@link FlowExecutionImplStateRestorer}.
107:             */
108:            private transient AttributeMap attributes;
109:
110:            /**
111:             * Set so the transient {@link #flow} field can be restored by the
112:             * {@link FlowExecutionImplStateRestorer}.
113:             */
114:            private String flowId;
115:
116:            /**
117:             * Default constructor required for externalizable serialization. Should NOT
118:             * be called programmatically.
119:             */
120:            public FlowExecutionImpl() {
121:            }
122:
123:            /**
124:             * Create a new flow execution executing the provided flow. This constructor
125:             * is mainly used for testing.
126:             * @param flow the root flow of this flow execution
127:             */
128:            public FlowExecutionImpl(Flow flow) {
129:                this (flow, new FlowExecutionListener[0], null);
130:            }
131:
132:            /**
133:             * Create a new flow execution executing the provided flow.
134:             * @param flow the root flow of this flow execution
135:             * @param listeners the listeners interested in flow execution lifecycle
136:             * events
137:             * @param attributes flow execution system attributes
138:             */
139:            public FlowExecutionImpl(Flow flow,
140:                    FlowExecutionListener[] listeners, AttributeMap attributes) {
141:                setFlow(flow);
142:                this .flowSessions = new LinkedList();
143:                this .listeners = new FlowExecutionListeners(listeners);
144:                this .attributes = (attributes != null ? attributes
145:                        : CollectionUtils.EMPTY_ATTRIBUTE_MAP);
146:                this .conversationScope = new LocalAttributeMap();
147:                if (logger.isDebugEnabled()) {
148:                    logger.debug("Created new execution of flow '"
149:                            + flow.getId() + "'");
150:                }
151:            }
152:
153:            public String getCaption() {
154:                return "execution of '" + flowId + "'";
155:            }
156:
157:            // implementing FlowExecutionContext
158:
159:            public FlowDefinition getDefinition() {
160:                return flow;
161:            }
162:
163:            public boolean isActive() {
164:                return !flowSessions.isEmpty();
165:            }
166:
167:            public FlowSession getActiveSession() {
168:                return getActiveSessionInternal();
169:            }
170:
171:            public MutableAttributeMap getConversationScope() {
172:                return conversationScope;
173:            }
174:
175:            public AttributeMap getAttributes() {
176:                return attributes;
177:            }
178:
179:            // methods implementing FlowExecution
180:
181:            public ViewSelection start(MutableAttributeMap input,
182:                    ExternalContext externalContext)
183:                    throws FlowExecutionException {
184:                Assert
185:                        .state(!isActive(),
186:                                "This flow is already executing -- you cannot call 'start()' more than once");
187:                if (logger.isDebugEnabled()) {
188:                    logger.debug("Starting execution with input '" + input
189:                            + "'");
190:                }
191:                RequestControlContext context = createControlContext(externalContext);
192:                getListeners().fireRequestSubmitted(context);
193:                try {
194:                    try {
195:                        // launch a flow session for the root flow
196:                        ViewSelection selectedView = context.start(flow, input);
197:                        return pause(context, selectedView);
198:                    } catch (FlowExecutionException e) {
199:                        return pause(context, handleException(e, context));
200:                    } catch (Exception e) {
201:                        return pause(context, handleException(wrapException(e),
202:                                context));
203:                    }
204:                } finally {
205:                    getListeners().fireRequestProcessed(context);
206:                }
207:            }
208:
209:            public ViewSelection signalEvent(String eventId,
210:                    ExternalContext externalContext)
211:                    throws FlowExecutionException {
212:                assertActive();
213:                if (logger.isDebugEnabled()) {
214:                    logger.debug("Resuming execution on user event '" + eventId
215:                            + "'");
216:                }
217:                RequestControlContext context = createControlContext(externalContext);
218:                context.getFlashScope().clear();
219:                getListeners().fireRequestSubmitted(context);
220:                try {
221:                    try {
222:                        resume(context);
223:                        Event event = new Event(externalContext, eventId,
224:                                externalContext.getRequestParameterMap()
225:                                        .asAttributeMap());
226:                        ViewSelection selectedView = context.signalEvent(event);
227:                        return pause(context, selectedView);
228:                    } catch (FlowExecutionException e) {
229:                        return pause(context, handleException(e, context));
230:                    } catch (Exception e) {
231:                        return pause(context, handleException(wrapException(e),
232:                                context));
233:                    }
234:                } finally {
235:                    getListeners().fireRequestProcessed(context);
236:                }
237:            }
238:
239:            public ViewSelection refresh(ExternalContext externalContext)
240:                    throws FlowExecutionException {
241:                assertActive();
242:                if (logger.isDebugEnabled()) {
243:                    logger.debug("Resuming execution for refresh");
244:                }
245:                RequestControlContext context = createControlContext(externalContext);
246:                getListeners().fireRequestSubmitted(context);
247:                try {
248:                    try {
249:                        resume(context);
250:                        State currentState = getCurrentState();
251:                        if (!(currentState instanceof  ViewState)) {
252:                            throw new IllegalStateException(
253:                                    "Current state is not a view state - cannot refresh; "
254:                                            + "perhaps an unhandled exception occured in another state?");
255:                        }
256:                        ViewSelection selectedView = ((ViewState) currentState)
257:                                .refresh(context);
258:                        return pause(context, selectedView);
259:                    } catch (FlowExecutionException e) {
260:                        return pause(context, handleException(e, context));
261:                    } catch (Exception e) {
262:                        return pause(context, handleException(wrapException(e),
263:                                context));
264:                    }
265:                } finally {
266:                    getListeners().fireRequestProcessed(context);
267:                }
268:            }
269:
270:            /**
271:             * Returns the listener list.
272:             * @return the attached execution listeners.
273:             */
274:            FlowExecutionListeners getListeners() {
275:                return listeners;
276:            }
277:
278:            /**
279:             * Resume this flow execution.
280:             * @param context the state request context
281:             */
282:            protected void resume(RequestControlContext context) {
283:                getActiveSessionInternal().setStatus(FlowSessionStatus.ACTIVE);
284:                getListeners().fireResumed(context);
285:            }
286:
287:            /**
288:             * Pause this flow execution.
289:             * @param context the request control context
290:             * @param selectedView the initial selected view to render
291:             * @return the selected view to render
292:             */
293:            protected ViewSelection pause(RequestControlContext context,
294:                    ViewSelection selectedView) {
295:                if (!isActive()) {
296:                    // view selected by an end state
297:                    return selectedView;
298:                }
299:                getActiveSessionInternal().setStatus(FlowSessionStatus.PAUSED);
300:                getListeners().firePaused(context, selectedView);
301:                if (logger.isDebugEnabled()) {
302:                    if (selectedView != null) {
303:                        logger.debug("Paused to render " + selectedView
304:                                + " and wait for user input");
305:                    } else {
306:                        logger.debug("Paused to wait for user input");
307:                    }
308:                }
309:                return selectedView;
310:            }
311:
312:            /**
313:             * Handles an exception that occured performing an operation on this flow
314:             * execution. First trys the set of exception handlers associated with the
315:             * offending state, then the handlers at the flow level.
316:             * @param exception the exception that occured
317:             * @param context the request control context the exception occured in
318:             * @return the selected error view, never null
319:             * @throws FlowExecutionException rethrows the exception if it was not handled
320:             * at the state or flow level
321:             */
322:            protected ViewSelection handleException(
323:                    FlowExecutionException exception,
324:                    RequestControlContext context)
325:                    throws FlowExecutionException {
326:                getListeners().fireExceptionThrown(context, exception);
327:                if (logger.isDebugEnabled()) {
328:                    logger.debug("Attempting to handle [" + exception + "]");
329:                }
330:                try {
331:                    // the state could be null if the flow was attempting a start operation
332:                    ViewSelection selectedView = tryStateHandlers(exception,
333:                            context);
334:                    if (selectedView != null) {
335:                        if (logger.isDebugEnabled()) {
336:                            logger.debug("State '" + exception.getStateId()
337:                                    + "' handled exception");
338:                        }
339:                        return selectedView;
340:                    }
341:                    selectedView = tryFlowHandlers(exception, context);
342:                    if (selectedView != null) {
343:                        if (logger.isDebugEnabled()) {
344:                            logger.debug("Flow '" + getCurrentFlow().getId()
345:                                    + "' handled exception");
346:                        }
347:                        return selectedView;
348:                    }
349:                } catch (FlowExecutionException newException) {
350:                    // exception handling resulted in a new FlowExecutionException, try to handle it
351:                    return handleException(newException, context);
352:                } catch (Exception e) {
353:                    // a lower-level exception occured, wrap it in a flow execution exception and try to handle it
354:                    return handleException(wrapException(e), context);
355:                }
356:                if (logger.isDebugEnabled()) {
357:                    logger
358:                            .debug("Rethrowing unhandled flow execution exception");
359:                }
360:                throw exception;
361:            }
362:
363:            /**
364:             * Try to handle given exception using execution exception handlers registered
365:             * at the state level. Returns null if no handler handled the exception.
366:             */
367:            private ViewSelection tryStateHandlers(
368:                    FlowExecutionException exception,
369:                    RequestControlContext context) {
370:                if (isActive() && exception.getStateId() != null) {
371:                    return getActiveFlow().getStateInstance(
372:                            exception.getStateId()).handleException(exception,
373:                            context);
374:                } else {
375:                    return null;
376:                }
377:            }
378:
379:            /**
380:             * Try to handle given exception using execution exception handlers registered
381:             * at the flow level. Returns null if no handler handled the exception.
382:             */
383:            private ViewSelection tryFlowHandlers(
384:                    FlowExecutionException exception,
385:                    RequestControlContext context) {
386:                return getCurrentFlow().handleException(exception, context);
387:            }
388:
389:            // internal helpers
390:
391:            /**
392:             * Create a flow execution control context.
393:             * @param externalContext the external context triggering this request
394:             */
395:            protected RequestControlContext createControlContext(
396:                    ExternalContext externalContext) {
397:                return new RequestControlContextImpl(this , externalContext);
398:            }
399:
400:            /**
401:             * Returns the currently active flow session.
402:             * @throws IllegalStateException this execution is not active
403:             */
404:            FlowSessionImpl getActiveSessionInternal()
405:                    throws IllegalStateException {
406:                assertActive();
407:                return (FlowSessionImpl) flowSessions.getLast();
408:            }
409:
410:            /**
411:             * Set the state that is currently active in this flow execution.
412:             * @param newState the new current state
413:             */
414:            protected void setCurrentState(State newState) {
415:                getActiveSessionInternal().setState(newState);
416:            }
417:
418:            /**
419:             * Activate a new <code>FlowSession</code> for the flow definition.
420:             * Creates the new flow session and pushes it onto the stack.
421:             * @param flow the flow definition
422:             * @return the new flow session
423:             */
424:            protected FlowSession activateSession(Flow flow) {
425:                FlowSessionImpl session;
426:                if (!flowSessions.isEmpty()) {
427:                    FlowSessionImpl parent = getActiveSessionInternal();
428:                    parent.setStatus(FlowSessionStatus.SUSPENDED);
429:                    session = createFlowSession(flow, parent);
430:                } else {
431:                    session = createFlowSession(flow, null);
432:                }
433:                flowSessions.add(session);
434:                session.setStatus(FlowSessionStatus.STARTING);
435:                if (logger.isDebugEnabled()) {
436:                    logger.debug("Starting " + session);
437:                }
438:                return session;
439:            }
440:
441:            /**
442:             * Create a new flow session object. Subclasses can override this to return
443:             * a special implementation if required.
444:             * @param flow the flow that should be associated with the flow session
445:             * @param parent the flow session that should be the parent of the newly
446:             * created flow session (may be null)
447:             * @return the newly created flow session
448:             */
449:            FlowSessionImpl createFlowSession(Flow flow, FlowSessionImpl parent) {
450:                return new FlowSessionImpl(flow, parent);
451:            }
452:
453:            /**
454:             * End the active flow session, popping it of the stack.
455:             * @return the ended session
456:             */
457:            public FlowSession endActiveFlowSession() {
458:                FlowSessionImpl endingSession = (FlowSessionImpl) flowSessions
459:                        .removeLast();
460:                endingSession.setStatus(FlowSessionStatus.ENDED);
461:                if (!flowSessions.isEmpty()) {
462:                    if (logger.isDebugEnabled()) {
463:                        logger.debug("Resuming session '"
464:                                + getActiveSessionInternal().getDefinition()
465:                                        .getId() + "' in state '"
466:                                + getActiveSessionInternal().getState().getId()
467:                                + "'");
468:                    }
469:                    getActiveSessionInternal().setStatus(
470:                            FlowSessionStatus.ACTIVE);
471:                } else {
472:                    if (logger.isDebugEnabled()) {
473:                        logger
474:                                .debug("[Ended] - this execution is now inactive");
475:                    }
476:                }
477:                return endingSession;
478:            }
479:
480:            /**
481:             * Make sure that this flow execution is active and throw an exception if it's
482:             * not.
483:             */
484:            private void assertActive() throws IllegalStateException {
485:                if (!isActive()) {
486:                    throw new IllegalStateException(
487:                            "This flow execution is not active, it has either ended or has never been started.");
488:                }
489:            }
490:
491:            /**
492:             * Returns the "current flow": which is the active flow if this execution is active, else the top-level flow definition.
493:             */
494:            private Flow getCurrentFlow() {
495:                return isActive() ? getActiveFlow() : this .flow;
496:            }
497:
498:            /**
499:             * Returns the id of the "current" state: a valid state identifier if the flow is active and in a state; null if the flow
500:             * is not active or has not yet entered a state.
501:             */
502:            private String getCurrentStateId() {
503:                if (isActive()) {
504:                    State state = getCurrentState();
505:                    if (state != null) {
506:                        return state.getId();
507:                    }
508:                }
509:                return null;
510:            }
511:
512:            /**
513:             * Returns the currently active flow.
514:             */
515:            private Flow getActiveFlow() throws IllegalStateException {
516:                return (Flow) getActiveSessionInternal().getDefinition();
517:            }
518:
519:            /**
520:             * Returns the current state of this flow execution.
521:             */
522:            private State getCurrentState() throws IllegalStateException {
523:                return (State) getActiveSessionInternal().getState();
524:            }
525:
526:            /**
527:             * Wrap given exception in a FlowExecutionException.
528:             */
529:            private FlowExecutionException wrapException(Exception e) {
530:                String flowId = getCurrentFlow().getId();
531:                String stateId = getCurrentStateId();
532:                return new FlowExecutionException(flowId, stateId,
533:                        "Exception thrown in state '" + stateId + "' of flow '"
534:                                + flowId + "'", e);
535:            }
536:
537:            // custom serialization (implementation of Externalizable for optimized
538:            // storage)
539:
540:            public void readExternal(ObjectInput in) throws IOException,
541:                    ClassNotFoundException {
542:                flowId = (String) in.readObject();
543:                flowSessions = (LinkedList) in.readObject();
544:            }
545:
546:            public void writeExternal(ObjectOutput out) throws IOException {
547:                out.writeObject(flowId);
548:                out.writeObject(flowSessions);
549:            }
550:
551:            public String toString() {
552:                if (!isActive()) {
553:                    return "[Inactive " + getCaption() + "]";
554:                } else {
555:                    if (flow != null) {
556:                        return new ToStringCreator(this ).append("flow",
557:                                flow.getId()).append("flowSessions",
558:                                flowSessions).toString();
559:                    } else {
560:                        return "[Unhydrated " + getCaption() + "]";
561:                    }
562:                }
563:            }
564:
565:            // package private setters for restoring transient state
566:            // used by FlowExecutionImplStateRestorer
567:
568:            /**
569:             * Restore the flow definition of this flow execution.
570:             */
571:            void setFlow(Flow flow) {
572:                Assert.notNull(flow, "The root flow definition is required");
573:                this .flow = flow;
574:                this .flowId = flow.getId();
575:            }
576:
577:            /**
578:             * Restore the listeners of this flow execution.
579:             */
580:            void setListeners(FlowExecutionListeners listeners) {
581:                Assert.notNull(listeners,
582:                        "The execution listener list is required");
583:                this .listeners = listeners;
584:            }
585:
586:            /**
587:             * Restore the execution attributes of this flow execution.
588:             */
589:            void setAttributes(AttributeMap attributes) {
590:                Assert.notNull(conversationScope,
591:                        "The execution attribute map is required");
592:                this .attributes = attributes;
593:            }
594:
595:            /**
596:             * Restore conversation scope for this flow execution.
597:             */
598:            void setConversationScope(MutableAttributeMap conversationScope) {
599:                Assert.notNull(conversationScope,
600:                        "The conversation scope map is required");
601:                this .conversationScope = conversationScope;
602:            }
603:
604:            /**
605:             * Returns the flow definition id of this flow execution.
606:             */
607:            String getFlowId() {
608:                return flowId;
609:            }
610:
611:            /**
612:             * Returns the list of flow session maintained by this flow execution.
613:             */
614:            LinkedList getFlowSessions() {
615:                return flowSessions;
616:            }
617:
618:            /**
619:             * Are there any flow sessions in this flow execution?
620:             */
621:            boolean hasSessions() {
622:                return !flowSessions.isEmpty();
623:            }
624:
625:            /**
626:             * Are there any sessions for sub flows in this flow execution?
627:             */
628:            boolean hasSubflowSessions() {
629:                return flowSessions.size() > 1;
630:            }
631:
632:            /**
633:             * Returns the flow session for the root flow of this flow execution.
634:             */
635:            FlowSessionImpl getRootSession() {
636:                return (FlowSessionImpl) flowSessions.getFirst();
637:            }
638:
639:            /**
640:             * Returns an iterator looping over the subflow sessions
641:             * in this flow execution.
642:             */
643:            ListIterator getSubflowSessionIterator() {
644:                return flowSessions.listIterator(1);
645:            }
646:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.