1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.flow;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import javax.el.MethodExpression;
29 import javax.faces.application.NavigationCase;
30 import javax.faces.context.FacesContext;
31 import javax.faces.flow.Flow;
32 import javax.faces.flow.FlowCallNode;
33 import javax.faces.flow.FlowNode;
34 import javax.faces.flow.MethodCallNode;
35 import javax.faces.flow.Parameter;
36 import javax.faces.flow.ReturnNode;
37 import javax.faces.flow.SwitchNode;
38 import javax.faces.flow.ViewNode;
39 import javax.faces.lifecycle.ClientWindow;
40
41
42
43
44
45
46 public class FlowImpl extends Flow implements Freezable
47 {
48 private MethodExpression _initializer;
49 private MethodExpression _finalizer;
50 private String _startNodeId;
51 private String _id;
52 private String _definingDocumentId;
53
54 private Map<String, FlowNode> _flowNodeMap;
55
56
57
58 private Map<String, Parameter> _inboundParametersMap;
59 private Map<String, FlowCallNode> _flowCallsMap;
60 private List<MethodCallNode> _methodCallsList;
61 private Map<String, ReturnNode> _returnsMap;
62 private Map<String, SwitchNode> _switchesMap;
63 private List<ViewNode> _viewsList;
64
65
66
67 private Map<String, Parameter> _unmodifiableInboundParametersMap;
68 private Map<String, FlowCallNode> _unmodifiableFlowCallsMap;
69 private List<MethodCallNode> _unmodifiableMethodCallsList;
70 private Map<String, ReturnNode> _unmodifiableReturnsMap;
71 private Map<String, SwitchNode> _unmodifiableSwitchesMap;
72 private List<ViewNode> _unmodifiableViewsList;
73
74 private Map<String, Set<NavigationCase>> _navigationCases;
75 private Map<String, Set<NavigationCase>> _unmodifiableNavigationCases;
76
77
78
79
80 private boolean _initialized;
81
82 public FlowImpl()
83 {
84 _flowNodeMap = new HashMap<String, FlowNode>();
85 _inboundParametersMap = new HashMap<String, Parameter>();
86 _flowCallsMap = new HashMap<String, FlowCallNode>();
87 _methodCallsList = new ArrayList<MethodCallNode>();
88 _returnsMap = new HashMap<String, ReturnNode>();
89 _switchesMap = new HashMap<String, SwitchNode>();
90 _viewsList = new ArrayList<ViewNode>();
91 _navigationCases = new HashMap<String, Set<NavigationCase>>();
92
93
94
95
96 _unmodifiableInboundParametersMap = Collections.unmodifiableMap(_inboundParametersMap);
97 _unmodifiableFlowCallsMap = Collections.unmodifiableMap(_flowCallsMap);
98 _unmodifiableMethodCallsList = Collections.unmodifiableList(_methodCallsList);
99 _unmodifiableReturnsMap = Collections.unmodifiableMap(_returnsMap);
100 _unmodifiableSwitchesMap = Collections.unmodifiableMap(_switchesMap);
101 _unmodifiableViewsList = Collections.unmodifiableList(_viewsList);
102
103 _unmodifiableNavigationCases = Collections.unmodifiableMap(_navigationCases);
104 }
105
106 public void freeze()
107 {
108
109
110 _initialized = true;
111
112 for (Map.Entry<String, Parameter> entry : _inboundParametersMap.entrySet())
113 {
114 if (entry.getValue() instanceof Freezable)
115 {
116 ((Freezable)entry.getValue()).freeze();
117 }
118 }
119
120 for (Map.Entry<String, FlowCallNode> entry : _flowCallsMap.entrySet())
121 {
122 if (entry.getValue() instanceof Freezable)
123 {
124 ((Freezable)entry.getValue()).freeze();
125 }
126 }
127
128 for (MethodCallNode value : _methodCallsList)
129 {
130 if (value instanceof Freezable)
131 {
132 ((Freezable)value).freeze();
133 }
134 }
135
136 for (Map.Entry<String, ReturnNode> entry : _returnsMap.entrySet())
137 {
138 if (entry.getValue() instanceof Freezable)
139 {
140 ((Freezable)entry.getValue()).freeze();
141 }
142 }
143
144 for (Map.Entry<String, SwitchNode> entry : _switchesMap.entrySet())
145 {
146 if (entry.getValue() instanceof Freezable)
147 {
148 ((Freezable)entry.getValue()).freeze();
149 }
150 }
151
152 for (ViewNode value : _viewsList)
153 {
154 if (value instanceof Freezable)
155 {
156 ((Freezable)value).freeze();
157 }
158 }
159 }
160
161 @Override
162 public String getClientWindowFlowId(ClientWindow curWindow)
163 {
164 String id = getId();
165 String documentId = getDefiningDocumentId();
166
167
168 String windowId = curWindow.getId();
169 StringBuilder sb = new StringBuilder( id.length() + 1 + windowId.length() );
170 sb.append(windowId).append('_').append(documentId).append('_').append(id);
171 return sb.toString();
172 }
173
174 @Override
175 public String getDefiningDocumentId()
176 {
177 return _definingDocumentId;
178 }
179
180 public void setDefiningDocumentId(String definingDocumentId)
181 {
182 checkInitialized();
183 _definingDocumentId = definingDocumentId;
184 }
185
186 @Override
187 public String getId()
188 {
189 return _id;
190 }
191
192 public void setId(String id)
193 {
194 checkInitialized();
195 _id = id;
196 }
197
198 @Override
199 public MethodExpression getInitializer()
200 {
201 return _initializer;
202 }
203
204 public void setInitializer(MethodExpression initializer)
205 {
206 checkInitialized();
207 _initializer = initializer;
208 }
209
210 @Override
211 public MethodExpression getFinalizer()
212 {
213 return _finalizer;
214 }
215
216 public void setFinalizer(MethodExpression finalizer)
217 {
218 checkInitialized();
219 _finalizer = finalizer;
220 }
221
222 @Override
223 public String getStartNodeId()
224 {
225 return _startNodeId;
226 }
227
228 public void setStartNodeId(String startNodeId)
229 {
230 checkInitialized();
231 _startNodeId = startNodeId;
232 }
233
234 @Override
235 public Map<String, Parameter> getInboundParameters()
236 {
237 return _unmodifiableInboundParametersMap;
238 }
239
240 public void putInboundParameter(String key, Parameter value)
241 {
242 checkInitialized();
243 _inboundParametersMap.put(key, value);
244 }
245
246 @Override
247 public Map<String, FlowCallNode> getFlowCalls()
248 {
249 return _unmodifiableFlowCallsMap;
250 }
251
252 public void putFlowCall(String key, FlowCallNode value)
253 {
254 checkInitialized();
255 _flowCallsMap.put(key, value);
256 _flowNodeMap.put(value.getId(), value);
257 }
258
259 @Override
260 public List<MethodCallNode> getMethodCalls()
261 {
262 return _unmodifiableMethodCallsList;
263 }
264
265 public void addMethodCall(MethodCallNode value)
266 {
267 checkInitialized();
268 _methodCallsList.add(value);
269 _flowNodeMap.put(value.getId(), value);
270 }
271
272 @Override
273 public Map<String, ReturnNode> getReturns()
274 {
275 return _unmodifiableReturnsMap;
276 }
277
278 public void putReturn(String key, ReturnNode value)
279 {
280 checkInitialized();
281 _returnsMap.put(key, value);
282 _flowNodeMap.put(value.getId(), value);
283 }
284
285 @Override
286 public Map<String, SwitchNode> getSwitches()
287 {
288 return _unmodifiableSwitchesMap;
289 }
290
291 public void putSwitch(String key, SwitchNode value)
292 {
293 checkInitialized();
294 _switchesMap.put(key, value);
295 _flowNodeMap.put(value.getId(), value);
296 }
297
298 @Override
299 public List<ViewNode> getViews()
300 {
301 return _unmodifiableViewsList;
302 }
303
304 public void addView(ViewNode value)
305 {
306 checkInitialized();
307 _viewsList.add(value);
308 _flowNodeMap.put(value.getId(), value);
309 }
310
311 @Override
312 public FlowCallNode getFlowCall(Flow targetFlow)
313 {
314 FacesContext facesContext = null;
315 for (Map.Entry<String, FlowCallNode> entry : _flowCallsMap.entrySet())
316 {
317 if (facesContext == null)
318 {
319 facesContext = FacesContext.getCurrentInstance();
320 }
321 String calledDocumentId = entry.getValue().getCalledFlowDocumentId(facesContext);
322 String calledFlowId = entry.getValue().getCalledFlowId(facesContext);
323 if (targetFlow.getDefiningDocumentId().equals(calledDocumentId) &&
324 targetFlow.getId().equals(calledFlowId) )
325 {
326 return entry.getValue();
327 }
328 }
329 return null;
330 }
331
332 @Override
333 public FlowNode getNode(String nodeId)
334 {
335 return _flowNodeMap.get(nodeId);
336 }
337
338 public void addNavigationCases(String fromViewId, Set<NavigationCase> navigationCases)
339 {
340 checkInitialized();
341 Set<NavigationCase> navigationCaseSet = _navigationCases.get(fromViewId);
342 if (navigationCaseSet == null)
343 {
344 navigationCaseSet = new HashSet<NavigationCase>();
345 _navigationCases.put(fromViewId, navigationCaseSet);
346 }
347 navigationCaseSet.addAll(navigationCases);
348 }
349
350 public void addNavigationCase(NavigationCase navigationCase)
351 {
352 checkInitialized();
353 Set<NavigationCase> navigationCaseSet = _navigationCases.get(navigationCase.getFromViewId());
354 if (navigationCaseSet == null)
355 {
356 navigationCaseSet = new HashSet<NavigationCase>();
357 _navigationCases.put(navigationCase.getFromViewId(), navigationCaseSet);
358 }
359 navigationCaseSet.add(navigationCase);
360 }
361
362 public void removeNavigationCase(NavigationCase navigationCase)
363 {
364 checkInitialized();
365 Set<NavigationCase> navigationCaseSet = _navigationCases.get(navigationCase.getFromViewId());
366 if (navigationCaseSet == null)
367 {
368 return;
369 }
370 navigationCaseSet.remove(navigationCase);
371 }
372
373 private void checkInitialized() throws IllegalStateException
374 {
375 if (_initialized)
376 {
377 throw new IllegalStateException("Flow is inmutable once initialized");
378 }
379 }
380
381 @Override
382 public Map<String, Set<NavigationCase>> getNavigationCases()
383 {
384 return _unmodifiableNavigationCases;
385 }
386
387 }