View Javadoc

1   package org.andromda.cartridges.bpm4struts.metafacades;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.Collection;
6   import java.util.Collections;
7   import java.util.Iterator;
8   import java.util.LinkedHashMap;
9   import java.util.LinkedHashSet;
10  import java.util.List;
11  import java.util.Map;
12  
13  import org.andromda.cartridges.bpm4struts.Bpm4StrutsGlobals;
14  import org.andromda.cartridges.bpm4struts.Bpm4StrutsProfile;
15  import org.andromda.cartridges.bpm4struts.Bpm4StrutsUtils;
16  import org.andromda.metafacades.uml.ClassifierFacade;
17  import org.andromda.metafacades.uml.EventFacade;
18  import org.andromda.metafacades.uml.FrontEndActivityGraph;
19  import org.andromda.metafacades.uml.ModelElementFacade;
20  import org.andromda.metafacades.uml.TransitionFacade;
21  import org.andromda.metafacades.uml.UMLMetafacadeUtils;
22  import org.andromda.metafacades.uml.UMLProfile;
23  import org.andromda.metafacades.uml.UseCaseFacade;
24  import org.andromda.utils.StringUtilsHelper;
25  import org.apache.commons.lang.StringUtils;
26  
27  
28  /**
29   * MetafacadeLogic implementation.
30   *
31   * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter
32   */
33  public class StrutsParameterLogicImpl
34      extends StrutsParameterLogic
35  {
36      public StrutsParameterLogicImpl(java.lang.Object metaObject,
37                                      java.lang.String context)
38      {
39          super(metaObject, context);
40      }
41  
42      protected Object handleGetStrutsAction()
43      {
44          Object actionObject = null;
45  
46          final EventFacade event = getEvent();
47          if (event != null)
48          {
49              final TransitionFacade transition = event.getTransition();
50              if (transition instanceof StrutsAction)
51              {
52                  actionObject = transition;
53              }
54          }
55          return actionObject;
56      }
57  
58      protected String handleGetStyleId()
59      {
60          String styleId = null;
61  
62          final StrutsAction action = this.getStrutsAction();
63          if (action != null)
64          {
65              // if this parameter's action links to a table we use a specific styleId
66              if (action.isTableLink())
67              {
68                  styleId = action.getTableLinkName() + StringUtilsHelper.upperCamelCaseName(getName());
69              }
70              else
71              {
72                  final EventFacade trigger = action.getTrigger();
73                  if (trigger != null)
74                  {
75                      styleId = StringUtilsHelper.lowerCamelCaseName(trigger.getName()) +
76                          StringUtilsHelper.upperCamelCaseName(getName());
77                  }
78              }
79          }
80  
81          return styleId;
82      }
83  
84      protected Object handleGetJsp()
85      {
86          Object jspObject = null;
87  
88          final EventFacade event = getEvent();
89          if (event != null)
90          {
91              final TransitionFacade transition = event.getTransition();
92              if (transition instanceof StrutsAction)
93              {
94                  final StrutsAction action = (StrutsAction)transition;
95                  jspObject = action.getInput();
96              }
97              else if (transition instanceof StrutsForward)
98              {
99                  final StrutsForward forward = (StrutsForward)transition;
100                 if (forward.isEnteringPage())
101                 {
102                     jspObject = forward.getTarget();
103                 }
104             }
105         }
106 
107         return jspObject;
108     }
109 
110     protected List handleGetFormFields()
111     {
112         final List formFields;
113         if (isControllerOperationArgument() && getName() != null)
114         {
115             final String name = getName();
116             formFields = new ArrayList();
117             Collection actions = this.getControllerOperation().getDeferringActions();
118             for (final Iterator actionIterator = actions.iterator(); actionIterator.hasNext();)
119             {
120                 StrutsAction action = (StrutsAction)actionIterator.next();
121                 Collection actionFormFields = action.getActionFormFields();
122                 for (final Iterator fieldIterator = actionFormFields.iterator(); fieldIterator.hasNext();)
123                 {
124                     StrutsParameter parameter = (StrutsParameter)fieldIterator.next();
125                     if (name.equals(parameter.getName()))
126                     {
127                         formFields.add(parameter);
128                     }
129                 }
130             }
131         }
132         else
133         {
134             formFields = Collections.EMPTY_LIST;
135         }
136         return formFields;
137     }
138 
139     /**
140      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getResetValue()()
141      */
142     protected java.lang.String handleGetNullValue()
143     {
144         String nullValue = null;
145 
146         final ClassifierFacade type = getType();
147         if (type != null)
148         {
149             nullValue = type.getJavaNullString();
150         }
151         return nullValue;
152     }
153 
154     /**
155      * @see StrutsParameter#isResetRequired()
156      */
157     protected boolean handleIsResetRequired()
158     {
159         final boolean resetRequired;
160 
161         if (isSelectable())
162         {
163             resetRequired = true;
164         }
165         else
166         {
167             final ClassifierFacade type = getType();
168             if (type == null)
169             {
170                 resetRequired = false;
171             }
172             else
173             {
174                 resetRequired = (type.isArrayType() || type.isFileType()) ? true : this.isValidatorBoolean();
175             }
176         }
177         return resetRequired;
178     }
179 
180     /**
181      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getMessageKey()()
182      */
183     protected java.lang.String handleGetMessageKey()
184     {
185         final StringBuffer messageKey = new StringBuffer();
186 
187         if (!normalizeMessages())
188         {
189             if (isActionParameter())
190             {
191                 final StrutsAction action = this.getStrutsAction();
192                 if (action != null)
193                 {
194                     messageKey.append(action.getMessageKey());
195                     messageKey.append('.');
196                 }
197             }
198             else
199             {
200                 final StrutsJsp page = getJsp();
201                 if (page != null)
202                 {
203                     messageKey.append(page.getMessageKey());
204                     messageKey.append('.');
205                 }
206             }
207             messageKey.append("param.");
208         }
209 
210         messageKey.append(StringUtilsHelper.toResourceMessageKey(super.getName()));
211         return messageKey.toString();
212     }
213 
214     /**
215      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getMessageValue()()
216      */
217     protected java.lang.String handleGetMessageValue()
218     {
219         return StringUtilsHelper.toPhrase(super.getName()); // the actual name is used for displaying
220     }
221 
222     /**
223      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getTitleKey()()
224      */
225     protected java.lang.String handleGetTitleKey()
226     {
227         return getMessageKey() + ".title";
228     }
229 
230     /**
231      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getTitleValue()()
232      */
233     protected java.lang.String handleGetTitleValue()
234     {
235         String requiredSuffix = "";
236         if (isRequired())
237         {
238             requiredSuffix = " is required";
239         }
240 
241         String dateSuffix = "";
242         if (isDate())
243         {
244             dateSuffix = (isStrictDateFormat())
245                 ? " (use this strict format: " + getDateFormat() + ")"
246                 : " (use this lenient format: " + getDateFormat() + ")";
247         }
248 
249         String documentation = getDocumentation("", 64, false);
250         return StringUtilsHelper.toResourceMessage((StringUtils.isBlank(documentation))
251             ? super.getName() + requiredSuffix + dateSuffix
252             : documentation.trim().replaceAll("\n", "<br/>"));
253     }
254 
255     protected String handleGetDocumentationKey()
256     {
257         return this.getMessageKey() + ".documentation";
258     }
259 
260     protected String handleGetDocumentationValue()
261     {
262         final String value = StringUtilsHelper.toResourceMessage(this.getDocumentation("", 64, false));
263         return (value == null) ? "" : value;
264     }
265 
266     protected String handleGetOnlineHelpKey()
267     {
268         return this.getMessageKey() + ".online.help";
269     }
270 
271     protected String handleGetOnlineHelpValue()
272     {
273         final String crlf = "<br/>";
274         final String format = getValidatorFormat();
275         final StringBuffer buffer = new StringBuffer();
276 
277         final String value = StringUtilsHelper.toResourceMessage(this.getDocumentation("", 64, false));
278         buffer.append((value == null) ? "No field documentation has been specified" : value);
279         buffer.append(crlf);
280         buffer.append(crlf);
281 
282         buffer.append(isRequired() ? "This field is required" : "This field is optional");
283         buffer.append(crlf);
284 
285         if ("password".equals(getWidgetType()))
286         {
287             buffer.append("This is a password field, it will not show the data you enter, ")
288                 .append("each character will be masked using an asterisk");
289             buffer.append(crlf);
290         }
291 
292         if (isCreditCardFormat(format))
293         {
294             buffer.append("The value of this field should reflect a ")
295                 .append("<a href=\"http://www.beachnet.com/~hstiles/cardtype.html\" target=\"_blank\">creditcard</a> ");
296             buffer.append(crlf);
297         }
298 
299         if (isDate())
300         {
301             String dateFormat = getDateFormat();
302             buffer.append("This field represents a date and should be formatted in the matter described here")
303                 .append("<a href=\"http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html\" ")
304                 .append("target=\"_jdk\">");
305             buffer.append(dateFormat).append("</a> ");
306 
307             if (isStrictDateFormat()) buffer
308                 .append("This format is strict in the sense that the parser will not use any heuristics in ")
309                 .append("order to guess the intended date in case the input would not perfectly match the format");
310             else
311             {
312                 buffer.append("This format is lenient in the sense that the parser will attempt to use heuristics in ")
313                     .append("order to guess the intended date in case the input would not perfectly match the format");
314             }
315             buffer.append(crlf);
316             buffer.append("A calendar has been foreseen to select a date from, it will automatically convert the date ")
317                 .append("to the appropriate format.");
318             buffer.append(crlf);
319         }
320 
321         if (this.isValidatorTime())
322         {
323             String dateFormat = getDateFormat();
324             buffer
325                 .append("This field represents a time and should be formatted in the manner described here (for time) ")
326                 .append("<a href=\"http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html\" ")
327                 .append("target=\"_jdk\">");
328             buffer.append(dateFormat).append("</a> ");
329         }
330 
331         if (isEmailFormat(format))
332         {
333             buffer.append("The value of this field should reflect an email address");
334             buffer.append(crlf);
335         }
336 
337         if (isMaxLengthFormat(format))
338         {
339             buffer.append("This field should not contain more than ");
340             buffer.append(getMaxLengthValue(format));
341             buffer.append(" characters");
342             buffer.append(crlf);
343         }
344 
345         if (isMinLengthFormat(format))
346         {
347             buffer.append("This field should contain at least ");
348             buffer.append(getMinLengthValue(format));
349             buffer.append(" characters");
350             buffer.append(crlf);
351         }
352 
353         if (isPatternFormat(format))
354         {
355             buffer.append("The value should match this ");
356             buffer.append(
357                 "<a href=\"http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html\" target=\"_jdk\">");
358             buffer.append("regular expression</a>: ");
359             buffer.append(getPatternValue(format));
360             buffer.append(crlf);
361         }
362 
363         if (isRangeFormat(format))
364         {
365             buffer.append("The value of this field should be in the range of ");
366             buffer.append(getRangeStart(format));
367             buffer.append(" to ");
368             buffer.append(getRangeEnd(format));
369             buffer.append(crlf);
370         }
371 
372         final String validWhen = getValidWhen();
373         if (validWhen != null)
374         {
375             buffer.append("This field is only valid under specific conditions, more concretely the following ")
376                 .append("expression must evaluate true: ").append(validWhen);
377             buffer.append(crlf);
378         }
379 
380         if (isReadOnly())
381         {
382             buffer.append("The value of this field cannot be changed, it is read-only");
383             buffer.append(crlf);
384         }
385 
386         if (isValidatorBoolean())
387         {
388             buffer.append("The value of this field should reflect a ")
389                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
390                 .append("target=\"_jdk\">boolean</a> value");
391             buffer.append(crlf);
392         }
393         else if (isValidatorByte())
394         {
395             buffer.append("The value of this field should reflect a ")
396                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
397                 .append("target=\"_jdk\">byte</a> value");
398             buffer.append(crlf);
399         }
400         else if (isValidatorChar())
401         {
402             buffer.append("The value of this field should reflect a ")
403                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
404                 .append("target=\"_jdk\">character</a> value");
405             buffer.append(crlf);
406         }
407         else if (isValidatorDouble())
408         {
409             buffer.append("The value of this field should reflect a ")
410                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
411                 .append("target=\"_jdk\">double precision integer</a> value");
412             buffer.append(crlf);
413         }
414         else if (isValidatorFloat())
415         {
416             buffer.append("The value of this field should reflect a ")
417                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
418                 .append("target=\"_jdk\">floating point</a> value");
419             buffer.append(crlf);
420         }
421         else if (isValidatorInteger())
422         {
423             buffer.append("The value of this field should reflect a ")
424                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
425                 .append("target=\"_jdk\">integer</a> value");
426             buffer.append(crlf);
427         }
428         else if (isValidatorLong())
429         {
430             buffer.append("The value of this field should reflect a ")
431                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
432                 .append("target=\"_jdk\">long integer</a> value");
433             buffer.append(crlf);
434         }
435         else if (isValidatorShort())
436         {
437             buffer.append("The value of this field should reflect a ")
438                 .append("<a href=\"http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html\" ")
439                 .append("target=\"_jdk\">short integer</a> value");
440             buffer.append(crlf);
441         }
442         else if (isValidatorUrl())
443         {
444             buffer.append("The value of this field should reflect a ")
445                 .append("<a href=\"http://java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html\" ")
446                 .append("target=\"_jdk\">URL</a> value");
447             buffer.append(crlf);
448         }
449 
450         return StringUtilsHelper.toResourceMessage(buffer.toString());
451     }
452 
453     protected boolean handleIsCalendarRequired()
454     {
455         return isDate() && String.valueOf(findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_CALENDAR)).equals("true");
456     }
457 
458     /**
459      * Overridden since StrutsAction does not extend FrontEndAction.
460      *
461      * @see org.andromda.metafacades.uml.FrontEndParameter#isActionParameter()
462      */
463     public boolean isActionParameter()
464     {
465         final StrutsAction action = getStrutsAction();
466         return (action != null) && action.getActionParameters().contains(this);
467     }
468 
469     protected String handleGetCollectionImplementationType()
470     {
471         String typeName = null;
472 
473         final ClassifierFacade type = this.getType();
474         if (type != null)
475         {
476             if (type.isCollectionType() || type.isListType())
477             {
478                 typeName = "java.util.ArrayList";
479             }
480             else if (type.isSetType())
481             {
482                 typeName = "java.util.HashSet";
483             }
484             else
485             {
486                 typeName = type.getFullyQualifiedName();
487             }
488         }
489         return typeName;
490     }
491 
492     protected boolean handleIsTableDecoratorRequired()
493     {
494         boolean required = false;
495 
496         if (isTable())
497         {
498             final Object taggedValue = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_TABLE_DECORATOR);
499             if (taggedValue != null)
500             {
501                 final String taggedValueString = String.valueOf(taggedValue);
502                 required = Boolean.valueOf(taggedValueString).booleanValue();
503             }
504             else
505             {
506                 final Object property = getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_GENERATE_TABLE_DECORATORS);
507                 final String propertyString = String.valueOf(property);
508                 required = Boolean.valueOf(propertyString).booleanValue();
509             }
510         }
511 
512         return required;
513     }
514     
515     /**
516      * Override to not allow selectable parameters to be considered tables.
517      * 
518      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameterLogic#isTable()
519      */
520     public boolean isTable()
521     {
522         return super.isTable() && !this.isSelectable() && !this.isHiddenField();
523     }
524 
525     protected boolean handleIsAllGlobalTableActionsHaveSameParameter()
526     {
527         boolean sameParameter = true;
528 
529         String name = null;
530         String type = null;
531 
532         final Collection actions = this.getTableGlobalActions();
533         for (final Iterator actionIterator = actions.iterator(); actionIterator.hasNext() && sameParameter;)
534         {
535             final StrutsAction action = (StrutsAction)actionIterator.next();
536             final List parameters = action.getActionParameters();
537             if (!parameters.isEmpty())
538             {
539                 final StrutsParameter parameter = (StrutsParameter)parameters.iterator().next();
540                 if (name == null || type == null)
541                 {
542                     name = parameter.getName();
543                     type = parameter.getType().getFullyQualifiedName();
544                 }
545                 else
546                 {
547                     sameParameter = name.equals(parameter.getName()) &&
548                         type.equals(parameter.getType().getFullyQualifiedName());
549                 }
550             }
551         }
552 
553         return sameParameter;
554     }
555 
556     protected List handleGetTableFormActions()
557     {
558         return this.internalGetTableActions(false, true, false);
559     }
560 
561     protected List handleGetTableHyperlinkActions()
562     {
563         return this.internalGetTableActions(true, false, false);
564     }
565 
566     protected Collection handleGetTableGlobalActions()
567     {
568         return this.internalGetTableActions(false, false, true);
569     }
570 
571     protected Object handleGetTableGlobalActionParameter()
572     {
573         Object parameter = null;
574 
575         final Collection actions = this.getTableGlobalActions();
576         if (!actions.isEmpty())
577         {
578             final List actionParameters = ((StrutsAction)actions.iterator().next()).getActionParameters();
579             if (!actionParameters.isEmpty())
580             {
581                 parameter = actionParameters.iterator().next();
582             }
583         }
584 
585         return parameter;
586     }
587 
588     protected boolean handleIsTableFormActionSharingWidgets()
589     {
590         // @todo (wouter)
591         return true;
592     }
593 
594     /**
595      * If this is a table this method returns all those actions that are declared to work
596      * on this table.
597      */
598     private List internalGetTableActions(boolean hyperlink,
599                                          boolean formPost,
600                                          boolean tableAction)
601     {
602         final String name = StringUtils.trimToNull(getName());
603         if (name == null || !isTable())
604         {
605             return Collections.EMPTY_LIST;
606         }
607 
608         final StrutsJsp page = this.getJsp();
609 
610         final Collection tableActions = new LinkedHashSet();
611 
612         final Collection allUseCases = getModel().getAllUseCases();
613         for (final Iterator useCaseIterator = allUseCases.iterator(); useCaseIterator.hasNext();)
614         {
615             final UseCaseFacade useCase = (UseCaseFacade)useCaseIterator.next();
616             if (useCase instanceof StrutsUseCase)
617             {
618                 final FrontEndActivityGraph graph = ((StrutsUseCase)useCase).getActivityGraph();
619                 if (graph != null)
620                 {
621                     final Collection transitions = graph.getTransitions();
622                     for (final Iterator transitionIterator = transitions.iterator(); transitionIterator.hasNext();)
623                     {
624                         final TransitionFacade transition = (TransitionFacade)transitionIterator.next();
625                         if (transition.getSource().equals(page) && transition instanceof StrutsAction)
626                         {
627                             final StrutsAction action = (StrutsAction)transition;
628                             if (action.isTableLink() && name.equals(action.getTableLinkName()))
629                             {
630                                 if ((hyperlink && action.isHyperlink()) ||
631                                     (formPost && action.isFormPost()) ||
632                                     (tableAction && action.isTableAction()))
633                                 {
634                                     tableActions.add(action);
635                                 }
636                             }
637                         }
638                     }
639                 }
640             }
641         }
642         return new ArrayList(tableActions);
643     }
644 
645     protected String handleGetTableDecoratorFullyQualifiedName()
646     {
647         String name = getTableDecoratorPackageName();
648         name = (StringUtils.trimToEmpty(name) == null) ? "" : name + '.';
649         return name + getTableDecoratorClassName();
650     }
651 
652     protected String handleGetTableDecoratorPackageName()
653     {
654         final StrutsJsp jsp = getJsp();
655         return (jsp == null) ? null : jsp.getPackageName();
656     }
657 
658     protected String handleGetTableDecoratorClassName()
659     {
660         String tableDecoratorClassName = null;
661 
662         final StrutsJsp jsp = getJsp();
663         if (jsp != null)
664         {
665             String suffix = String.valueOf(getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_TABLE_DECORATOR_SUFFIX));
666             tableDecoratorClassName = StringUtilsHelper.upperCamelCaseName(getName()) + suffix;
667         }
668 
669         return tableDecoratorClassName;
670     }
671 
672     protected String handleGetTableDecoratorFullPath()
673     {
674         return getTableDecoratorFullyQualifiedName().replace('.', '/');
675     }
676 
677     protected String handleGetTableExportTypes()
678     {
679         return Bpm4StrutsUtils.getDisplayTagExportTypes(
680             this.findTaggedValues(Bpm4StrutsProfile.TAGGEDVALUE_TABLE_EXPORT),
681             (String)getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_DEFAULT_TABLE_EXPORT_TYPES) );
682     }
683 
684     protected boolean handleIsTableExportable()
685     {
686         return this.getTableExportTypes().indexOf("none") == -1;
687     }
688 
689     protected boolean handleIsTableSortable()
690     {
691         final Object taggedValue = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_TABLE_SORTABLE);
692         return (taggedValue == null)
693             ? Bpm4StrutsProfile.TAGGEDVALUE_TABLE_SORTABLE_DEFAULT_VALUE
694             : Bpm4StrutsUtils.isTrue(String.valueOf(taggedValue));
695     }
696 
697     protected boolean handleIsTableHyperlinkColumn()
698     {
699         boolean tableHyperlinkColumn = false;
700 
701         final String name = this.getName();
702         if (name != null)
703         {
704             // this parameter's action must be a table hyperlink
705             final StrutsAction action = this.getStrutsAction();
706             if (action.isHyperlink() && action.isTableLink())
707             {
708                 // get the table and check whether this parameter is part of that table's columns
709                 final StrutsParameter table = action.getTableLinkParameter();
710                 if (table != null)
711                 {
712                     final Collection tableColumns = table.getTableColumns();
713                     // if this parameter's name matches that targetted column name then we have found our column
714                     tableHyperlinkColumn = tableColumns.contains(this) && name.equals(action.getTableLinkColumnName());
715                 }
716             }
717         }
718 
719         return tableHyperlinkColumn;
720     }
721 
722     protected List handleGetTableColumnActions(final String columnName)
723     {
724         final List columnActions = new ArrayList();
725 
726         if (columnName != null)
727         {
728             // only hyperlinks can target table columns
729             final List hyperlinkActions = this.getTableHyperlinkActions();
730             for (int i = 0; i < hyperlinkActions.size(); i++)
731             {
732                 final StrutsAction action = (StrutsAction)hyperlinkActions.get(i);
733                 if (columnName.equals(action.getTableLinkColumnName()))
734                 {
735                     columnActions.add(action);
736                 }
737             }
738         }
739 
740         return columnActions;
741     }
742 
743     /**
744      * @return true if this parameter represents a table and is an array of custom types (no datatype)
745      */
746     private boolean isCustomArrayTable()
747     {
748         final ClassifierFacade type = this.getType();
749         return type != null && this.isTable() && type.isArrayType() && !type.isDataType();
750     }
751 
752     /**
753      * Overridden since StrutsAction doesn't extend FrontEndAction.
754      * 
755      * @see org.andromda.metafacades.uml.FrontEndParameter#getTableColumns()
756      */
757     public Collection getTableColumns()
758     {
759         // in this method we collect the elements that represent the columns of a table
760         // if no specific element (parameter, attribute) can be found a simple String instance
761         // is used
762         // the event parameters have priority to be included in the collection because
763         // they contain additional information such as validation constraint and widget type, ...
764 
765         // try to preserve the order of the elements encountered
766         final Map tableColumnsMap = new LinkedHashMap();
767 
768         // order is important
769         final List actions = new ArrayList();
770 
771         // all table actions need the exact same parameters, just not always all of them
772         actions.addAll(this.getTableFormActions());
773         // if there are any actions that are hyperlinks then their parameters get priority
774         // the user should not have modeled it that way (constraints will warn him/her)
775         actions.addAll(this.getTableHyperlinkActions());
776 
777         for (final Iterator actionIterator = actions.iterator(); actionIterator.hasNext();)
778         {
779             final StrutsAction action = (StrutsAction)actionIterator.next();
780             final Collection actionParameters = action.getActionParameters();
781             for (final Iterator parameterIterator = actionParameters.iterator(); parameterIterator.hasNext();)
782             {
783                 final StrutsParameter parameter = (StrutsParameter)parameterIterator.next();
784                 final String parameterName = parameter.getName();
785                 if (parameterName != null)
786                 {
787                     // never overwrite column specific table links
788                     // the hyperlink table links working on a real column get priority
789                     final StrutsParameter existingParameter = (StrutsParameter)tableColumnsMap.get(parameterName);
790                     if (existingParameter == null ||
791                         (action.isHyperlink() && parameterName.equals(action.getTableLinkColumnName())))
792                     {
793                         tableColumnsMap.put(parameterName, parameter);
794                     }
795                 }
796             }
797         }
798 
799         final Collection columnNames = this.getTableColumnNames();
800 
801         // in case of a custom array just add the attributes
802         if (this.isCustomArrayTable())
803         {
804             final Collection attributes = this.getType().getNonArray().getAttributes(true);
805             for (final Iterator attributeIterator = attributes.iterator(); attributeIterator.hasNext();)
806             {
807                 final ModelElementFacade attribute = (ModelElementFacade)attributeIterator.next();
808                 // don't override
809                 if (!tableColumnsMap.containsKey(attribute.getName()))
810                 {
811                     tableColumnsMap.put(attribute.getName(), attribute);
812                 }
813             }
814         }
815         else
816         {
817             for (final Iterator columnNameIterator = columnNames.iterator(); columnNameIterator.hasNext();)
818             {
819                 final String columnName = (String)columnNameIterator.next();
820                 // don't override
821                 if (!tableColumnsMap.containsKey(columnName))
822                 {
823                     tableColumnsMap.put(columnName, columnName);
824                 }
825             }
826         }
827 
828         // return everything in the same order as it has been modeled (using the table tagged value)
829         // note that only those columns mentioned in the tagged value are returned
830         final Collection tableColumns = new ArrayList();
831         for (final Iterator columnNameIterator = columnNames.iterator(); columnNameIterator.hasNext();)
832         {
833             final Object columnObject = columnNameIterator.next();
834             tableColumns.add(tableColumnsMap.get(columnObject));
835         }
836         return tableColumns;
837     }
838 
839     protected String handleGetTableColumnMessageKey(String columnName)
840     {
841         StringBuffer messageKey = null;
842 
843         if (isTable())
844         {
845             messageKey = new StringBuffer();
846 
847             if (!normalizeMessages())
848             {
849                 final StrutsJsp page = getJsp();
850                 if (page != null)
851                 {
852                     messageKey.append(getMessageKey());
853                     messageKey.append('.');
854                 }
855             }
856 
857             messageKey.append(StringUtilsHelper.toResourceMessageKey(columnName));
858         }
859 
860         return (messageKey == null) ? null : messageKey.toString();
861     }
862 
863     protected String handleGetTableColumnMessageValue(String columnName)
864     {
865         return (isTable()) ? StringUtilsHelper.toPhrase(columnName) : null;
866     }
867 
868     protected int handleGetTableMaxRows()
869     {
870         final Object taggedValue = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_TABLE_MAXROWS);
871         int pageSize;
872 
873         try
874         {
875             pageSize = Integer.parseInt(String.valueOf(taggedValue));
876         }
877         catch (Exception e)
878         {
879             pageSize = Bpm4StrutsProfile.TAGGEDVALUE_TABLE_MAXROWS_DEFAULT_COUNT;
880         }
881 
882         return pageSize;
883     }
884 
885     protected String handleGetWidgetType()
886     {
887         Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE);
888         final String fieldType = value == null ? null : value.toString();
889 
890         String widgetType = null;
891 
892         if (isActionParameter())
893         {
894             if (fieldType == null)
895             {
896                 // no widget type has been specified
897                 final ClassifierFacade type = getType();
898                 if (type != null)
899                 {
900                     if (type.isFileType()) widgetType = Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_FILE;
901                     else if (isValidatorBoolean()) widgetType = Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_CHECKBOX;
902                     else if (isMultiple()) widgetType = Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_SELECT;
903                     else widgetType = Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_TEXT;
904                 }
905             }
906             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_SELECT.equalsIgnoreCase(fieldType))
907             {
908                 widgetType = "select";
909             }
910             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_PASSWORD.equalsIgnoreCase(fieldType))
911             {
912                 widgetType = "password";
913             }
914             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_TEXTAREA.equalsIgnoreCase(fieldType))
915             {
916                 widgetType = "textarea";
917             }
918             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_HIDDEN.equalsIgnoreCase(fieldType))
919             {
920                 widgetType = HIDDEN_INPUT_TYPE;
921             }
922             else if (fieldType.toLowerCase().startsWith(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_RADIO))
923             {
924                 widgetType = "radio";
925             }
926             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_CHECKBOX.equalsIgnoreCase(fieldType))
927             {
928                 widgetType = "checkbox";
929             }
930             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_PLAINTEXT.equalsIgnoreCase(fieldType))
931             {
932                 widgetType = "plaintext";
933             }
934             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_TEXT.equalsIgnoreCase(fieldType))
935             {
936                 widgetType = "text";
937             }
938             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_MULTIBOX.equalsIgnoreCase(fieldType))
939             {
940                 if (getMultiboxPropertyName() != null)
941                 {
942                     widgetType = "multibox";
943                 }
944             }
945             else if (Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_LINK.equalsIgnoreCase(fieldType))
946             {
947                 final StrutsAction action = getStrutsAction();
948                 if (action != null)
949                 {
950                     if (action.isTableLink())
951                     {
952                         widgetType = "link";
953                     }
954                 }
955             }
956             else
957             {
958                 widgetType = (isMultiple()) ? "select" : "text";
959             }
960         }
961         return widgetType;
962     }
963 
964     /**
965      * The input type representing a 'hidden' parameter.
966      */
967     static final String HIDDEN_INPUT_TYPE = "hidden";
968 
969     protected boolean handleIsFile()
970     {
971         boolean file = false;
972 
973         ClassifierFacade type = getType();
974         if (type != null)
975         {
976             file = type.isFileType();
977         }
978         return file;
979     }
980 
981     protected boolean handleIsMultiple()
982     {
983         boolean multiple = false;
984 
985         ClassifierFacade type = getType();
986         if (type != null)
987         {
988             multiple = type.isCollectionType() || type.isArrayType();
989         }
990         return multiple;
991     }
992 
993     protected String handleGetBackingListName()
994     {
995         return getName() + "BackingList";
996     }
997 
998     protected String handleGetValueListResetValue()
999     {
1000         return constructArray();
1001     }
1002 
1003     protected boolean handleIsSelectable()
1004     {
1005         boolean selectable = false;
1006 
1007         if (isActionParameter())
1008         {
1009             selectable = Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_SELECT.equals(getWidgetType());
1010             final ClassifierFacade type = getType();
1011 
1012             if (!selectable && type != null)
1013             {
1014                 final String name = getName();
1015                 final String typeName = type.getFullyQualifiedName();
1016 
1017                 /**
1018                  * if the parameter is not selectable but on a targetting page it _is_ selectable we must
1019                  * allow the user to set the backing list too
1020                  */
1021                 final Collection pages = getStrutsAction().getTargetPages();
1022                 for (final Iterator pageIterator = pages.iterator(); pageIterator.hasNext() && !selectable;)
1023                 {
1024                     final StrutsJsp page = (StrutsJsp)pageIterator.next();
1025                     final Collection parameters = page.getAllActionParameters();
1026                     for (final Iterator parameterIterator = parameters.iterator();
1027                          parameterIterator.hasNext() && !selectable;)
1028                     {
1029                         final StrutsParameter parameter = (StrutsParameter)parameterIterator.next();
1030                         final String parameterName = parameter.getName();
1031                         final ClassifierFacade parameterType = parameter.getType();
1032                         if (parameterType != null)
1033                         {
1034                             final String parameterTypeName = parameterType.getFullyQualifiedName();
1035                             if (name.equals(parameterName) && typeName.equals(parameterTypeName))
1036                             {
1037                                 selectable = Bpm4StrutsProfile.TAGGEDVALUE_INPUT_TYPE_SELECT
1038                                     .equals(parameter.getWidgetType());
1039                             }
1040                         }
1041                     }
1042                 }
1043             }
1044         }
1045         else if (isControllerOperationArgument())
1046         {
1047             final String name = this.getName();
1048             final Collection actions = this.getControllerOperation().getDeferringActions();
1049             for (final Iterator actionIterator = actions.iterator(); actionIterator.hasNext();)
1050             {
1051                 final StrutsAction action = (StrutsAction)actionIterator.next();
1052                 final Collection formFields = action.getActionFormFields();
1053                 for (final Iterator fieldIterator = formFields.iterator(); fieldIterator.hasNext() && !selectable;)
1054                 {
1055                     final StrutsParameter parameter = (StrutsParameter)fieldIterator.next();
1056                     if (name.equals(parameter.getName()))
1057                     {
1058                         selectable = parameter.isSelectable();
1059                     }
1060                 }
1061             }
1062         }
1063         return selectable;
1064     }
1065 
1066     /**
1067      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getValueListName()
1068      */
1069     protected String handleGetValueListName()
1070     {
1071         return getName() + "ValueList";
1072     }
1073 
1074     /**
1075      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getLabelListName()
1076      */
1077     protected String handleGetLabelListName()
1078     {
1079         return getName() + "LabelList";
1080     }
1081 
1082     /**
1083      * @return A String representing Java code for the initialization of an array using 5 elements.
1084      */
1085     private String constructArray()
1086     {
1087         final String name = getName();
1088         return "new Object[] {\"" +
1089             name +
1090             "-1\", \"" +
1091             name +
1092             "-2\", \"" +
1093             name +
1094             "-3\", \"" +
1095             name +
1096             "-4\", \"" +
1097             name +
1098             "-5\"}";
1099     }
1100 
1101     /**
1102      * Override normal parameter facade required implementation.
1103      *
1104      * @see org.andromda.metafacades.uml.ParameterFacade#isRequired()
1105      */
1106     public boolean isRequired()
1107     {
1108         final Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_REQUIRED);
1109         return Bpm4StrutsUtils.isTrue(value == null ? null : String.valueOf(value));
1110     }
1111 
1112     /**
1113      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#isReadOnly()
1114      */
1115     protected boolean handleIsReadOnly()
1116     {
1117         final Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_READONLY);
1118         return Bpm4StrutsUtils.isTrue(value == null ? null : String.valueOf(value));
1119     }
1120 
1121     /**
1122      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#isDate()
1123      */
1124     protected boolean handleIsDate()
1125     {
1126         return this.isValidatorDate();
1127     }
1128 
1129     /**
1130      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getDateFormat()
1131      */
1132     protected String handleGetDateFormat()
1133     {
1134         final String format = this.getValidatorFormat();
1135         return format == null ? this.getDefaultDateFormat() : this.getDateFormat(format);
1136     }
1137 
1138     /**
1139      * @return the default date format pattern as defined using the configured property
1140      */
1141     private String getDefaultDateFormat()
1142     {
1143         return (String)getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_DEFAULT_DATEFORMAT);
1144     }
1145 
1146     /**
1147      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getTimeFormat()
1148      */
1149     protected String handleGetTimeFormat()
1150     {
1151         final String format = this.getValidatorFormat();
1152         return format == null ? this.getDefaultTimeFormat() : format;
1153     }
1154 
1155     /**
1156      * @return the default time format pattern as defined using the configured property
1157      */
1158     private String getDefaultTimeFormat()
1159     {
1160         return (String)this.getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_DEFAULT_TIMEFORMAT);
1161     }
1162 
1163     /**
1164      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#isStrictDateFormat()
1165      */
1166     protected boolean handleIsStrictDateFormat()
1167     {
1168         final String format = this.getValidatorFormat();
1169         return format == null 
1170             ? Bpm4StrutsUtils.isTrue((String)this.getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_STRICT_DATETIMEFORMAT))
1171             : this.isStrictDateFormat(format);
1172     }
1173 
1174     /**
1175      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getResetValue()
1176      */
1177     protected String handleGetResetValue()
1178     {
1179         final ClassifierFacade type = getType();
1180         if (type != null)
1181         {
1182             final String name = getName();
1183 
1184             if (isValidatorString()) return "\"" + name + "-test" + "\"";
1185             if (isValidatorDate()) return "new java.util.Date()";
1186 
1187             if (type.isPrimitive())
1188             {
1189                 if (isValidatorInteger()) return "(int)" + name.hashCode();
1190                 if (isValidatorBoolean()) return "false";
1191                 if (isValidatorLong()) return "(long)" + name.hashCode();
1192                 if (isValidatorChar()) return "(char)" + name.hashCode();
1193                 if (isValidatorFloat()) return "(float)" + name.hashCode();
1194                 if (isValidatorDouble()) return "(double)" + name.hashCode();
1195                 if (isValidatorShort()) return "(short)" + name.hashCode();
1196                 if (isValidatorByte()) return "(byte)" + name.hashCode();
1197             }
1198             else
1199             {
1200                 if (isValidatorInteger()) return "new Integer((int)" + name.hashCode() + ")";
1201                 if (isValidatorBoolean()) return "Boolean.FALSE";
1202                 if (isValidatorLong()) return "new Long((long)" + name.hashCode() + ")";
1203                 if (isValidatorChar()) return "new Character(char)" + name.hashCode() + ")";
1204                 if (isValidatorFloat()) return "new Float((float)" + name.hashCode() + ")";
1205                 if (isValidatorDouble()) return "new Double((double)" + name.hashCode() + ")";
1206                 if (isValidatorShort()) return "new Short((short)" + name.hashCode() + ")";
1207                 if (isValidatorByte()) return "new Byte((byte)" + name.hashCode() + ")";
1208             }
1209 
1210             if (type.isArrayType()) return constructArray();
1211             if (type.isSetType()) return "new java.util.HashSet(java.util.Arrays.asList(" + constructArray() + "))";
1212             if (type.isCollectionType()) return "java.util.Arrays.asList(" + constructArray() + ")";
1213 
1214             // maps and others types will simply not be treated
1215         }
1216         return "null";
1217     }
1218 
1219     /**
1220      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#isValidationRequired()
1221      */
1222     protected boolean handleIsValidationRequired()
1223     {
1224         final String disableValidationForHiddenFormFields = (String)getConfiguredProperty(Bpm4StrutsGlobals.DISABLE_VALIDATION_FOR_HIDDEN_FORM_FIELDS);
1225         return !("true".equals(disableValidationForHiddenFormFields) && "hidden".equals(getWidgetType())) &&
1226             !getValidatorTypes().isEmpty();
1227     }
1228 
1229     private String getValidatorFormat()
1230     {
1231         Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_FORMAT);
1232         final String format = value == null ? null : String.valueOf(value);
1233         return (format == null) ? null : format.trim();
1234     }
1235 
1236     protected java.util.Collection handleGetValidatorTypes()
1237     {
1238         final Collection validatorTypesList = new ArrayList();
1239 
1240         ClassifierFacade type = getType();
1241         if (type != null)
1242         {
1243             final String format = getValidatorFormat();
1244             final boolean isRangeFormat = (format != null) && isRangeFormat(format);
1245 
1246             if (isRequired()) validatorTypesList.add("required");
1247 
1248             if (isValidatorByte()) validatorTypesList.add("byte");
1249             else if (isValidatorShort()) validatorTypesList.add("short");
1250             else if (isValidatorInteger()) validatorTypesList.add("integer");
1251             else if (isValidatorLong()) validatorTypesList.add("long");
1252             else if (isValidatorFloat()) validatorTypesList.add("float");
1253             else if (isValidatorDouble()) validatorTypesList.add("double");
1254             else if (isValidatorDate()) validatorTypesList.add("date");
1255             else if (isValidatorTime()) validatorTypesList.add("time");
1256             else if (isValidatorUrl()) validatorTypesList.add("url");
1257 
1258             if (isRangeFormat)
1259             {
1260                 if (isValidatorInteger() || isValidatorShort() || isValidatorLong()) validatorTypesList.add("intRange");
1261                 if (isValidatorFloat()) validatorTypesList.add("floatRange");
1262                 if (isValidatorDouble()) validatorTypesList.add("doubleRange");
1263             }
1264 
1265             if (format != null)
1266             {
1267                 if (isValidatorString() && isEmailFormat(format)) validatorTypesList.add("email");
1268                 else if (isValidatorString() && isCreditCardFormat(format)) validatorTypesList.add("creditCard");
1269                 else
1270                 {
1271                     Collection formats = findTaggedValues(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_FORMAT);
1272                     for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();)
1273                     {
1274                         String additionalFormat = String.valueOf(formatIterator.next());
1275                         if (isMinLengthFormat(additionalFormat)) validatorTypesList.add("minlength");
1276                         else if (isMaxLengthFormat(additionalFormat)) validatorTypesList.add("maxlength");
1277                         else if (isPatternFormat(additionalFormat)) validatorTypesList.add("mask");
1278                     }
1279                 }
1280             }
1281 
1282             if (getValidWhen() != null)
1283             {
1284                 validatorTypesList.add("validwhen");
1285             }
1286         }
1287 
1288         // custom (paramterized) validators are allowed here
1289         Collection taggedValues = findTaggedValues(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_VALIDATORS);
1290         for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();)
1291         {
1292             String validator = String.valueOf(iterator.next());
1293             validatorTypesList.add(Bpm4StrutsUtils.parseValidatorName(validator));
1294         }
1295 
1296         return validatorTypesList;
1297     }
1298 
1299     /**
1300      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getValidatorMsgKey()
1301      */
1302     protected String handleGetValidatorMsgKey()
1303     {
1304         return getMessageKey();
1305     }
1306 
1307     /**
1308      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getValidatorArgs(java.lang.String)
1309      */
1310     protected java.util.Collection handleGetValidatorArgs(java.lang.String validatorType)
1311     {
1312         final Collection args = new ArrayList();
1313         if ("intRange".equals(validatorType) ||
1314             "floatRange".equals(validatorType) ||
1315             "doubleRange".equals(validatorType))
1316         {
1317             args.add("${var:min}");
1318             args.add("${var:max}");
1319         }
1320         else if ("minlength".equals(validatorType))
1321         {
1322             args.add("${var:minlength}");
1323         }
1324         else if ("maxlength".equals(validatorType))
1325         {
1326             args.add("${var:maxlength}");
1327         }
1328         else if ("date".equals(validatorType))
1329         {
1330             final String validatorFormat = getValidatorFormat();
1331             if (validatorFormat != null && isStrictDateFormat(validatorFormat))
1332             {
1333                 args.add("${var:datePatternStrict}");
1334             }
1335             else
1336             {
1337                 args.add("${var:datePattern}");
1338             }
1339         }
1340         else if ("time".equals(validatorType))
1341         {
1342             args.add("${var:timePattern}");
1343         }
1344 
1345         // custom (paramterized) validators are allowed here
1346         Collection taggedValues = findTaggedValues(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_VALIDATORS);
1347         for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();)
1348         {
1349             String validator = String.valueOf(iterator.next());
1350             if (validatorType.equals(Bpm4StrutsUtils.parseValidatorName(validator)))
1351             {
1352                 args.addAll(Bpm4StrutsUtils.parseValidatorArgs(validator));
1353             }
1354         }
1355 
1356         return args;
1357     }
1358     
1359     /**
1360      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getValidatorVars()
1361      */
1362     protected java.util.Collection handleGetValidatorVars()
1363     {
1364         final Map vars = new LinkedHashMap();
1365 
1366         final ClassifierFacade type = getType();
1367         if (type != null)
1368         {
1369             final String format = getValidatorFormat();
1370             if (format != null)
1371             {
1372                 final boolean isRangeFormat = isRangeFormat(format);
1373 
1374                 if (isRangeFormat)
1375                 {
1376                     vars.put("min", Arrays.asList(new Object[]{"min", getRangeStart(format)}));
1377                     vars.put("max", Arrays.asList(new Object[]{"max", getRangeEnd(format)}));
1378                 }
1379                 else
1380                 {
1381                     final Collection formats = findTaggedValues(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_FORMAT);
1382                     for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();)
1383                     {
1384                         final String additionalFormat = String.valueOf(formatIterator.next());
1385                         if (isMinLengthFormat(additionalFormat)) vars.put("minlength",
1386                             Arrays.asList(new Object[]{"minlength", this.getMinLengthValue(additionalFormat)}));
1387                         else if (isMaxLengthFormat(additionalFormat)) vars.put("maxlength",
1388                             Arrays.asList(new Object[]{"maxlength", this.getMaxLengthValue(additionalFormat)}));
1389                         else if (isPatternFormat(additionalFormat)) vars
1390                             .put("mask", Arrays.asList(new Object[]{"mask", this.getPatternValue(additionalFormat)}));
1391                     }
1392                 }
1393             }
1394             if (isValidatorDate())
1395             {
1396                 if (format != null && isStrictDateFormat(format))
1397                 {
1398                     vars.put("datePatternStrict",
1399                         Arrays.asList(new Object[]{"datePatternStrict", this.getDateFormat()}));
1400                 }
1401                 else
1402                 {
1403                     vars.put("datePattern", Arrays.asList(new Object[]{"datePattern", this.getDateFormat()}));
1404                 }
1405             }
1406             if (this.isValidatorTime())
1407             {
1408                 vars.put("timePattern", Arrays.asList(new Object[]{"timePattern", this.getTimeFormat()}));
1409             }
1410 
1411             final String validWhen = getValidWhen();
1412             if (validWhen != null)
1413             {
1414                 vars.put("test", Arrays.asList(new Object[]{"test", validWhen}));
1415             }
1416         }
1417 
1418         // custom (paramterized) validators are allowed here
1419         // in this case we will reuse the validator arg values
1420         Collection taggedValues = findTaggedValues(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_VALIDATORS);
1421         for (final Iterator iterator = taggedValues.iterator(); iterator.hasNext();)
1422         {
1423             String validator = String.valueOf(iterator.next());
1424 
1425             // guaranteed to be of the same length
1426             List validatorVars = Bpm4StrutsUtils.parseValidatorVars(validator);
1427             List validatorArgs = Bpm4StrutsUtils.parseValidatorArgs(validator);
1428 
1429             for (int i = 0; i < validatorVars.size(); i++)
1430             {
1431                 String validatorVar = (String)validatorVars.get(i);
1432                 String validatorArg = (String)validatorArgs.get(i);
1433 
1434                 vars.put(validatorVar, Arrays.asList(new Object[]{validatorVar, validatorArg}));
1435             }
1436         }
1437 
1438         return vars.values();
1439     }
1440 
1441     /**
1442      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getValidWhen()
1443      */
1444     protected java.lang.String handleGetValidWhen()
1445     {
1446         final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_VALIDWHEN);
1447         return value == null ? null : '(' + value.toString() + ')';
1448     }
1449 
1450     /**
1451      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getMultiboxPropertyName()
1452      */
1453     protected String handleGetMultiboxPropertyName()
1454     {
1455         Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_MULTIBOX);
1456         return (value == null) ? null : StringUtils.trimToNull(value.toString());
1457     }
1458 
1459     /**
1460      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getOptionKeys()
1461      */
1462     protected List handleGetOptionKeys()
1463     {
1464         final String key = getMessageKey() + '.';
1465         final List optionKeys = new ArrayList();
1466         final int optionCount = getOptionCount();
1467         for (int i = 0; i < optionCount; i++)
1468             optionKeys.add(key + i);
1469         return optionKeys;
1470     }
1471 
1472     /**
1473      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsParameter#getOptionValues()
1474      */
1475     protected List handleGetOptionValues()
1476     {
1477         final List optionValues = new ArrayList();
1478         final Object taggedValueObject = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_INPUT_RADIO);
1479 
1480         if (taggedValueObject == null)
1481         {
1482             // we resort to the default values
1483             optionValues.add("0");
1484             optionValues.add("1");
1485             optionValues.add("2");
1486         }
1487         else
1488         {
1489             final String taggedValue = String.valueOf(taggedValueObject).trim();
1490 
1491             int optionCount;
1492             try
1493             {
1494                 optionCount = Integer.parseInt(taggedValue);
1495                 for (int i = 0; i < optionCount; i++)
1496                 {
1497                     optionValues.add(String.valueOf(i));
1498                 }
1499             }
1500             catch (Exception exception)
1501             {
1502                 // this means the value wasn't a valid integer, we'll interpret it is a comma-separated
1503                 // list of option-values
1504                 final String[] options = taggedValue.split("[,]");
1505                 for (int i = 0; i < options.length; i++)
1506                 {