KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > webflow > engine > EndState


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;
17
18 import org.springframework.binding.mapping.AttributeMapper;
19 import org.springframework.core.style.ToStringCreator;
20 import org.springframework.util.Assert;
21 import org.springframework.webflow.core.collection.LocalAttributeMap;
22 import org.springframework.webflow.execution.Event;
23 import org.springframework.webflow.execution.FlowExecutionException;
24 import org.springframework.webflow.execution.FlowSession;
25 import org.springframework.webflow.execution.RequestContext;
26 import org.springframework.webflow.execution.ViewSelection;
27
28 /**
29  * A state that ends a flow when entered. More specifically, this state ends the
30  * active flow session of the active flow execution associated with the current
31  * request context.
32  * <p>
33  * If the ended session is the "root flow session" the entire flow execution
34  * ends, signaling the end of a logical conversation.
35  * <p>
36  * If the terminated session was acting as a subflow the flow execution
37  * continues and control is returned to the parent flow session. In that case,
38  * this state returns an ending result event the resuming parent flow is
39  * expected to respond to.
40  * <p>
41  * An end state may optionally be configured with the name of a view to render
42  * when entered. This view will be rendered if the end state terminates the
43  * entire flow execution as a kind of flow ending "confirmation page".
44  * <p>
45  * Note: if no <code>viewName</code> property is specified <b>and</b> this
46  * end state terminates the entire flow execution it is expected that some
47  * action has already written the response (or else a blank response will
48  * result). On the other hand, if no <code>viewName</code> is specified <b>and</b>
49  * this end state relinquishes control back to a parent flow, view selection
50  * responsibility falls on the parent flow.
51  *
52  * @see org.springframework.webflow.engine.ViewSelector
53  * @see org.springframework.webflow.engine.SubflowState
54  *
55  * @author Keith Donald
56  * @author Colin Sampaleanu
57  * @author Erwin Vervaet
58  */

59 public class EndState extends State {
60
61     /**
62      * The optional view selector that will select a view to render if this end
63      * state terminates a root flow session.
64      */

65     private ViewSelector viewSelector = NullViewSelector.INSTANCE;
66
67     /**
68      * Attribute mapper for mapping output attributes exposed by this end state
69      * when it is entered.
70      */

71     private AttributeMapper outputMapper;
72
73     /**
74      * Create a new end state with no associated view.
75      * @param flow the owning flow
76      * @param id the state identifier (must be unique to the flow)
77      * @throws IllegalArgumentException when this state cannot be added to given
78      * flow, e.g. because the id is not unique
79      * @see State#State(Flow, String)
80      * @see #setViewSelector(ViewSelector)
81      * @see #setOutputMapper(AttributeMapper)
82      */

83     public EndState(Flow flow, String JavaDoc id) throws IllegalArgumentException JavaDoc {
84         super(flow, id);
85     }
86
87     /**
88      * Returns the strategy used to select the view to render in this end state
89      * if it terminates a root flow.
90      */

91     public ViewSelector getViewSelector() {
92         return viewSelector;
93     }
94
95     /**
96      * Sets the strategy used to select the view to render when this end state
97      * is entered and terminates a root flow.
98      */

99     public void setViewSelector(ViewSelector viewSelector) {
100         Assert.notNull(viewSelector, "The view selector is required");
101         this.viewSelector = viewSelector;
102     }
103
104     /**
105      * Returns the configured attribute mapper for mapping output attributes
106      * exposed by this end state when it is entered.
107      */

108     public AttributeMapper getOutputMapper() {
109         return outputMapper;
110     }
111
112     /**
113      * Sets the attribute mapper to use for mapping output attributes exposed by
114      * this end state when it is entered.
115      */

116     public void setOutputMapper(AttributeMapper outputMapper) {
117         this.outputMapper = outputMapper;
118     }
119
120     /**
121      * Specialization of State's <code>doEnter</code> template method that
122      * executes behaviour specific to this state type in polymorphic fashion.
123      * <p>
124      * This implementation pops the top (active) flow session off the execution
125      * stack, ending it, and resumes control in the parent flow (if neccessary).
126      * If the ended session is the root flow, a {@link ViewSelection} is
127      * returned.
128      * @param context the control context for the currently executing flow, used
129      * by this state to manipulate the flow execution
130      * @return a view selection signaling that control should be returned to the
131      * client and a view rendered
132      * @throws FlowExecutionException if an exception occurs in this state
133      */

134     protected ViewSelection doEnter(RequestControlContext context) throws FlowExecutionException {
135         FlowSession activeSession = context.getFlowExecutionContext().getActiveSession();
136         if (activeSession.isRoot()) {
137             // entire flow execution is ending, return ending view if applicable
138
ViewSelection selectedView = viewSelector.makeEntrySelection(context);
139             context.endActiveFlowSession(createSessionOutput(context));
140             return selectedView;
141         }
142         else {
143             // there is a parent flow that will resume (this flow is a subflow)
144
LocalAttributeMap sessionOutput = createSessionOutput(context);
145             context.endActiveFlowSession(sessionOutput);
146             return context.signalEvent(new Event(this, getId(), sessionOutput));
147         }
148     }
149
150     /**
151      * Returns the subflow output map. This will invoke the output mapper (if any)
152      * to map data available in the flow execution request context into a newly
153      * creaed empty map.
154      */

155     protected LocalAttributeMap createSessionOutput(RequestContext context) {
156         LocalAttributeMap outputMap = new LocalAttributeMap();
157         if (outputMapper != null) {
158             outputMapper.map(context, outputMap, null);
159         }
160         return outputMap;
161     }
162
163     protected void appendToString(ToStringCreator creator) {
164         creator.append("viewSelector", viewSelector).append("outputMapper", outputMapper);
165     }
166 }
Popular Tags