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 }