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