1 package com.explosion.expfmodules.wizard.standard;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import com.explosion.expfmodules.wizard.Step;
29 import com.explosion.expfmodules.wizard.Wizard;
30 import com.explosion.utilities.exception.ExceptionManagerFactory;
31
32 /***
33 * @author Stephen Cowx
34 * This is a standard and basic implementation of the Wizard interface intended for use with simple wizards
35 * Created on 02-Dec-2004
36 */
37 public class StandardWizard implements Wizard
38 {
39 private static org.apache.log4j.Logger log = org.apache.log4j.LogManager.getLogger(StandardWizard.class);
40 private String name;
41 private String version;
42
43 private Map stepDefinitions;
44 private Step firstStep;
45
46 private Step currentStep;
47 private List previousSteps = new ArrayList();
48 private List previousDataValues = new ArrayList();
49 private Map currentDataValues = new HashMap();
50
51 /***
52 * Advances to the next step by checking all of the conditions of the outbound routes
53 * the first outbound step with no condition or with a condition thatmatches will be chosen
54 *
55 * It also copies all of the data items from this step into the data items set for the wizard.
56 * If the step is reversed (using back) the dataitems are also reversed. The step dataitems are remembered
57 * usign shallow copies so any changes to the actual data items may not be rolled back
58 * @see com.explosion.expfmodules.wizard.Wizard#next()
59 *
60 */
61 public void next()
62 {
63 try
64 {
65 log.debug("Called next");
66 boolean found = false;
67 if (currentStep != null)
68 {
69
70 List outboundRoutes = currentStep.getOutboundSteps();
71 for (Iterator it = outboundRoutes.iterator(); it.hasNext();)
72 {
73 Step step = (Step) it.next();
74 if (step.getCondition() == null || step.getCondition().conditionMet(this))
75 {
76
77 previousSteps.add(currentStep);
78
79
80 promoteDataValues();
81
82
83 if (currentStep.getStepDefinition().getAction() != null)
84 {
85 boolean advance = currentStep.getStepDefinition().getAction().execute(this);
86 if (!advance)
87 {
88
89 undoPromote();
90 break;
91 }
92 }
93
94
95 currentStep = step;
96 found = true;
97
98 break;
99 }
100 }
101 if (!found)
102 log.error("No suitable outbound routes found for step " + currentStep.getStepDefinition().getName() + " (ID: )" + currentStep.getStepDefinition().getId());
103 }
104 }
105 catch (Exception e)
106 {
107 ExceptionManagerFactory.getExceptionManager().manageException(e,"Exception caught while advancing wizard to the next step.");
108 }
109 }
110
111 /***
112 * This method moves the data values from the current step into the data values for the wizard.
113 * It also saves the previous data values hash map and makes a new one
114 */
115 private void promoteDataValues() {
116
117 previousDataValues.add(currentDataValues);
118 Map newDataValues = new HashMap();
119 for (Iterator valKeys = currentDataValues.keySet().iterator(); valKeys.hasNext();)
120 {
121 Object key = valKeys.next();
122 newDataValues.put(key, currentDataValues.get(key));
123 }
124
125 if (currentStep.getStepDefinition().getDataItems() != null)
126 {
127
128 for (Iterator newKeys = currentStep.getStepDefinition().getDataItems().keySet().iterator(); newKeys.hasNext();)
129 {
130 Object key = newKeys.next();
131 newDataValues.put(key, currentStep.getStepDefinition().getDataItems().get(key));
132 }
133 }
134
135
136 currentDataValues = newDataValues;
137 }
138
139 /***
140 * This method must be called for the wizard to be initialised and ready for processing.
141 * It initialises the currentStep with the step set as the firstStep and clears the previousSteps array.
142 * @see com.explosion.expfmodules.wizard.Wizard#start()
143 *
144 */
145 public void start()
146 {
147 log.debug("Called start");
148 if (firstStep != null)
149 {
150 previousSteps = new ArrayList();
151 currentStep = firstStep;
152
153 previousDataValues = new ArrayList();
154 currentDataValues = (Map) new HashMap();
155 }
156 }
157
158 /***
159 * This method moves the currentStep to the previous step,
160 * essentially just moving the wizard back one step.
161 * @see com.explosion.expfmodules.wizard.Wizard#back()
162 */
163 public void back()
164 {
165 log.debug("Called back");
166 if (previousSteps.size() > 0)
167 {
168 currentStep = (Step) previousSteps.get(previousSteps.size()-1);
169 undoPromote();
170 }
171
172 }
173
174 /***
175 * This is a helper method for code shared in several places in this class.It rolls back changes made
176 * to the data items and steps
177 */
178 private void undoPromote()
179 {
180 previousSteps.remove(previousSteps.size()-1);
181 currentDataValues = (Map) previousDataValues.get(previousDataValues.size()-1);
182 previousDataValues.remove(previousDataValues.size()-1);
183 }
184
185 /***
186 * This method cancels the wizard.
187 * It may perform some logic here perhaps instantiate a class of type Cencel and invoke the Cancel method.
188 * Currently it is not implemented.
189 * @see com.explosion.expfmodules.wizard.Wizard#cancel()
190 *
191 */
192 public void cancel()
193 {
194 log.debug("Called cancel");
195 }
196
197 /***
198 * This method completes the wizard.
199 * It may perform some logic here perhaps instantiate a class of type Completion and invoke the complete method.
200 * Currently it is not implemented.
201 * @see com.explosion.expfmodules.wizard.Wizard#finish()
202 *
203 */
204 public void finish()
205 {
206 try {
207 log.debug("Called finish");
208
209
210 previousSteps.add(currentStep);
211
212
213 promoteDataValues();
214
215
216 if (currentStep.getStepDefinition().getAction() != null)
217 {
218 boolean advance = currentStep.getStepDefinition().getAction().execute(this);
219 if (!advance)
220 {
221
222 undoPromote();
223 return;
224 }
225 }
226
227 currentStep = null;
228
229 } catch (Exception e) {
230 ExceptionManagerFactory.getExceptionManager().manageException(e,"Exception caught while finshing wizard");
231 }
232 }
233
234 /***
235 *
236 * @see com.explosion.expfmodules.wizard.Wizard#getName()
237 * @return
238 */
239 public String getName()
240 {
241 log.debug("Called getName");
242 return name;
243 }
244
245 /***
246 * Sets the name for this wizard
247 * @param name
248 */
249 public void setName(String name)
250 {
251 this.name = name;
252 }
253
254
255 /***
256 *
257 * @see com.explosion.expfmodules.wizard.Wizard#getFirstStep()
258 * @return
259 */
260 public Step getFirstStep()
261 {
262 log.debug("Called getStepsDefinitions");
263 return firstStep;
264 }
265
266 /***
267 * Sets the first step for this wizard
268 * @param steps
269 */
270 public void setFirstStep(Step firstStep)
271 {
272 this.firstStep = firstStep;
273 this.currentStep = firstStep;
274 }
275
276
277 /***
278 * @return Returns the stepDefinitions.
279 */
280 public Map getStepDefinitions()
281 {
282 return stepDefinitions;
283 }
284
285 /***
286 * @param stepDefinitions The stepDefinitions to set.
287 */
288 public void setStepDefinitions(Map stepDefinitions)
289 {
290 this.stepDefinitions = stepDefinitions;
291 }
292
293 /***
294 * This method returns the current step which the wizard is on.
295 * @return
296 */
297 public Step getCurrentStep()
298 {
299 return currentStep;
300 }
301
302 /***
303 * REeturns the version of this Wizard
304 * @return
305 */
306 public String getVersion()
307 {
308 return version;
309 }
310
311 /***
312 * Sets the version of this wizard
313 * @param version
314 */
315 public void setVersion(String version)
316 {
317 this.version = version;
318 }
319
320 /***
321 * These values will be populated by each step in the wizard as it progresses so that at the end of the wizard
322 * the values collected can be used by the action performed
323 * @return
324 */
325 public Map getWizardDataValues()
326 {
327 return this.currentDataValues;
328 }
329
330 /***
331 * Returns true if this wizard is finshed
332 * @return
333 */
334 public boolean isFinished()
335 {
336 if (this.currentStep == null)
337 return true;
338 else
339 return false;
340 }
341 }