View Javadoc
1   package org.andromda.cartridges.jsf.metafacades;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.HashMap;
6   import java.util.HashSet;
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  import java.util.Set;
13  import org.andromda.cartridges.jsf.JSFGlobals;
14  import org.andromda.cartridges.jsf.JSFProfile;
15  import org.andromda.cartridges.jsf.JSFUtils;
16  import org.andromda.metafacades.uml.AssociationEndFacade;
17  import org.andromda.metafacades.uml.AttributeFacade;
18  import org.andromda.metafacades.uml.ClassifierFacade;
19  import org.andromda.metafacades.uml.EventFacade;
20  import org.andromda.metafacades.uml.FrontEndAction;
21  import org.andromda.metafacades.uml.FrontEndActivityGraph;
22  import org.andromda.metafacades.uml.FrontEndForward;
23  import org.andromda.metafacades.uml.FrontEndParameter;
24  import org.andromda.metafacades.uml.FrontEndView;
25  import org.andromda.metafacades.uml.ModelElementFacade;
26  import org.andromda.metafacades.uml.TransitionFacade;
27  import org.andromda.metafacades.uml.UseCaseFacade;
28  import org.andromda.utils.StringUtilsHelper;
29  import org.apache.commons.lang.ObjectUtils;
30  import org.apache.commons.lang.StringUtils;
31  
32  /**
33   * MetafacadeLogic implementation for org.andromda.cartridges.jsf.metafacades.JSFParameter.
34   *
35   * @see org.andromda.cartridges.jsf.metafacades.JSFParameter
36   */
37  public class JSFParameterLogicImpl
38      extends JSFParameterLogic
39  {
40      private static final long serialVersionUID = 34L;
41      /**
42       * @param metaObject
43       * @param context
44       */
45      public JSFParameterLogicImpl(
46          Object metaObject,
47          String context)
48      {
49          super(metaObject, context);
50      }
51  
52      /**
53       * Overridden to make sure it's not an inputTable.
54       *
55       * @see org.andromda.metafacades.uml.FrontEndParameter#isTable()
56       */
57      public boolean isTable()
58      {
59          return (super.isTable() || this.isPageableTable()) && !this.isSelectable()
60              && !this.isInputTable() && !this.isInputHidden();
61      }
62  
63      /**
64       * @return isPageableTable
65       * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isPageableTable()
66       */
67      protected boolean handleIsPageableTable()
68      {
69          final Object value = this.findTaggedValue(JSFProfile.TAGGEDVALUE_TABLE_PAGEABLE);
70          return Boolean.valueOf(ObjectUtils.toString(value)).booleanValue();
71      }
72  
73      /**
74       * @return messageKey
75       * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMessageKey()
76       */
77      protected String handleGetMessageKey()
78      {
79          final StringBuilder messageKey = new StringBuilder();
80  
81          if (!this.isNormalizeMessages())
82          {
83              if (this.isActionParameter())
84              {
85                  final JSFAction action = (JSFAction)this.getAction();
86                  if (action != null)
87                  {
88                      messageKey.append(action.getMessageKey());
89                      messageKey.append('.');
90                  }
91              }
92              else
93              {
94                  final JSFView view = (JSFView)this.getView();
95                  if (view != null)
96                  {
97                      messageKey.append(view.getMessageKey());
98                      messageKey.append('.');
99                  }
100             }
101             messageKey.append("param.");
102         }
103 
104         messageKey.append(StringUtilsHelper.toResourceMessageKey(super.getName()));
105         return messageKey.toString();
106     }
107 
108     /**
109      * @return getMessageKey() + '.' + JSFGlobals.DOCUMENTATION_MESSAGE_KEY_SUFFIX
110      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDocumentationKey()
111      */
112     protected String handleGetDocumentationKey()
113     {
114         return getMessageKey() + '.' + JSFGlobals.DOCUMENTATION_MESSAGE_KEY_SUFFIX;
115     }
116 
117     /**
118      * @return documentationValue
119      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDocumentationValue()
120      */
121     protected String handleGetDocumentationValue()
122     {
123         final String value = StringUtilsHelper.toResourceMessage(this.getDocumentation(
124                     "",
125                     64,
126                     false));
127         return value == null ? "" : value;
128     }
129 
130     /**
131      * Indicates whether or not we should normalize messages.
132      *
133      * @return true/false
134      */
135     private boolean isNormalizeMessages()
136     {
137         final String normalizeMessages = (String)getConfiguredProperty(JSFGlobals.NORMALIZE_MESSAGES);
138         return Boolean.valueOf(normalizeMessages).booleanValue();
139     }
140 
141     /**
142      * @return messageValue
143      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMessageValue()
144      */
145     protected String handleGetMessageValue()
146     {
147         return StringUtilsHelper.toPhrase(super.getName()); // the actual name is used for displaying
148     }
149 
150     /**
151      * @param columnName
152      * @return tableColumnMessageKey
153      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableColumnMessageKey(String)
154      */
155     protected String handleGetTableColumnMessageKey(final String columnName)
156     {
157         StringBuilder messageKey = new StringBuilder();
158         if (!this.isNormalizeMessages())
159         {
160             final JSFView view = (JSFView)this.getView();
161             if (view != null)
162             {
163                 messageKey.append(this.getMessageKey());
164                 messageKey.append('.');
165             }
166         }
167         messageKey.append(StringUtilsHelper.toResourceMessageKey(columnName));
168         return messageKey.toString();
169     }
170 
171     /**
172      * @param columnName
173      * @return StringUtilsHelper.toPhrase(columnName)
174      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableColumnMessageValue(String)
175      */
176     protected String handleGetTableColumnMessageValue(final String columnName)
177     {
178         return StringUtilsHelper.toPhrase(columnName);
179     }
180 
181     /**
182      * @return getTableActions(true)
183      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableHyperlinkActions()
184      */
185     protected List<JSFAction> handleGetTableHyperlinkActions()
186     {
187         return this.getTableActions(true);
188     }
189 
190     /**
191      * If this is a table this method returns all those actions that are declared to work
192      * on this table.
193      *
194      * @param hyperlink denotes on which type of actions to filter
195      */
196     private List<JSFAction> getTableActions(boolean hyperlink)
197     {
198         final Set<JSFAction> actions = new LinkedHashSet<JSFAction>();
199         final String name = StringUtils.trimToNull(getName());
200         if (name != null && isTable())
201         {
202             final JSFView view = (JSFView)this.getView();
203 
204             final Collection<UseCaseFacade> allUseCases = getModel().getAllUseCases();
205             for (final UseCaseFacade useCase : allUseCases)
206             {
207                 if (useCase instanceof JSFUseCase)
208                 {
209                     final FrontEndActivityGraph graph = ((JSFUseCase)useCase).getActivityGraph();
210                     if (graph != null)
211                     {
212                         final Collection<TransitionFacade> transitions = graph.getTransitions();
213                         for (final TransitionFacade transition : transitions)
214                         {
215                             if (transition.getSource().equals(view) && transition instanceof JSFAction)
216                             {
217                                 final JSFAction action = (JSFAction)transition;
218                                 if (action.isTableLink() && name.equals(action.getTableLinkName()))
219                                 {
220                                     if (hyperlink == action.isHyperlink())
221                                     {
222                                         actions.add(action);
223                                     }
224                                 }
225                             }
226                         }
227                     }
228                 }
229             }
230         }
231         return new ArrayList<JSFAction>(actions);
232     }
233 
234     /**
235      * @return getTableActions(false)
236      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableFormActions()
237      */
238     protected List<JSFAction> handleGetTableFormActions()
239     {
240         return this.getTableActions(false);
241     }
242 
243     /**
244      * @see org.andromda.metafacades.uml.FrontEndParameter#getTableColumns()
245      */
246     // TODO tableColumns can be either String or JSFParameter. Should use a single return type in Collection.
247     public Collection getTableColumns()
248     {
249         final Collection tableColumns = super.getTableColumns();
250         if (tableColumns.isEmpty())
251         {
252             // try to preserve the order of the elements encountered
253             //final Map<String, JSFParameter> tableColumnsMap = new LinkedHashMap<String, JSFParameter>();
254             final Map tableColumnsMap = new LinkedHashMap();
255 
256             // order is important
257             final List<JSFAction> actions = new ArrayList<JSFAction>();
258 
259             // all table actions need the exact same parameters, just not always all of them
260             actions.addAll(this.getTableFormActions());
261 
262             // if there are any actions that are hyperlinks then their parameters get priority
263             // the user should not have modeled it that way (constraints will warn him/her)
264             actions.addAll(this.getTableHyperlinkActions());
265 
266             for (final JSFAction action : actions)
267             {
268                 for (final FrontEndParameter actionParameter : action.getParameters())
269                 {
270                     if (actionParameter instanceof JSFParameter)
271                     {
272                         final JSFParameter parameter = (JSFParameter)actionParameter;
273                         final String parameterName = parameter.getName();
274                         if (parameterName != null)
275                         {
276                             // never overwrite column specific table links
277                             // the hyperlink table links working on a real column get priority
278                             final Object existingObject = tableColumnsMap.get(parameterName);
279                             if (existingObject instanceof JSFParameter)
280                             {
281                                 if (action.isHyperlink() && parameterName.equals(action.getTableLinkColumnName()))
282                                 {
283                                     tableColumnsMap.put(
284                                         parameterName,
285                                         parameter);
286                                 }
287                             }
288                         }
289                     }
290                 }
291             }
292 
293             // for any missing parameters we just add the name of the column
294             for (final String columnName : this.getTableColumnNames())
295             {
296                 if (!tableColumnsMap.containsKey(columnName))
297                 {
298                     tableColumnsMap.put(
299                         columnName,
300                         columnName);
301                 }
302             }
303 
304             // return everything in the same order as it has been modeled (using the table tagged value)
305             for (final String columnObject : this.getTableColumnNames())
306             {
307                 tableColumns.add(tableColumnsMap.get(columnObject));
308             }
309         }
310         return tableColumns;
311     }
312 
313     /**
314      * @return the default date format pattern as defined using the configured property
315      */
316     private String getDefaultDateFormat()
317     {
318         return (String)this.getConfiguredProperty(JSFGlobals.PROPERTY_DEFAULT_DATEFORMAT);
319     }
320 
321     /**
322      * @return format
323      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getFormat()
324      */
325     protected String handleGetFormat()
326     {
327         return JSFUtils.getFormat(
328             (ModelElementFacade)this.THIS(),
329             this.getType(),
330             this.getDefaultDateFormat(),
331             this.getDefaultTimeFormat());
332     }
333 
334     /**
335      * @return the default time format pattern as defined using the configured property
336      */
337     private String getDefaultTimeFormat()
338     {
339         return (String)this.getConfiguredProperty(JSFGlobals.PROPERTY_DEFAULT_TIMEFORMAT);
340     }
341 
342     /**
343      * @return JSFUtils.isStrictDateFormat((ModelElementFacade)this.THIS())
344      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isStrictDateFormat()
345      */
346     protected boolean handleIsStrictDateFormat()
347     {
348         return JSFUtils.isStrictDateFormat((ModelElementFacade)this.THIS());
349     }
350 
351     /**
352      * @return dateFormatter
353      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDateFormatter()
354      */
355     protected String handleGetDateFormatter()
356     {
357         final ClassifierFacade type = this.getType();
358         return type != null && type.isDateType() ? this.getName() + "DateFormatter" : null;
359     }
360 
361     /**
362      * @return timeFormatter
363      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTimeFormatter()
364      */
365     protected String handleGetTimeFormatter()
366     {
367         final ClassifierFacade type = this.getType();
368         return type != null && type.isTimeType() ? this.getName() + "TimeFormatter" : null;
369     }
370 
371     /**
372      * Gets the current value of the specified input type (or an empty string
373      * if one isn't specified).
374      *
375      * @return the input type name.
376      */
377     private String getInputType()
378     {
379         return ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TYPE)).trim();
380     }
381 
382     /**
383      * Indicates whether or not this parameter is of the given input type.
384      *
385      * @param inputType the name of the input type to check for.
386      * @return true/false
387      */
388     private boolean isInputType(final String inputType)
389     {
390         return inputType.equalsIgnoreCase(this.getInputType());
391     }
392 
393     /**
394      * @return isInputType(JSFGlobals.INPUT_TEXTAREA)
395      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputTextarea()
396      */
397     protected boolean handleIsInputTextarea()
398     {
399         return this.isInputType(JSFGlobals.INPUT_TEXTAREA);
400     }
401 
402     /**
403      * @return isInputType(JSFGlobals.INPUT_SELECT)
404      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputSelect()
405      */
406     protected boolean handleIsInputSelect()
407     {
408         return this.isInputType(JSFGlobals.INPUT_SELECT);
409     }
410 
411     /**
412      * @return isInputType(JSFGlobals.INPUT_PASSWORD)
413      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputSecret()
414      */
415     protected boolean handleIsInputSecret()
416     {
417         return this.isInputType(JSFGlobals.INPUT_PASSWORD);
418     }
419 
420     /**
421      * @return isInputType(JSFGlobals.INPUT_HIDDEN)
422      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputHidden()
423      */
424     protected boolean handleIsInputHidden()
425     {
426         return this.isInputType(JSFGlobals.INPUT_HIDDEN);
427     }
428 
429     /**
430      * @return isInputType(JSFGlobals.PLAIN_TEXT)
431      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isPlaintext()
432      */
433     protected boolean handleIsPlaintext()
434     {
435         return this.isInputType(JSFGlobals.PLAIN_TEXT);
436     }
437 
438     /**
439      * @return isInputTable
440      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputTable()
441      */
442     protected boolean handleIsInputTable()
443     {
444         return this.getInputTableIdentifierColumns().length() > 0 || this.isInputType(JSFGlobals.INPUT_TABLE);
445     }
446 
447     /**
448      * @return isInputType(JSFGlobals.INPUT_RADIO)
449      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputRadio()
450      */
451     protected boolean handleIsInputRadio()
452     {
453         return this.isInputType(JSFGlobals.INPUT_RADIO);
454     }
455 
456     /**
457      * @return isInputType(JSFGlobals.INPUT_TEXT)
458      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputText()
459      */
460     protected boolean handleIsInputText()
461     {
462         return this.isInputType(JSFGlobals.INPUT_TEXT);
463     }
464 
465     /**
466      * @return isInputType(JSFGlobals.INPUT_MULTIBOX)
467      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputMultibox()
468      */
469     protected boolean handleIsInputMultibox()
470     {
471         return this.isInputType(JSFGlobals.INPUT_MULTIBOX);
472     }
473 
474     /**
475      * @return isInputCheckbox
476      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputCheckbox()
477      */
478     protected boolean handleIsInputCheckbox()
479     {
480         boolean checkbox = this.isInputType(JSFGlobals.INPUT_CHECKBOX);
481         if (!checkbox && this.getInputType().length() == 0)
482         {
483             final ClassifierFacade type = this.getType();
484             checkbox = type != null ? type.isBooleanType() : false;
485         }
486         return checkbox;
487     }
488 
489     /**
490      * @return isInputFile
491      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputFile()
492      */
493     protected boolean handleIsInputFile()
494     {
495         boolean file = false;
496         ClassifierFacade type = getType();
497         if (type != null)
498         {
499             file = type.isFileType();
500         }
501         return file;
502     }
503 
504     /**
505      * @return backingListName
506      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getBackingListName()
507      */
508     protected String handleGetBackingListName()
509     {
510         return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.BACKING_LIST_PATTERN)).replaceAll(
511             "\\{0\\}",
512             this.getName());
513     }
514 
515     /**
516      * @return backingValueName
517      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getBackingValueName()
518      */
519     protected String handleGetBackingValueName()
520     {
521         return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.BACKING_VALUE_PATTERN)).replaceAll(
522             "\\{0\\}",
523             this.getName());
524     }
525 
526     /**
527      * @return valueListName
528      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValueListName()
529      */
530     protected String handleGetValueListName()
531     {
532         return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.VALUE_LIST_PATTERN)).replaceAll(
533             "\\{0\\}",
534             this.getName());
535     }
536 
537     /**
538      * @return labelListName
539      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getLabelListName()
540      */
541     protected String handleGetLabelListName()
542     {
543         return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.LABEL_LIST_PATTERN)).replaceAll(
544             "\\{0\\}",
545             this.getName());
546     }
547 
548     /**
549      * @return isSelectable
550      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isSelectable()
551      */
552     protected boolean handleIsSelectable()
553     {
554         boolean selectable = false;
555         if (this.isActionParameter())
556         {
557             selectable = this.isInputMultibox() || this.isInputSelect() || this.isInputRadio();
558             final ClassifierFacade type = this.getType();
559 
560             if (!selectable && type != null)
561             {
562                 final String name = this.getName();
563                 final String typeName = type.getFullyQualifiedName();
564 
565                 // - if the parameter is not selectable but on a targeting page it IS selectable we must
566                 //   allow the user to set the backing list too
567                 final Collection<FrontEndView> views = this.getAction().getTargetViews();
568                 for (final Iterator<FrontEndView> iterator = views.iterator(); iterator.hasNext() && !selectable;)
569                 {
570                     final Collection<FrontEndParameter> parameters = iterator.next().getAllActionParameters();
571                     for (final Iterator<FrontEndParameter> parameterIterator = parameters.iterator();
572                         parameterIterator.hasNext() && !selectable;)
573                     {
574                         final Object object = parameterIterator.next();
575                         if (object instanceof JSFParameter)
576                         {
577                             final JSFParameter parameter = (JSFParameter)object;
578                             final String parameterName = parameter.getName();
579                             final ClassifierFacade parameterType = parameter.getType();
580                             if (parameterType != null)
581                             {
582                                 final String parameterTypeName = parameterType.getFullyQualifiedName();
583                                 if (name.equals(parameterName) && typeName.equals(parameterTypeName))
584                                 {
585                                     selectable =
586                                         parameter.isInputMultibox() || parameter.isInputSelect() ||
587                                         parameter.isInputRadio();
588                                 }
589                             }
590                         }
591                     }
592                 }
593             }
594         }
595         else if (this.isControllerOperationArgument())
596         {
597             final String name = this.getName();
598             final Collection actions = this.getControllerOperation().getDeferringActions();
599             for (final Iterator actionIterator = actions.iterator(); actionIterator.hasNext();)
600             {
601                 final JSFAction action = (JSFAction)actionIterator.next();
602                 final Collection<FrontEndParameter>  formFields = action.getFormFields();
603                 for (final Iterator<FrontEndParameter>  fieldIterator = formFields.iterator();
604                     fieldIterator.hasNext() && !selectable;)
605                 {
606                     final Object object = fieldIterator.next();
607                     if (object instanceof JSFParameter)
608                     {
609                         final JSFParameter parameter = (JSFParameter)object;
610                         if (!parameter.equals(this))
611                         {
612                             if (name.equals(parameter.getName()))
613                             {
614                                 selectable = parameter.isSelectable();
615                             }
616                         }
617                     }
618                 }
619             }
620         }
621         return selectable;
622     }
623 
624     /**
625      * Stores the initial value of each type.
626      */
627     private final Map<String, String> initialValues = new HashMap<String, String>();
628 
629     /**
630      * @return constructDummyArray()
631      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValueListDummyValue()
632      */
633     protected String handleGetValueListDummyValue()
634     {
635         return this.constructDummyArray();
636     }
637 
638     /**
639      * @return dummyValue
640      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDummyValue()
641      */
642     protected String handleGetDummyValue()
643     {
644         final ClassifierFacade type = this.getType();
645         final String typeName = type != null ? type.getFullyQualifiedName() : "";
646         String initialValue = null;
647         if (type != null)
648         {
649             if (type.isSetType())
650             {
651                 initialValue =
652                     "new java.util.LinkedHashSet(java.util.Arrays.asList(" + this.constructDummyArray() + "))";
653             }
654             else if (type.isCollectionType())
655             {
656                 initialValue = "java.util.Arrays.asList(" + this.constructDummyArray() + ")";
657             }
658             else if (type.isArrayType())
659             {
660                 initialValue = this.constructDummyArray();
661             }
662             final String name = this.getName() != null ? this.getName() : "";
663             if (this.initialValues.isEmpty())
664             {
665                 initialValues.put(
666                     boolean.class.getName(),
667                     "false");
668                 initialValues.put(
669                     int.class.getName(),
670                     "(int)" + name.hashCode());
671                 initialValues.put(
672                     long.class.getName(),
673                     "(long)" + name.hashCode());
674                 initialValues.put(
675                     short.class.getName(),
676                     "(short)" + name.hashCode());
677                 initialValues.put(
678                     byte.class.getName(),
679                     "(byte)" + name.hashCode());
680                 initialValues.put(
681                     float.class.getName(),
682                     "(float)" + name.hashCode());
683                 initialValues.put(
684                     double.class.getName(),
685                     "(double)" + name.hashCode());
686                 initialValues.put(
687                     char.class.getName(),
688                     "(char)" + name.hashCode());
689 
690                 initialValues.put(
691                     String.class.getName(),
692                     "\"" + name + "-test" + "\"");
693                 initialValues.put(
694                     java.util.Date.class.getName(),
695                     "new java.util.Date()");
696                 initialValues.put(
697                     java.sql.Date.class.getName(),
698                     "new java.util.Date()");
699                 initialValues.put(
700                     java.sql.Timestamp.class.getName(),
701                     "new java.util.Date()");
702 
703                 initialValues.put(
704                     Integer.class.getName(),
705                     "new Integer((int)" + name.hashCode() + ")");
706                 initialValues.put(
707                     Boolean.class.getName(),
708                     "Boolean.FALSE");
709                 initialValues.put(
710                     Long.class.getName(),
711                     "new Long((long)" + name.hashCode() + ")");
712                 initialValues.put(
713                     Character.class.getName(),
714                     "new Character(char)" + name.hashCode() + ")");
715                 initialValues.put(
716                     Float.class.getName(),
717                     "new Float((float)" + name.hashCode() / hashCode() + ")");
718                 initialValues.put(
719                     Double.class.getName(),
720                     "new Double((double)" + name.hashCode() / hashCode() + ")");
721                 initialValues.put(
722                     Short.class.getName(),
723                     "new Short((short)" + name.hashCode() + ")");
724                 initialValues.put(
725                     Byte.class.getName(),
726                     "new Byte((byte)" + name.hashCode() + ")");
727             }
728             if (initialValue == null)
729             {
730                 initialValue = this.initialValues.get(typeName);
731             }
732         }
733         if (initialValue == null)
734         {
735             initialValue = "null";
736         }
737         return initialValue;
738     }
739 
740     /**
741      * Constructs a string representing an array initialization in Java.
742      *
743      * @return A String representing Java code for the initialization of an array.
744      */
745     private String constructDummyArray()
746     {
747         return JSFUtils.constructDummyArrayDeclaration(
748             this.getName(),
749             JSFGlobals.DUMMY_ARRAY_COUNT);
750     }
751 
752     /**
753      * @return getName() + "SortColumn"
754      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableSortColumnProperty()
755      */
756     protected String handleGetTableSortColumnProperty()
757     {
758         return this.getName() + "SortColumn";
759     }
760 
761     /**
762      * @return getName() + "SortAscending"
763      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableSortAscendingProperty()
764      */
765     protected String handleGetTableSortAscendingProperty()
766     {
767         return this.getName() + "SortAscending";
768     }
769 
770     /**
771      * @return getName() + "Set"
772      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getFormAttributeSetProperty()
773      */
774     protected String handleGetFormAttributeSetProperty()
775     {
776         return this.getName() + "Set";
777     }
778 
779     //TODO remove after 3.4 release
780     /**
781      * Hack to keep the compatibility with Andromda 3.4
782      */
783     /**
784      * @see org.andromda.metafacades.uml.FrontEndParameter#getView()
785      */
786     public FrontEndView getView()
787     {
788         Object view = null;
789         final EventFacade event = this.getEvent();
790         if (event != null)
791         {
792             final TransitionFacade transition = event.getTransition();
793             if (transition instanceof JSFActionLogicImpl)
794             {
795                 final JSFActionLogicImpl action = (JSFActionLogicImpl)transition;
796                 view = action.getInput();
797             }
798             else if (transition instanceof FrontEndForward)
799             {
800                 final FrontEndForward forward = (FrontEndForward)transition;
801                 if (forward.isEnteringView())
802                 {
803                     view = forward.getTarget();
804                 }
805             }
806         }
807         return (FrontEndView)view;
808     }
809 
810     /**
811      * @return validationRequired
812      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isValidationRequired()
813      */
814     protected boolean handleIsValidationRequired()
815     {
816         boolean required = !this.getValidatorTypes().isEmpty();
817         if (!required)
818         {
819             // - look for any attributes
820             for (final Iterator<JSFAttribute> iterator = this.getAttributes().iterator(); iterator.hasNext();)
821             {
822                 required = !iterator.next().getValidatorTypes().isEmpty();
823                 if (required)
824                 {
825                     break;
826                 }
827             }
828 
829             // - look for any table columns
830             if (!required)
831             {
832                 for (final Iterator iterator = this.getTableColumns().iterator(); iterator.hasNext();)
833                 {
834                     final Object object = iterator.next();
835                     if (object instanceof JSFAttribute)
836                     {
837                         final JSFAttribute attribute = (JSFAttribute)object;
838                         required = !attribute.getValidatorTypes().isEmpty();
839                         if (required)
840                         {
841                             break;
842                         }
843                     }
844                 }
845             }
846         }
847         return required;
848     }
849 
850     /**
851      * @return validatorTypes
852      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidatorTypes()
853      */
854     protected Collection handleGetValidatorTypes()
855     {
856         return JSFUtils.getValidatorTypes(
857             (ModelElementFacade)this.THIS(),
858             this.getType());
859     }
860 
861     /**
862      * @return JSFUtils.getValidWhen(this)
863      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidWhen()
864      */
865     protected String handleGetValidWhen()
866     {
867         return JSFUtils.getValidWhen(this);
868     }
869 
870     /**
871      * Overridden to have the same behavior as bpm4struts.
872      *
873      * @see org.andromda.metafacades.uml.ParameterFacade#isRequired()
874      */
875     public boolean isRequired()
876     {
877         if("org.omg.uml.foundation.core".equals(metaObject.getClass().getPackage().getName()))
878         {
879             //if uml 1.4, keep the old behavior (like bpm4struts)
880             final Object value = this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_REQUIRED);
881             return Boolean.valueOf(ObjectUtils.toString(value)).booleanValue();
882         }
883         else
884         {
885             //if >= uml 2, default behavior
886             return super.isRequired();
887         }
888     }
889 
890     /**
891      * @return JSFUtils.isReadOnly(this)
892      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isReadOnly()
893      */
894     protected boolean handleIsReadOnly()
895     {
896         return JSFUtils.isReadOnly(this);
897     }
898 
899     /**
900      * @param validatorType
901      * @return validatorArgs
902      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidatorArgs(String)
903      */
904     protected Collection handleGetValidatorArgs(final String validatorType)
905     {
906         return JSFUtils.getValidatorArgs(
907             (ModelElementFacade)this.THIS(),
908             validatorType);
909     }
910 
911     /**
912      * @return validatorVars
913      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidatorVars()
914      */
915     protected Collection handleGetValidatorVars()
916     {
917         return JSFUtils.getValidatorVars(
918             (ModelElementFacade)this.THIS(),
919             this.getType(),
920             null);
921     }
922 
923     /**
924      * @return reset
925      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isReset()
926      */
927     protected boolean handleIsReset()
928     {
929         boolean reset =
930             Boolean.valueOf(ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_RESET)))
931                    .booleanValue();
932         if (!reset)
933         {
934             final JSFAction action = (JSFAction)this.getAction();
935             reset = action != null && action.isFormReset();
936         }
937         return reset;
938     }
939 
940     /**
941      * @return complex
942      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isComplex()
943      */
944     protected boolean handleIsComplex()
945     {
946         boolean complex = false;
947         final ClassifierFacade type = this.getType();
948         if (type != null)
949         {
950             complex = !type.getAttributes().isEmpty();
951             if (!complex)
952             {
953                 complex = !type.getAssociationEnds().isEmpty();
954             }
955         }
956         return complex;
957     }
958 
959     /**
960      * @return attributes
961      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getAttributes()
962      */
963     protected Collection<AttributeFacade> handleGetAttributes()
964     {
965         Collection<AttributeFacade> attributes = null;
966         ClassifierFacade type = this.getType();
967         if (type != null)
968         {
969             if (type.isArrayType())
970             {
971                 type = type.getNonArray();
972             }
973             if (type != null)
974             {
975                 attributes = type.getAttributes(true);
976             }
977         }
978         return attributes == null ? new ArrayList<AttributeFacade>() : attributes;
979     }
980 
981     /**
982      * @return navigableAssociationEnds
983      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getNavigableAssociationEnds()
984      */
985     protected Collection<AssociationEndFacade> handleGetNavigableAssociationEnds()
986     {
987         Collection<AssociationEndFacade> associationEnds = null;
988         ClassifierFacade type = this.getType();
989         if (type != null)
990         {
991             if (type.isArrayType())
992             {
993                 type = type.getNonArray();
994             }
995             if (type != null)
996             {
997                 associationEnds = type.getNavigableConnectingEnds();
998             }
999         }
1000         return associationEnds == null ? new ArrayList<AssociationEndFacade>() : associationEnds;
1001     }
1002 
1003     /**
1004      * @return isEqualValidator
1005      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isEqualValidator()
1006      */
1007     protected boolean handleIsEqualValidator()
1008     {
1009         final String equal = JSFUtils.getEqual((ModelElementFacade)this.THIS());
1010         return equal != null && equal.trim().length() > 0;
1011     }
1012 
1013     /**
1014      * @return isBackingValueRequired
1015      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isEqualValidator()
1016      */
1017     protected boolean handleIsBackingValueRequired()
1018     {
1019         boolean required = false;
1020         if (this.isActionParameter())
1021         {
1022             required = this.isInputTable();
1023             final ClassifierFacade type = this.getType();
1024 
1025             if (!required && type != null)
1026             {
1027                 final String name = this.getName();
1028                 final String typeName = type.getFullyQualifiedName();
1029 
1030                 // - if the backing value is not required for this parameter but on
1031                 //   a targeting page it IS selectable we must allow the user to set the backing value as well
1032                 final Collection<FrontEndView> views = this.getAction().getTargetViews();
1033                 for (final Iterator<FrontEndView> iterator = views.iterator(); iterator.hasNext() && !required;)
1034                 {
1035                     final Collection<FrontEndParameter> parameters = iterator.next().getAllActionParameters();
1036                     for (final Iterator<FrontEndParameter> parameterIterator = parameters.iterator();
1037                         parameterIterator.hasNext() && !required;)
1038                     {
1039                         final FrontEndParameter object = parameterIterator.next();
1040                         if (object instanceof JSFParameter)
1041                         {
1042                             final JSFParameter parameter = (JSFParameter)object;
1043                             final String parameterName = parameter.getName();
1044                             final ClassifierFacade parameterType = parameter.getType();
1045                             if (parameterType != null)
1046                             {
1047                                 final String parameterTypeName = parameterType.getFullyQualifiedName();
1048                                 if (name.equals(parameterName) && typeName.equals(parameterTypeName))
1049                                 {
1050                                     required = parameter.isInputTable();
1051                                 }
1052                             }
1053                         }
1054                     }
1055                 }
1056             }
1057         }
1058         else if (this.isControllerOperationArgument())
1059         {
1060             final String name = this.getName();
1061             final Collection<FrontEndAction> actions = this.getControllerOperation().getDeferringActions();
1062             for (final Iterator<FrontEndAction> actionIterator = actions.iterator(); actionIterator.hasNext();)
1063             {
1064                 final JSFAction action = (JSFAction)actionIterator.next();
1065                 final Collection<FrontEndParameter> formFields = action.getFormFields();
1066                 for (final Iterator<FrontEndParameter> fieldIterator = formFields.iterator();
1067                     fieldIterator.hasNext() && !required;)
1068                 {
1069                     final Object object = fieldIterator.next();
1070                     if (object instanceof JSFParameter)
1071                     {
1072                         final JSFParameter parameter = (JSFParameter)object;
1073                         if (!parameter.equals(this))
1074                         {
1075                             if (name.equals(parameter.getName()))
1076                             {
1077                                 required = parameter.isBackingValueRequired();
1078                             }
1079                         }
1080                     }
1081                 }
1082             }
1083         }
1084         return required;
1085     }
1086 
1087     /**
1088      * @return findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TABLE_IDENTIFIER_COLUMNS)
1089      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getInputTableIdentifierColumns()
1090      */
1091     protected String handleGetInputTableIdentifierColumns()
1092     {
1093         return ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TABLE_IDENTIFIER_COLUMNS)).trim();
1094     }
1095 
1096     /**
1097      * @param columnName
1098      * @return tableColumnActions
1099      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableColumnActions(String)
1100      */
1101     protected List<JSFAction> handleGetTableColumnActions(final String columnName)
1102     {
1103         final List<JSFAction> columnActions = new ArrayList<JSFAction>();
1104 
1105         if (columnName != null)
1106         {
1107             final Set<JSFAction> actions = new LinkedHashSet<JSFAction>(this.getTableHyperlinkActions());
1108             actions.addAll(this.getTableFormActions());
1109             for (final JSFAction action : actions)
1110             {
1111                 if (columnName.equals(action.getTableLinkColumnName()))
1112                 {
1113                     columnActions.add(action);
1114                 }
1115             }
1116         }
1117 
1118         return columnActions;
1119     }
1120 
1121     /**
1122      * @return maxLength
1123      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMaxLength()
1124      */
1125     protected String handleGetMaxLength()
1126     {
1127         final Collection<Collection> vars=getValidatorVars();
1128         if(vars == null)
1129         {
1130             return null;
1131         }
1132         for(Iterator<Collection> it=vars.iterator(); it.hasNext();)
1133         {
1134             final Object[] values=(it.next()).toArray();
1135             if("maxlength".equals(values[0]))
1136             {
1137                 return values[1].toString();
1138             }
1139         }
1140         return null;
1141     }
1142 
1143     //to be used in the range validator: "range - 1000" or "range 20 -".
1144     /** - */
1145     static final String UNDEFINED_BOUND="-";
1146     /** javax.validation.constraints.NotNull */
1147     static final String AN_REQUIRED = "@javax.validation.constraints.NotNull";
1148     /** org.hibernate.validator.constraints.URL */
1149     static final String AN_URL = "@org.hibernate.validator.constraints.URL";
1150     /** org.apache.myfaces.extensions.validator.baseval.annotation.LongRange */
1151     static final String AN_LONG_RANGE = "@org.apache.myfaces.extensions.validator.baseval.annotation.LongRange";
1152     /** org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange */
1153     static final String AN_DOUBLE_RANGE = "@org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange";
1154     /** org.hibernate.validator.constraints.Email */
1155     static final String AN_EMAIL = "@org.hibernate.validator.constraints.Email";
1156     /** org.hibernate.validator.constraints.CreditCardNumber */
1157     static final String AN_CREDIT_CARD = "@org.hibernate.validator.constraints.CreditCardNumber";
1158     /** javax.validation.constraints.Size */
1159     static final String AN_LENGTH = "@javax.validation.constraints.Size";
1160     /** org.apache.myfaces.extensions.validator.baseval.annotation.Pattern */
1161     static final String AN_PATTERN = "@org.apache.myfaces.extensions.validator.baseval.annotation.Pattern";
1162     /** org.apache.myfaces.extensions.validator.crossval.annotation.Equals */
1163     static final String AN_EQUALS = "@org.apache.myfaces.extensions.validator.crossval.annotation.Equals";
1164 
1165     /**
1166      * @return the annotations
1167      * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMaxLength()
1168      */
1169     @Override
1170     protected Collection<String> handleGetAnnotations()
1171     {
1172         final Collection<String> result=new HashSet<String>();
1173         boolean requiredAdded=false;
1174         for(String vt: (Collection<String>)getValidatorTypes())
1175         {
1176             if(vt.startsWith("@")) //add the annotation
1177             {
1178                 result.add(vt);
1179             }
1180             if(JSFUtils.VT_REQUIRED.equals(vt))
1181             {
1182                 requiredAdded=true;
1183                 result.add(AN_REQUIRED);
1184             }
1185             else if(JSFUtils.VT_URL.equals(vt))
1186             {
1187                 result.add(AN_URL);
1188             }
1189             else if(JSFUtils.VT_INT_RANGE.equals(vt))
1190             {
1191                 final StringBuilder sb=new StringBuilder(AN_LONG_RANGE+"(");
1192                 final String format = JSFUtils.getInputFormat((ModelElementFacade)this.THIS());
1193                 final String rangeStart = JSFUtils.getRangeStart(format);
1194                 boolean addComma=false;
1195                 if(StringUtils.isNotBlank(rangeStart) && !rangeStart.equals(UNDEFINED_BOUND))
1196                 {
1197                     sb.append("minimum="+rangeStart);
1198                     addComma=true;
1199                 }
1200                 final String rangeEnd = JSFUtils.getRangeEnd(format);
1201                 if(StringUtils.isNotBlank(rangeEnd) && !rangeEnd.equals(UNDEFINED_BOUND))
1202                 {
1203                     if(addComma)
1204                     {
1205                         sb.append(",");
1206                     }
1207                     sb.append("maximum="+rangeEnd);
1208                 }
1209                 sb.append(")");
1210                 result.add(sb.toString());
1211             }
1212             else if(JSFUtils.VT_FLOAT_RANGE.equals(vt) || JSFUtils.VT_DOUBLE_RANGE.equals(vt))
1213             {
1214                 final StringBuilder sb=new StringBuilder(AN_DOUBLE_RANGE+"(");
1215                 final String format = JSFUtils.getInputFormat(((ModelElementFacade)this.THIS()));
1216                 final String rangeStart = JSFUtils.getRangeStart(format);
1217                 boolean addComma=false;
1218                 if(StringUtils.isNotBlank(rangeStart) && !rangeStart.equals(UNDEFINED_BOUND))
1219                 {
1220                     sb.append("minimum="+rangeStart);
1221                     addComma=true;
1222                 }
1223                 final String rangeEnd = JSFUtils.getRangeEnd(format);
1224                 if(StringUtils.isNotBlank(rangeEnd) && !rangeEnd.equals(UNDEFINED_BOUND))
1225                 {
1226                     if(addComma)
1227                     {
1228                         sb.append(",");
1229                     }
1230                     sb.append("maximum="+rangeEnd);
1231                 }
1232                 sb.append(")");
1233                 result.add(sb.toString());
1234             }
1235             else if(JSFUtils.VT_EMAIL.equals(vt))
1236             {
1237                 result.add(AN_EMAIL);
1238             }
1239             else if(JSFUtils.VT_CREDIT_CARD.equals(vt))
1240             {
1241                 result.add(AN_CREDIT_CARD);
1242             }
1243             else if(JSFUtils.VT_MIN_LENGTH.equals(vt) || JSFUtils.VT_MAX_LENGTH.equals(vt))
1244             {
1245                 final StringBuilder sb=new StringBuilder(AN_LENGTH+"(");
1246                 final Collection formats = this.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_FORMAT);
1247                 boolean addComma=false;
1248                 for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();)
1249                 {
1250                     final String additionalFormat = String.valueOf(formatIterator.next());
1251                     if (JSFUtils.isMinLengthFormat(additionalFormat))
1252                     {
1253                         if(addComma)
1254                         {
1255                             sb.append(",");
1256                         }
1257                         sb.append("min=");
1258                         sb.append(JSFUtils.getMinLengthValue(additionalFormat));
1259                         addComma=true;
1260                     }
1261                     else if (JSFUtils.isMaxLengthFormat(additionalFormat))
1262                     {
1263                         if(addComma)
1264                         {
1265                             sb.append(",");
1266                         }
1267                         sb.append("max=");
1268                         sb.append(JSFUtils.getMinLengthValue(additionalFormat));
1269                         addComma=true;
1270                     }
1271                 }
1272                 sb.append(")");
1273                 result.add(sb.toString());
1274             }
1275             else if(JSFUtils.VT_MASK.equals(vt))
1276             {
1277                 final Collection formats = this.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_FORMAT);
1278                 for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();)
1279                 {
1280                     final String additionalFormat = String.valueOf(formatIterator.next());
1281                     if (JSFUtils.isPatternFormat(additionalFormat))
1282                     {
1283                         result.add(AN_PATTERN+"(\""+JSFUtils.getPatternValue(additionalFormat)+"\")");
1284                     }
1285                 }
1286             }
1287             else if(JSFUtils.VT_VALID_WHEN.equals(vt))
1288             {
1289                 result.add("");
1290             }
1291             else if(JSFUtils.VT_EQUAL.equals(vt))
1292             {
1293                 result.add(AN_EQUALS+"(\""+JSFUtils.getEqual((ModelElementFacade)this.THIS())+"\")");
1294             }
1295         }
1296         if(!requiredAdded && getLower() > 0)
1297         {
1298             result.add(AN_REQUIRED);
1299         }
1300         return result;
1301     }
1302 }