1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.myfaces.orchestra.flow;
20
21 import java.util.Map;
22
23 import javax.faces.component.UIViewRoot;
24
25 import org.apache.myfaces.orchestra.flow.config.FlowAccept;
26 import org.apache.myfaces.orchestra.flow.config.FlowCall;
27
28 /**
29 * Holds information about a specific call to a specific flow.
30 * <p>
31 * A new instance of this type is created for each call to a flow,
32 * and is stored in the ConversationContext created for that flow.
33 */
34 public class FlowInfo
35 {
36 public static final int STATE_ACTIVE = 1;
37 public static final int STATE_COMMITTED = 2;
38 public static final int STATE_CANCELLED = 3;
39
40 private int state = STATE_ACTIVE;
41 private boolean isModalFlow;
42
43 // caller info
44 private String callerOutcome;
45 private String callerViewId;
46 private UIViewRoot callerViewRoot;
47 private FlowCall flowCall;
48
49 // values being passed from caller to callee
50 private Map<String,Object> argsIn;
51
52 // values being returned from callee to caller
53 private Map<String,Object> argsOut;
54
55 // Javascript to render when closing a flow that was run as
56 // a modal dialog.
57 private String onExitScript;
58
59 // callee info
60 private String flowViewId;
61 private String flowPath;
62 private FlowAccept flowAccept;
63
64 /**
65 * Constructor.
66 * <p>
67 * This creates just a partially-initialised FlowInfo object, as it defines only
68 * information about the caller. It is expected that very soon after this is
69 * created a call to setAcceptInfo will be made to add information about the
70 * called flow.
71 *
72 * @param callerViewId contains the viewId of the view that started the call. This
73 * value must not be null.
74 *
75 * @param callerViewRoot contains the view tree for the view that started the call.
76 * This is optional; when not null then this view state will be restored on return
77 * from the flow. In particular, this allows data entered by the user into input
78 * components to be restored when the flow returns (assumes that the flow call is
79 * triggered by an immediate command component). When this is null, then on return
80 * to the caller a new view tree will be created. The viewRoot should normally not
81 * be saved (this avoids wasting memory). It does need to be saved, however, when
82 * the component triggering the flow has immediate=true and the caller wants
83 * incomplete data to be preserved on return. It may also need to be preserved in
84 * certain scenarios such as when code stores stateful data into the view tree (eg
85 * when the t:saveState tag is used or when JSF2.0 view-scope beans are used).
86 *
87 * @param flowCall is the configuration object that describes the caller of a flow.
88 *
89 * @param argsIn is the set of parameter values being passed to the called flow. See
90 * FlowCall.readSendParams().
91 */
92 public FlowInfo(
93 String callerOutcome,
94 String callerViewId,
95 UIViewRoot callerViewRoot,
96 FlowCall flowCall,
97 Map<String, Object> argsIn)
98 {
99 this.callerOutcome = callerOutcome;
100 this.callerViewId = callerViewId;
101 this.callerViewRoot = callerViewRoot;
102 this.flowCall = flowCall;
103 this.argsIn = argsIn;
104
105 // TODO: save the serialized view tree, not just a ref to the viewroot
106 // TODO: determine whether to save the view tree or not (see comments on callerViewRoot property)
107 }
108
109 /**
110 * Return the outcome string that triggered this flowcall.
111 */
112 public String getCallerOutcome()
113 {
114 return callerOutcome;
115 }
116
117 /**
118 * Return the viewId of the page that initiated the call to a flow (never null).
119 */
120 public String getCallerViewId()
121 {
122 return callerViewId;
123 }
124
125 /**
126 * Return the view root of the page that initiated the call to a flow (optional,
127 * may be null).
128 */
129 public UIViewRoot getCallerViewRoot()
130 {
131 return callerViewRoot;
132 }
133
134 /**
135 * Return metadata about the caller of the flow.
136 */
137 public FlowCall getFlowCall()
138 {
139 return flowCall;
140 }
141
142 /**
143 * Get the (name,value) parameters that the caller is passing to the
144 * called flow.
145 * <p>
146 * These objects are then "accepted" into the called flow when the flow
147 * first starts. These objects are also used if the flow performs a
148 * "restart"; note however that if any of these objects are mutable then
149 * on restart the modified versions are passed to the called flow.
150 */
151 public Map<String,Object> getArgsIn()
152 {
153 return argsIn;
154 }
155
156 /**
157 * Get the (name,value) parameters that the caller is returning to the
158 * called flow.
159 * <p>
160 * These objects are then "accepted" into the calling flow when the
161 * caller's view is restored. The return value is null until the
162 * flow has committed.
163 */
164 public Map<String, Object> getArgsOut()
165 {
166 return argsOut;
167 }
168
169 /** Set to true to specify that the flow this object represents is "modal". */
170 public void setModalFlow(boolean state)
171 {
172 this.isModalFlow = state;
173 }
174
175 /**
176 * Returns true when this flow represents a modal flow.
177 */
178 public boolean isModalFlow()
179 {
180 return isModalFlow;
181 }
182
183 /**
184 * Finish initialising this object by adding information about the called flow.
185 * <p>
186 * It is assumed that the FlowAccept has been checked for compatibility against
187 * the FlowCall object.
188 * <p>
189 * @param entryViewId
190 * @param flowPath
191 * @param flowAccept
192 */
193 public void setAcceptInfo(String flowViewId, String flowPath, FlowAccept flowAccept)
194 {
195 this.flowViewId = flowViewId;
196 this.flowPath = flowPath;
197 this.flowAccept = flowAccept;
198 }
199
200 /**
201 * Return the viewId of the entry page of the flow.
202 */
203 public String getFlowViewId()
204 {
205 return flowViewId;
206 }
207
208 /**
209 * Return the path prefix which is expected to be present on the viewId of every
210 * page that "belongs" to this flow.
211 * <p>
212 * A viewId which does not start with the flowPath is not part of the current flow,
213 * and so immediately triggers cancellation of the flow.
214 */
215 public String getFlowPath()
216 {
217 return flowPath;
218 }
219
220 /**
221 * Return metadata about the called flow.
222 */
223 public FlowAccept getFlowAccept()
224 {
225 return flowAccept;
226 }
227
228 public String getOnExitScript()
229 {
230 return onExitScript;
231 }
232
233 public void setOnExitScript(String script)
234 {
235 onExitScript = script;
236 }
237
238
239 public int getState()
240 {
241 return state;
242 }
243
244 public void commit(Map<String, Object> argsOut)
245 {
246 this.argsOut = argsOut;
247 state = STATE_COMMITTED;
248 }
249
250 public void cancel()
251 {
252 state = STATE_CANCELLED;
253 }
254
255 public boolean isComplete()
256 {
257 return (state == STATE_CANCELLED || state == STATE_COMMITTED);
258 }
259 }