KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > webflow > executor > jsf > FlowNavigationHandler


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.executor.jsf;
17
18 import javax.faces.application.NavigationHandler;
19 import javax.faces.context.FacesContext;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.springframework.web.jsf.DecoratingNavigationHandler;
24 import org.springframework.webflow.context.ExternalContext;
25 import org.springframework.webflow.core.collection.MutableAttributeMap;
26 import org.springframework.webflow.definition.FlowDefinition;
27 import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
28 import org.springframework.webflow.execution.FlowExecution;
29 import org.springframework.webflow.execution.FlowExecutionFactory;
30 import org.springframework.webflow.execution.ViewSelection;
31 import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor;
32
33 /**
34  * An implementation of a JSF <code>NavigationHandler</code> that provides
35  * integration with Spring Web Flow. It delegates handling to the standard
36  * NavigationHandler implementation when a navigation request does not pertain
37  * to a flow execution.
38  * <p>
39  * Specifically, the following navigation handler algorithm is implemented:
40  * <ul>
41  * <li>If a flow execution is <strong>not</strong> currently in progress:
42  * <ul>
43  * <li>If the specified logical outcome <strong>is</strong> of the form
44  * <em>flowId:xxx</em>, look up the corresponding
45  * {@link org.springframework.webflow.engine.Flow} definition with that id and
46  * launch a new flow execution in the starting state. Expose information to
47  * indicate that this flow is in progress and render the starting
48  * {@link ViewSelection}.</li>
49  * <li>If the specified logical outcome is <strong>not</strong> of the form
50  * <em>flowId:xxx</em>, simply delegate to the standard
51  * <code>NavigationHandler</code> implementation and return.</li>
52  * </ul>
53  * </li>
54  * <li>If a flow execution <strong>is</strong> currently in progress:
55  * <ul>
56  * <li>Load the reference to the current in-progress flow execution using the
57  * submitted <em>_flowExecutionKey</em> parameter.</li>
58  * <li>Resume the flow execution by signaling what action outcome (aka event)
59  * the user took in the current state.
60  * <li>Once state event processing to complete, render the
61  * <code>ViewSelection</code> returned.</li>
62  * </ul>
63  * </li>
64  * </ul>
65  *
66  * @author Craig McClanahan
67  * @author Colin Sampaleanu
68  * @author Keith Donald
69  */

70 public class FlowNavigationHandler extends DecoratingNavigationHandler {
71
72     /**
73      * Logger, usable by subclasses.
74      */

75     protected final Log logger = LogFactory.getLog(getClass());
76
77     /**
78      * A helper for extracting parameters needed by this flow navigation
79      * handler.
80      */

81     private FlowExecutorArgumentExtractor argumentExtractor = new FlowNavigationHandlerArgumentExtractor();
82
83     /**
84      * Create a new {@link FlowNavigationHandler} using the default constructor.
85      */

86     public FlowNavigationHandler() {
87         super();
88     }
89
90     /**
91      * Create a new {@link FlowNavigationHandler}, wrapping the specified
92      * standard navigation handler implementation.
93      * @param originalNavigationHandler Standard <code>NavigationHandler</code>
94      * we are wrapping
95      */

96     public FlowNavigationHandler(NavigationHandler originalNavigationHandler) {
97         super(originalNavigationHandler);
98     }
99
100     /**
101      * Returns the argument extractor used by this navigation handler.
102      */

103     public FlowExecutorArgumentExtractor getArgumentExtractor() {
104         return argumentExtractor;
105     }
106
107     /**
108      * Sets the argument extractor to use.
109      */

110     public void setArgumentExtractor(FlowExecutorArgumentExtractor argumentExtractor) {
111         this.argumentExtractor = argumentExtractor;
112     }
113
114     public void handleNavigation(FacesContext facesContext, String JavaDoc fromAction, String JavaDoc outcome,
115             NavigationHandler originalNavigationHandler) {
116         JsfExternalContext context = new JsfExternalContext(facesContext, fromAction, outcome);
117         if (FlowExecutionHolderUtils.isFlowExecutionRestored(facesContext)) {
118             // the flow execution has been restored, now see if we need to
119
// signal an event against it
120
if (argumentExtractor.isEventIdPresent(context)) {
121                 // a flow execution has been restored, signal an event in it
122
String JavaDoc eventId = argumentExtractor.extractEventId(context);
123                 FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(facesContext);
124                 ViewSelection selectedView = holder.getFlowExecution().signalEvent(eventId, context);
125                 holder.setViewSelection(selectedView);
126                 holder.markNeedsSave();
127             }
128         }
129         else {
130             // no flow execution exists, see if we need to launch one if the
131
// flow id is present
132
if (argumentExtractor.isFlowIdPresent(context)) {
133                 // a flow execution launch has been requested, start it
134
String JavaDoc flowId = argumentExtractor.extractFlowId(context);
135                 FlowDefinition flowDefinition = getLocator(context).getFlowDefinition(flowId);
136                 FlowExecution flowExecution = getFactory(context).createFlowExecution(flowDefinition);
137                 FlowExecutionHolder holder = new FlowExecutionHolder(flowExecution);
138                 FlowExecutionHolderUtils.setFlowExecutionHolder(holder, facesContext);
139                 ViewSelection selectedView = flowExecution.start(createInput(flowExecution, context), context);
140                 holder.setViewSelection(selectedView);
141                 holder.markNeedsSave();
142             }
143             else {
144                 // no flow id submitted, proceed with std navigation
145
originalNavigationHandler.handleNavigation(facesContext, fromAction, outcome);
146             }
147         }
148     }
149
150     private FlowDefinitionLocator getLocator(JsfExternalContext context) {
151         return FlowFacesUtils.getDefinitionLocator(context.getFacesContext());
152     }
153     
154     private FlowExecutionFactory getFactory(JsfExternalContext context) {
155         return FlowFacesUtils.getExecutionFactory(context.getFacesContext());
156     }
157     
158     /**
159      * Factory method that creates the input attribute map for a newly created
160      * {@link FlowExecution}. TODO - add support for input mappings here
161      * @param flowExecution the new flow execution (yet to be started)
162      * @param context the external context
163      * @return the input map
164      */

165     protected MutableAttributeMap createInput(FlowExecution flowExecution, ExternalContext context) {
166         return null;
167     }
168 }
Popular Tags