1 /*
2 * Copyright (c) 2005-2007 Creative Sphere Limited.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *
10 * Creative Sphere - initial API and implementation
11 *
12 */
13 package org.abstracthorizon.danube.webflow;
14
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import org.abstracthorizon.danube.connection.Connection;
19 import org.abstracthorizon.danube.connection.ConnectionException;
20 import org.abstracthorizon.danube.http.HTTPConnection;
21 import org.abstracthorizon.danube.http.session.HTTPSessionManager;
22 import org.abstracthorizon.danube.http.session.SimpleSessionManager;
23 import org.abstracthorizon.danube.mvc.Controller;
24 import org.abstracthorizon.danube.mvc.ModelAndView;
25 import org.springframework.webflow.context.ExternalContext;
26 import org.springframework.webflow.execution.support.ApplicationView;
27 import org.springframework.webflow.executor.FlowExecutor;
28 import org.springframework.webflow.executor.ResponseInstruction;
29 import org.springframework.webflow.executor.mvc.FlowController;
30 import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor;
31 import org.springframework.webflow.executor.support.FlowRequestHandler;
32
33 /**
34 * <p>
35 * Flow execution manager for Danube MVC. This is a glue between Spring Webflow and Danube.
36 * </p>
37 * <p>
38 * Note: Code is based on the code from {@link FlowController} by Erwin Vervaet and Keith Donald
39 * </p>
40 *
41 * @author Daniel Sendula
42 */
43 public class DanubeFlowController implements Controller {
44
45 /** Flow executor */
46 private FlowExecutor flowExecutor;
47
48 /** Argument extractor */
49 private FlowExecutorArgumentExtractor argumentExtractor = null; // TODO !!! new FlowExecutorArgumentExtractor();
50
51 /** Session manager */
52 private HTTPSessionManager sessionManager;
53
54 /** Context attributes */
55 private Map<String, Object> attributes;
56
57 /**
58 * Constructor.
59 */
60 public DanubeFlowController() {
61 }
62
63 /**
64 * Sets the flow locator. It automatically creates and sets {@link FlowExecutionImpl}.
65
66 * @param flowLocator flow locator
67 */
68 // TODO !!!
69 // public void setFlowLocator(FlowLocator flowLocator) {
70 // this.flowExecutor = new FlowExecutorImpl(flowLocator);
71 // }
72
73 /**
74 * Returns flow executor.
75 *
76 * @return flow executor
77 */
78 public FlowExecutor getFlowExecutor() {
79 return flowExecutor;
80 }
81
82 /**
83 * Sets flow executor.
84 *
85 * @param flowExecutor flow executor
86 */
87 public void setFlowExecutor(FlowExecutor flowExecutor) {
88 this.flowExecutor = flowExecutor;
89 }
90
91 /**
92 * Returns argument extractor used by this controller.
93 * @return argument extractor
94 */
95 public FlowExecutorArgumentExtractor getArgumentExtractor() {
96 if (argumentExtractor == null) {
97 // TODO !!! argumentExtractor = new FlowExecutorArgumentExtractor();
98 }
99 return argumentExtractor;
100 }
101
102 /**
103 * Sets argument extractor to be used.
104 *
105 * @param parameterExtractor argument extractor
106 */
107 public void setArgumentExtractor(FlowExecutorArgumentExtractor parameterExtractor) {
108 this.argumentExtractor = parameterExtractor;
109 }
110
111 /**
112 * Sets default flow id if none is specified with the parameters.
113 *
114 * @param defaultFlowId default flow id
115 */
116 public void setDefaultFlowId(String defaultFlowId) {
117 // TODO !!! this.argumentExtractor.setDefaultFlowId(defaultFlowId);
118 }
119
120 /**
121 * Handles request
122 * @param connection connection
123 * @return model and view combination
124 * @throws ConnectionException connection exception
125 */
126 public ModelAndView handleRequest(Connection connection) throws ConnectionException {
127 try {
128 HTTPConnection httpConnection = (HTTPConnection) connection;
129
130 DanubeExternalContext context = new DanubeExternalContext(this, httpConnection);
131
132 FlowRequestHandler flowRequestHandler = new FlowRequestHandler(getFlowExecutor(), getArgumentExtractor());
133 ResponseInstruction responseInstruction = flowRequestHandler.handleFlowRequest(context);
134
135 return toModelAndView(responseInstruction, context);
136 } catch (ConnectionException e) {
137 throw e;
138 } catch (Exception e) {
139 throw new ConnectionException(e);
140 }
141 }
142
143 /**
144 * Returns model and a view combination
145 * @param response response instruction
146 * @param context external context
147 * @return model and view
148 */
149 @SuppressWarnings("unchecked")
150 protected ModelAndView toModelAndView(ResponseInstruction response, ExternalContext context) {
151 if (response.isApplicationView()) {
152 ApplicationView view = (ApplicationView)response.getViewSelection();
153 Map<String, Object> model = new HashMap<String, Object>(view.getModel());
154 // TODO
155 // argumentExtractor.put(response.getFlowExecutionKey(), model);
156 // argumentExtractor.put(response.getFlowExecutionContext(), model);
157 return new ModelAndView(view.getViewName(), model);
158 // TODO
159 // } else if (response.isConversationRedirect()) {
160 // // redirect to active conversation URL
161 // Serializable conversationId = response.getFlowExecutionKey().getConversationId();
162 // String conversationUrl = argumentExtractor.createConversationUrl(conversationId, context);
163 // return new org.springframework.web.servlet.ModelAndView(new RedirectView(conversationUrl, true));
164 // } else if (response.isExternalRedirect()) {
165 // // redirect to external URL
166 // ExternalRedirect redirect = (ExternalRedirect)response.getViewSelection();
167 // String externalUrl = argumentExtractor.createExternalUrl(redirect, response.getFlowExecutionKey(), context);
168 // return new org.springframework.web.servlet.ModelAndView(new RedirectView(externalUrl, redirect.isContextRelative()));
169 // } else if (response.isFlowRedirect()) {
170 // // restart the flow by redirecting to flow launch URL
171 // String flowUrl = argumentExtractor.createFlowUrl((FlowRedirect)response.getViewSelection(), context);
172 // return new org.springframework.web.servlet.ModelAndView(new RedirectView(flowUrl, true));
173 } else if (response.isNull()) {
174 return null;
175 } else {
176 throw new IllegalArgumentException("Don't know how to handle response instruction " + response);
177 }
178 }
179
180 /**
181 * Returns session manaager
182 * @return http session manager
183 */
184 public HTTPSessionManager getSessionManager() {
185 if (sessionManager == null) {
186 sessionManager = new SimpleSessionManager();
187 }
188 return sessionManager;
189 }
190
191 /**
192 * Sets session manager
193 * @param sessionManager http session manager
194 */
195 public void setSessionManager(HTTPSessionManager sessionManager) {
196 this.sessionManager = sessionManager;
197 }
198
199 /**
200 * Returns attributes as a map
201 * @return attributes
202 */
203 public Map<String, Object> getAttributes() {
204 if (attributes == null) {
205 attributes = new HashMap<String, Object>();
206 }
207 return attributes;
208 }
209
210 /**
211 * Sets attributes map
212 * @param attributes attributes
213 */
214 public void setAttributes(Map<String, Object> attributes) {
215 if (attributes == null) {
216 getAttributes();
217 }
218 this.attributes = attributes;
219 }
220 }