1 package com.sri.emo.wizard.creation;
2
3 import java.io.*;
4 import java.util.*;
5
6 import com.jcorporate.expresso.core.controller.*;
7 import com.jcorporate.expresso.core.dataobjects.*;
8 import com.jcorporate.expresso.core.db.*;
9 import com.jcorporate.expresso.core.db.exception.*;
10 import com.jcorporate.expresso.core.registry.*;
11 import com.sri.common.util.*;
12 import com.sri.emo.dbobj.*;
13 import com.sri.emo.wizard.*;
14 import com.sri.emo.wizard.defaults.*;
15 import com.sri.emo.wizard.creation.model.*;
16
17 /***
18 * A creation wizard, as originally copied from Completion wizard with
19 * some modifications done to allow for the initialization page to be inserted
20 * For the completion wizard pages, ids are java.lang.Integer types with values
21 * <= 0 are special pages. Any values >0 represent a corresponding Part.
22 * Developers should use isPartsPage() for interpretation of this, however.
23 *
24 * @author Michael Rimov
25 *
26 */
27 public class EmoCreationWizardOld extends SequentialWizard {
28
29 /***
30 * Constant for the title page id.
31 */
32 public static final String TITLE_PAGE_ID = "-2";
33
34 /***
35 * Constant for the initialization page id
36 */
37 public static final String INITIALIZATION_PAGE_ID = "-3";
38
39 /***
40 * Constant for the last page (where 'finish' appears) id.
41 */
42 public static final String FINAL_PAGE_ID = "-1";
43
44
45 /***
46 * Underlying completion data bean. This object is not serialized due
47 * to space considerations since it is stateless for the given wizard.
48 * However, for saving state and reconsistuting it via the <tt>Memento</tt>
49 * pattern, then it is set/reset during that phase.
50 */
51 private transient CreationBean completionBean;
52
53
54 /***
55 * Constructs an emo completion wizard.
56 *
57 * @param wizMonitor WizardMonitor
58 * @param steps WizardPage[]
59 */
60 public EmoCreationWizardOld(final WizardMonitor wizMonitor, final WizardPage[] steps) {
61 super(wizMonitor, steps);
62 }
63
64
65 /***
66 * Override of Sequential's onNextPage to allow for validation of values
67 * as they're entered.
68 *
69 * @param previousPage WizardPage
70 * @param nextPage The next page that will be invoked. A 'lookahead' so
71 * to speak.
72 * @param previousPageData Serializable
73 * @return boolean true if the wizard can proceed, false if the previous
74 * page needs to be displayed with validation errors.
75 * @throws WizardException upon error.
76 * @throws AssertionError if the previouspage id is the final page.
77 */
78 protected boolean onNextPage(final WizardPage previousPage, final WizardPage nextPage,
79 final Serializable previousPageData) throws WizardException, AssertionError {
80
81 Integer previousPageId = (Integer) previousPage.getId();
82 assert previousPageId != null;
83 if(isInitializationPage(previousPageId)){
84 return validateInitializationPageData(previousPage, previousPageData);
85 }
86
87 else if (isPartsPage(previousPageId)) {
88
89 return validatePartPageData(previousPage, previousPageData);
90
91 } else if (TITLE_PAGE_ID.equals(previousPageId.toString())) {
92
93 return true;
94
95
96 } else if (FINAL_PAGE_ID.equals(previousPageId.toString())) {
97 assert false:"Final page should not have gotten 'onNext' event";
98 throw new WizardException("Internal Error: received 'next' where the previous page "
99 + "was the final page. Wizard is incorrectly constructed.");
100 } else {
101
102
103
104 if (nextPage.getMetadata() instanceof MultiEntryMetadata) {
105 boolean returnValue = validatePreMultiAttributesPage(previousPage, nextPage, previousPageData);
106 returnValue &= super.onNextPage(previousPage, nextPage, previousPageData);
107 return returnValue;
108
109
110
111 }
112
113
114
115
116 }
117
118
119
120
121 return super.onNextPage(previousPage, nextPage, previousPageData);
122 }
123
124 /***
125 * validateInitializationPageData
126 *
127 * @param previousPage WizardPage
128 * @param previousPageData Serializable
129 * @return boolean
130 */
131 private boolean validateInitializationPageData(WizardPage src,
132 Serializable previousPageData) {
133 List list = (List)previousPageData;
134 String title = (String) list.get(0);
135 if(title == null || title.length() == 0){
136 src.addError("Please enter a title.");
137 return false;
138 }
139 try {
140 Node testNode = new Node(RequestRegistry.getUser());
141 testNode.setNodeTitle(title);
142 System.out.println("node type = " + testNode.getNodeType());
143 if (testNode.find()) {
144 src.addError(
145 "Title is already in use; please choose another.");
146 return false;
147 }
148 } catch (DBException ex1) {
149 src.addError(ex1.getMessage());
150 return false;
151 }
152 try {
153 completionBean.getCurrentNode().set(Node.NODE_TITLE, title);
154 } catch (DataException ex) {
155 src.addError(ex.getMessage());
156 return false;
157 }
158 return true;
159 }
160
161 /***
162 * isInitializationPage
163 *
164 * @param previousPageId Integer
165 * @return boolean
166 */
167 private boolean isInitializationPage(Integer previousPageId) {
168
169 Integer i = new Integer(INITIALIZATION_PAGE_ID);
170 return i.equals(previousPageId);
171 }
172
173
174 private boolean validatePreMultiAttributesPage(final WizardPage previousPage, final WizardPage nextPage,
175 final Serializable previousPageData) {
176
177
178
179
180
181 MultiEntryWizardPage multiNextPage = (MultiEntryWizardPage) nextPage;
182 MultiEntryMetadata nextPageMetadata = (MultiEntryMetadata) nextPage.getMetadata();
183
184 int numEntries = 0;
185 try {
186
187 if (previousPageData == null || ((String) previousPageData).trim().length() == 0) {
188 numEntries = 0;
189 } else {
190 numEntries = Integer.parseInt((String) previousPageData);
191 }
192 } catch (NumberFormatException ex) {
193 previousPage.addError("You must enter a valid number for this page");
194 return false;
195 }
196
197 boolean hadError = false;
198
199
200
201
202
203
204
205
206 if (nextPageMetadata.getMaxEntries() != null
207 && numEntries > nextPageMetadata.getMaxEntries().intValue()) {
208 previousPage.addError(
209 "Too many. You must enter a value less than or equal to the maximum number of entries: "
210 + nextPageMetadata.getMaxEntries());
211 hadError = true;
212 }
213
214 if (hadError) {
215 return false;
216 }
217
218 multiNextPage.setNumEntries(numEntries);
219 return true;
220 }
221
222 /***
223 * Constant for the minimum possible part number. Anything else is a
224 * 'special page' of some sort.
225 */
226 private static final int MIN_PARTS_NUMBER = 0;
227
228 /***
229 * Overridden target node id. This must be explicitly set by the
230 * wizard controller. Otherwise we use the completion bean.
231 */
232
233
234 /***
235 * Checks if the given page Id indicates it is a
236 * 'Parts' page.
237 *
238 * @param pageId Integer
239 * @return boolean
240 */
241 protected boolean isPartsPage(final Integer pageId) {
242 assert pageId != null;
243
244 return pageId.intValue() >= MIN_PARTS_NUMBER;
245 }
246
247 /***
248 * @param src WizardPage
249 * @param enteredData Serializable
250 * @return boolean true if the data was validated.
251 * @throws WizardException upon error.
252 */
253 private boolean validatePartPageData(final WizardPage src, final Serializable enteredData) throws WizardException {
254 int partId = ((Integer) src.getId()).intValue();
255
256 try {
257 Part onePart = new Part();
258 onePart.setPartId(partId);
259 onePart.retrieve();
260
261
262 if (onePart.isSingleValued()) {
263 if (enteredData == null) {
264 src.addError("Please enter a value for this page.");
265 return false;
266 }
267 }
268 } catch (DBRecordNotFoundException ex) {
269 throw new WizardException("Could not find part of id: " + partId
270 + " perhaps it was deleted by someone else?", ex);
271 } catch (Throwable ex) {
272 throw new WizardException("Error processing page for part id: " + partId, ex);
273 }
274
275 return true;
276 }
277
278
279 /***
280 * This version returns a <tt>Node<tt> instance if one has
281 * been successfully created.
282 * <p>{@inheritDoc}</p>
283 *
284 * @param src WizardPage the source of the event.
285 * @param data This class expects a string for the data.
286 * @param additonalParams anything that the underlying wizard needs. The
287 * values are set by the Application Controller.
288 * @return An instance of a {@link com.sri.emo.dbobj.Node} object
289 * that represents the node the Decision Matrix returned or null if
290 * there was no equivilant data found.
291 * @throws WizardException upon error.
292 */
293 public Object processFinish(final WizardPage src, final Serializable data,
294 final Map additonalParams) throws WizardException {
295 super.processFinish(src, data, additonalParams);
296
297 assert src != null;
298
299 Node node = getCompletionBean().getCurrentNode();
300 System.out.println("processFinish : " + node.toDebugString());
301 try {
302 if(!verifyRequiredAttributes(src)){
303 return null;
304 }
305 copyReqDataIntoTargetNode(node);
306 node.add();
307 copyDataIntoTargetNode(node);
308 } catch (DBException ex) {
309 src.addError(ex.getMessage());
310 throw new WizardException(ex);
311 } catch (Exception e) {
312 src.addError(e.getMessage());
313
314 if (e instanceof RuntimeException) {
315 throw (RuntimeException) e;
316 } else {
317 throw new WizardException(e);
318 }
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347 return node;
348 }
349
350 /***
351 * verifyRequiredAttributes
352 */
353 private boolean verifyRequiredAttributes(WizardPage src) throws DBException,
354 NumberFormatException, WizardException {
355 CreationBean completionBean = this.getCompletionBean();
356
357 boolean requiredFilled = true;
358
359 for (Iterator partsIterator = completionBean.getCompletionParts().iterator(); partsIterator.hasNext();) {
360 CreationPartsBean onePartBean = (CreationPartsBean) partsIterator.next();
361
362 if (onePartBean.getFieldCompletion() == FieldCompletion.NOT_INCLUDED) {
363 continue;
364 }
365
366 Part currentPart = onePartBean.getPart();
367
368
369
370 Object wizardData = this.getAllData().get(new Integer(currentPart.getId()));
371 if(onePartBean.isRequired()){
372 System.out.println(currentPart.getPartType() + " is required");
373 System.out.println("data = '" + wizardData + "' class:"+wizardData.getClass());
374 if(wizardData == null){
375 src.addError(currentPart.getPartLabel() + " was marked as a required field, but has not been set, please fix.");
376 requiredFilled = false;
377 }
378 else if(wizardData instanceof Collection &&
379 ((Collection)wizardData).size() == 0){
380 src.addError(currentPart.getPartLabel() + " was marked as a required field, but has not been set, please fix.");
381 requiredFilled = false;
382 }
383 }
384 }
385 return requiredFilled;
386 }
387
388 /***
389 * copyReqDataIntoTargetNode
390 *
391 * @param node Node
392 */
393 private void copyReqDataIntoTargetNode(Node node) throws DataException {
394 Map allData = this.getAllData();
395 System.out.println("All Data = " +
396 StringUtil.toString(allData.keySet().iterator()));
397
398
399 List list = (List)allData.get(new Integer(EmoCreationWizardOld.
400 INITIALIZATION_PAGE_ID));
401 String title = (String) list.get(0);
402 String summary = (String) list.get(1);
403 String comment = (String) list.get(2);
404 System.out.println("found title as '" + title + "'");
405 node.set(Node.NODE_TITLE, title);
406 node.set(Node.NODE_ANNOTATION, summary);
407 node.set(Node.NODE_COMMENT, comment);
408 }
409
410
411 /***
412 * Returns true if the dynamic target has been specified.
413 *
414 * @return boolean
415 */
416 protected boolean isDynamicTarget() {
417
418
419 return true;
420
421
422
423
424
425 }
426
427 /***
428 * Copies the wizard data into the given node.
429 *
430 * @param target Node The node that is set to receive all the data.
431 * @throws Exception upon consturction error, and database errors.
432 */
433 private void copyDataIntoTargetNode(final Node target) throws Exception {
434 CreationBean completionBean = this.getCompletionBean();
435
436
437
438 for (Iterator partsIterator = completionBean.getCompletionParts().iterator(); partsIterator.hasNext();) {
439 CreationPartsBean onePartBean = (CreationPartsBean) partsIterator.next();
440
441 if (onePartBean.getFieldCompletion() == FieldCompletion.NOT_INCLUDED) {
442 continue;
443 }
444
445 Part currentPart = onePartBean.getPart();
446 System.out.println("working on part type " + currentPart.getPartType());
447
448
449 Object wizardData = this.getAllData().get(new Integer(currentPart.getId()));
450
451 if (currentPart.isHaveCustomHandler()) {
452
453 CustomPartHandlerMetadata meta = (CustomPartHandlerMetadata) getCurrentPage().getMetadata();
454 IPartHandler handler = meta.getCustomHandler();
455 List inputs = meta.getInputList();
456
457 for (Iterator iterator = inputs.iterator(); iterator.hasNext();) {
458 Input input = (Input) iterator.next();
459 handler.saveInput(input);
460 }
461
462 } else if (currentPart.isOwnedAttribute()) {
463
464 if (currentPart.isMultipleAllowed()) {
465 List valueList = (List) wizardData;
466
467 if (valueList == null) {
468 valueList = new ArrayList(0);
469 }
470
471 Attribute[] attributes = target.getAttributes(currentPart.getPartType());
472
473
474 for (int attributeIndex = 0; attributeIndex < attributes.length; attributeIndex++) {
475 attributes[attributeIndex].delete(true);
476 }
477
478 for (Iterator pageValuesIterator = valueList.iterator(); pageValuesIterator.hasNext();) {
479 String onePageValue = (String) pageValuesIterator.next();
480 System.out.println("adding attribute " + currentPart.getPartType() + " as " + onePageValue);
481 target.addAttribute(currentPart.getPartType(), onePageValue, "");
482 }
483
484 } else {
485
486 Attribute[] attributes = target.getAttributes(currentPart.getPartType());
487 System.out.println("attribute.length = " + attributes.length);
488 for (int i = 0; i < attributes.length; i++) {
489 System.out.println(attributes[i].getAttribValue());
490 }
491
492 assert attributes.length == 0 || attributes.length == 1:
493 "Expected only zero or one attributes returned for single attribute";
494
495 if (attributes.length == 0) {
496 if (wizardData != null) {
497 target.addAttribute(currentPart.getPartType(), wizardData.toString(), "");
498 }
499 } else {
500 if (wizardData == null) {
501 target.removeAttribute(attributes[0].getAttribId());
502 } else {
503 target.updateAttribute(attributes[0].getAttribId(), wizardData.toString(), "");
504 }
505 }
506 }
507
508 } else if (currentPart.isSharedNodeAttrib()) {
509
510 assert wizardData instanceof Set;
511
512 Set allRelationsParameterMap = (Set) wizardData;
513 if (allRelationsParameterMap == null) {
514 allRelationsParameterMap = new HashSet(0);
515 }
516 String[] allRelationIds = (String[]) allRelationsParameterMap.toArray(
517 new String[allRelationsParameterMap.size()]);
518
519 target.updateNodeRelations(currentPart.getPartType(), currentPart.getNodeRelation(), allRelationIds);
520 }
521
522 }
523 }
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551 /***
552 * Sets the underlying completion bean.
553 *
554 * @param completionBean CompletionBean
555 */
556 public void setCompletionBean(final CreationBean completionBean) {
557 this.completionBean = completionBean;
558 }
559
560
561
562
563
564 public CreationBean getCompletionBean() {
565 return completionBean;
566 }
567
568
569 }