1
2
3
4
5
6
7
8
9
10 package com.sri.emo.wizard.selection;
11
12 import com.jcorporate.expresso.core.controller.Transition;
13 import com.jcorporate.expresso.core.db.DBException;
14 import com.sri.emo.dbobj.WizDefinition;
15 import com.sri.emo.dbobj.WizStep;
16 import com.sri.emo.wizard.*;
17 import com.sri.emo.wizard.defaults.EmoWizardMetadata;
18 import com.sri.emo.wizard.defaults.Log4jWizMonitor;
19 import com.sri.emo.wizard.defaults.SequentialWizard;
20 import com.sri.emo.wizard.expressoimpl.ExpressoLink;
21 import com.sri.emo.wizard.expressoimpl.WizardController;
22
23 import java.io.Serializable;
24 import java.lang.reflect.Constructor;
25 import java.lang.reflect.InvocationTargetException;
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29
30
31 /***
32 * Wizard Factory for EMO wizards.
33 * It also happens to implement WizardMementoConverter because it is most
34 * intimate with the inner workings of the wizards, therefore it is best able
35 * to do the dehydration and rehydration grunt work. That said, the client
36 * shouldn't know that!
37 *
38 * @author Michael Rimov
39 */
40 public class EmoSelectionWizardFactory implements WizardFactory, WizardFactorySPI {
41 /***
42 * Wizard Id.
43 */
44 private int wizardId;
45
46 /***
47 * Constant for the default controller used for Emo.
48 */
49 public final Class DEFAULT_CONTROLLER = com.sri.emo.wizard.selection.WizardAction.class;
50
51
52 /***
53 * Constructor that takes a data context.
54 */
55 public EmoSelectionWizardFactory() {
56 }
57
58 /***
59 * Sets the wizard id for the given selection factory. In other words,
60 * what is the wizard id of what is going to be constructed.
61 *
62 * @param newId int
63 */
64 public void setWizardId(int newId) {
65 wizardId = newId;
66 }
67
68
69 protected Transition commonTransitionConstruction(final int id) {
70 Transition t = new Transition();
71 t.setControllerObject(DEFAULT_CONTROLLER);
72 t.addParam(WizardController.WIZ_PARAMETER_ID, Integer.toString(id));
73 return t;
74 }
75
76 /***
77 * Builds the link that corresponds to the 'next' location.
78 *
79 * @param id int the wizard id
80 * @return Link
81 */
82 protected ExpressoLink buildNextLink(final int id) {
83 Transition t = commonTransitionConstruction(id);
84 t.setState(WizardController.NEXT_STATE);
85 t.setLabel("Next");
86 t.setName("Next");
87 return new ExpressoLink(t);
88 }
89
90 /***
91 * Builds the link that corresponds to the 'finish' location.
92 *
93 * @param id int the wizard id
94 * @return Link
95 */
96 protected ExpressoLink buildFinishLink(final int id) {
97 Transition t = commonTransitionConstruction(id);
98 t.setState(WizardController.FINISH_STATE);
99 t.setLabel("Finish");
100 t.setName("Finish");
101
102 return new ExpressoLink(t);
103 }
104
105 /***
106 * Builds the link that corresponds to the 'cancel' location.
107 *
108 * @param id int the wizard id
109 * @return Link
110 */
111 protected ExpressoLink buildCancelLink(final int id) {
112 Transition t = commonTransitionConstruction(id);
113 t.setState(WizardController.CANCEL_STATE);
114 t.setLabel("Cancel");
115 t.setName("Cancel");
116
117 return new ExpressoLink(t);
118 }
119
120 /***
121 * Builds the link that corresponds to the 'back' location.
122 *
123 * @param id int the wizard id
124 * @return Link
125 */
126 protected ExpressoLink buildBackLink(final int id) {
127 Transition t = commonTransitionConstruction(id);
128 t.setState(WizardController.PREVIOUS_STATE);
129 t.setLabel("Back");
130 t.setName("Back");
131
132 return new ExpressoLink(t);
133 }
134
135 public Wizard buildWizard() throws WizardException {
136 try {
137 WizDefinition wizard = getWizDefinition();
138
139 int id = wizard.getFieldInt(WizDefinition.FLD_ID);
140
141 ExpressoLink next = buildNextLink(id);
142 ExpressoLink finish = buildFinishLink(id);
143 ExpressoLink cancel = buildCancelLink(id);
144 ExpressoLink back = buildBackLink(id);
145
146 List steps = constructSteps(wizard, next, finish, cancel, back);
147
148 return constructWizard(wizard, steps);
149 } catch (DBException ex) {
150 throw new WizardException("Error building wizard: "
151 + wizardId, ex);
152 }
153 }
154
155 /***
156 * Retrieve the WizDefinition associated with the defined id in the
157 * constructor.
158 *
159 * @return WizDefinition associated with the id.
160 * @throws DBException if the wizdefinition cannot be retrieved.
161 */
162 protected WizDefinition getWizDefinition() throws DBException {
163 WizDefinition wizard = new WizDefinition();
164 wizard.setId(wizardId);
165 wizard.retrieve();
166 return wizard;
167 }
168
169 /***
170 * Constructs the steps of the wizard. Override to customize your
171 * step construction.
172 *
173 * @param wizard The Wizard Definition DBObject
174 * @param next the Next Link instance
175 * @param finish the Finish Link instance
176 * @param cancel the Cancel Link instance
177 * @param back the Back Link instance
178 * @return List of Wizard Steps
179 * @throws WizardException upon construction error.
180 * @throws DBException upon database access error.
181 */
182 private List constructSteps(final WizDefinition wizard,
183 final ExpressoLink next, final ExpressoLink finish,
184 final Link cancel, ExpressoLink back) throws WizardException, DBException {
185
186 List steps = wizard.getPageDefinitions();
187 List returnValue = new ArrayList();
188 boolean firstPage = true;
189
190 for (Iterator i = steps.iterator(); i.hasNext();) {
191 WizStep oneStep = (com.sri.emo.dbobj.WizStep) i.next();
192 EmoWizardMetadata pageMetadata;
193
194 ExpressoLink nextPageLink = cloneTransition(next, oneStep.getId());
195 ExpressoLink backPageLink = cloneTransition(back, oneStep.getId());
196
197 if (firstPage) {
198 firstPage = false;
199 if (i.hasNext()) {
200 pageMetadata = new EmoWizardMetadata();
201 pageMetadata.setCancelLink(cancel);
202 pageMetadata.setNextLink(nextPageLink);
203 } else {
204
205
206 pageMetadata = new EmoWizardMetadata();
207 pageMetadata.setCancelLink(cancel);
208 pageMetadata.setNextLink(nextPageLink);
209 }
210
211
212 pageMetadata.setEntryRequired(false);
213
214
215
216
217
218
219
220
221
222
223 } else {
224
225 pageMetadata = new EmoWizardMetadata();
226 pageMetadata.setCancelLink(cancel);
227 pageMetadata.setPreviousLink(backPageLink);
228 pageMetadata.setNextLink(nextPageLink);
229
230
231 pageMetadata.setEntryRequired(true);
232 }
233
234 WizardPage page = oneStep.getWizardPage(pageMetadata);
235 returnValue.add(page);
236 }
237
238
239
240
241 EmoWizardMetadata pageMetadata = new EmoWizardMetadata();
242 ExpressoLink nextPageLink = cloneTransition(next, DisplaySummaryPage.PAGE_ID.toString());
243 ExpressoLink finishPageLink = cloneTransition(finish, DisplaySummaryPage.PAGE_ID.toString());
244 ExpressoLink backPageLink = cloneTransition(back, DisplaySummaryPage.PAGE_ID.toString());
245 pageMetadata.setCancelLink(cancel);
246 pageMetadata.setNextLink(nextPageLink);
247 pageMetadata.setPreviousLink(backPageLink);
248 pageMetadata.setViewId("displayResults");
249 WizardPage page = new DisplaySummaryPage(pageMetadata);
250 returnValue.add(page);
251
252
253
254
255 pageMetadata = new EmoWizardMetadata();
256
257 nextPageLink = cloneTransition(next, NameNodePage.PAGE_ID);
258 finishPageLink = cloneTransition(finish, NameNodePage.PAGE_ID);
259 backPageLink = cloneTransition(back, NameNodePage.PAGE_ID);
260
261 pageMetadata.setCancelLink(cancel);
262 pageMetadata.setPreviousLink(backPageLink);
263 pageMetadata.setFinishLink(finishPageLink);
264 pageMetadata.setViewId("promptTemplateName");
265
266
267 pageMetadata.setEntryRequired(true);
268 pageMetadata.setEntry(true);
269 pageMetadata.setTitle("Name Your Template");
270
271 page = new NameNodePage(new Integer(NameNodePage.PAGE_ID), pageMetadata);
272
273 returnValue.add(page);
274
275
276 return returnValue;
277 }
278
279 protected ExpressoLink cloneTransition(final ExpressoLink next, String pageId) {
280 ExpressoLink nextPageLink = null;
281 try {
282 nextPageLink = (ExpressoLink) next.clone();
283 } catch (CloneNotSupportedException e) {
284 throw new RuntimeException(e);
285 }
286 nextPageLink.getTransition().addParam(WizardController.WIZ_PAGE_PARAMETER, pageId);
287 return nextPageLink;
288 }
289
290 protected void addFinalStepToConstructedSteps(final WizDefinition definition, final List predefinedSteps) throws
291 DBException {
292 }
293
294 private void setWizardForStepsThatNeedIt(final Wizard constructedWizard, final List steps) {
295 for (Iterator i = steps.iterator(); i.hasNext();) {
296 WizardPage oneStep = (WizardPage) i.next();
297
298 if (oneStep instanceof DisplaySummaryPage) {
299 ((DisplaySummaryPage) oneStep).setMyOwner(constructedWizard);
300 }
301 }
302
303 }
304
305 /***
306 * Constructs the wizard itself.
307 *
308 * @param definition the WizDefinition dbobject for this wizard.
309 * @param steps the List of steps that were constructed previously in
310 * the constructSteps function.
311 * @return fully constructed Wizard instance.
312 * @throws DBException upon database exception error.
313 */
314 protected Wizard constructWizard(final WizDefinition definition, final List steps) throws DBException {
315 String wizardClassString = definition.getWizardClass();
316 Class wizardClass;
317 try {
318 wizardClass = Thread.currentThread().getContextClassLoader()
319 .loadClass(wizardClassString);
320 if (!SequentialWizard.class.isAssignableFrom(wizardClass)) {
321 throw new IllegalArgumentException("If you do not"
322 + " implement a wizard"
323 + " that derives from SequentialWizard and uses the same "
324 + "constructor then you need to implement your own"
325 + " Wizard Factory implementation");
326
327 }
328
329 Constructor c = wizardClass.getConstructor(new Class[]{
330 WizardMonitor.class, WizardPage[].class});
331 AbstractWizard emoWizard = (AbstractWizard) c
332 .newInstance(
333 new Object[]{constructMonitor(), (WizardPage[]) steps.toArray(
334 new WizardPage[steps.size()])});
335
336 emoWizard.setId(new Integer(definition.getId()));
337 emoWizard.setTitle(definition.getWizName());
338 emoWizard.setSummary(definition.getSummary());
339 setWizardForStepsThatNeedIt(emoWizard, steps);
340 return emoWizard;
341 } catch (ClassNotFoundException ex) {
342 throw new IllegalArgumentException("Unknown class: "
343 + wizardClassString
344 + " edit your wizard definition to solve this problem");
345 } catch (InvocationTargetException ex) {
346 throw new DBException("An Exception was thrown constructing the " +
347 "wizard", ex);
348 } catch (IllegalAccessException ex) {
349 throw new IllegalArgumentException("The wizard specified: "
350 + wizardClassString + " does not have a public constructor"
351 + " like the default. You may need to implement your own "
352 + "wizard factory.");
353 } catch (InstantiationException ex) {
354 throw new DBException("There was an error constructing your "
355 + "wizard.", ex);
356 } catch (NoSuchMethodException ex) {
357 throw new IllegalArgumentException("No appropriate constructor"
358 + " found:" + ex.getMessage());
359 }
360
361 }
362
363 /***
364 * Override to provide your own monitor, possibly for testing purposes.
365 *
366 * @return WizardMonitor instance.
367 */
368 protected WizardMonitor constructMonitor() {
369 return new Log4jWizMonitor();
370 }
371
372 /***
373 * Retrieve the controller for the wizard. Override for your own
374 * customization.
375 *
376 * @return java.lang.Class should be instance of
377 * com.jcorporate.expresso.core.controller.Controller
378 */
379 protected Class getWizardController() {
380 try {
381 String className = getWizDefinition().getController();
382 if (className == null || className.length() == 0) {
383 return DEFAULT_CONTROLLER;
384 } else {
385 try {
386 return Class.forName(className, true,
387 Thread.currentThread().getContextClassLoader());
388 } catch (ClassNotFoundException ex1) {
389 return DEFAULT_CONTROLLER;
390 }
391 }
392 } catch (DBException ex) {
393 return DEFAULT_CONTROLLER;
394 }
395
396 }
397
398 /***
399 * getWizardId
400 *
401 * @return String
402 */
403 protected int getWizardId() {
404 return wizardId;
405 }
406
407
408 public Serializable toMemento(Wizard target) throws WizardException {
409 return (Serializable) target;
410 }
411
412 public Wizard fromMemento(Serializable previouslyExternalized) throws WizardException {
413 return (Wizard) previouslyExternalized;
414 }
415
416 }