View Javadoc
1   package org.andromda.cartridges.bpm4struts.metafacades;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.HashMap;
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 org.andromda.cartridges.bpm4struts.Bpm4StrutsGlobals;
13  import org.andromda.cartridges.bpm4struts.Bpm4StrutsProfile;
14  import org.andromda.cartridges.bpm4struts.Bpm4StrutsUtils;
15  import org.andromda.metafacades.uml.EventFacade;
16  import org.andromda.metafacades.uml.FilteredCollection;
17  import org.andromda.metafacades.uml.FrontEndEvent;
18  import org.andromda.metafacades.uml.FrontEndExceptionHandler;
19  import org.andromda.metafacades.uml.FrontEndFinalState;
20  import org.andromda.metafacades.uml.FrontEndForward;
21  import org.andromda.metafacades.uml.FrontEndParameter;
22  import org.andromda.metafacades.uml.FrontEndUseCase;
23  import org.andromda.metafacades.uml.ModelElementFacade;
24  import org.andromda.metafacades.uml.ParameterFacade;
25  import org.andromda.metafacades.uml.PseudostateFacade;
26  import org.andromda.metafacades.uml.Role;
27  import org.andromda.metafacades.uml.StateVertexFacade;
28  import org.andromda.metafacades.uml.TransitionFacade;
29  import org.andromda.metafacades.uml.UMLProfile;
30  import org.andromda.metafacades.uml.UseCaseFacade;
31  import org.andromda.utils.StringUtilsHelper;
32  import org.apache.commons.collections.CollectionUtils;
33  import org.apache.commons.collections.Predicate;
34  import org.apache.commons.lang.ObjectUtils;
35  import org.apache.commons.lang.StringUtils;
36  
37  /**
38   * MetafacadeLogic implementation.
39   *
40   * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction
41   */
42  public class StrutsActionLogicImpl
43      extends StrutsActionLogic
44  {
45      private static final long serialVersionUID = 34L;
46      /**
47       * All action states that make up this action, this includes all possible action states traversed
48       * after a decision point too.
49       */
50      private Collection<StrutsActionState> actionStates = null;
51  
52      /**
53       * All transitions leading into either a page or final state that originated from a call to this action.
54       */
55      private Map<StateVertexFacade, TransitionFacade> actionForwards = null;
56  
57      /**
58       * All transitions leading into a decision point that originated from a call to this action.
59       */
60      private Collection<TransitionFacade> decisionTransitions = null;
61  
62      /**
63       * All transitions that can be traversed when calling this action.
64       */
65      private Collection<TransitionFacade> transitions = null;
66  
67      /**
68       * @param metaObject
69       * @param context
70       */
71      public StrutsActionLogicImpl(Object metaObject,
72                                   String context)
73      {
74          super(metaObject, context);
75      }
76  
77      /**
78       * Initializes all action states, action forwards, decision transitions and transitions in one shot, so that they
79       * can be queried more efficiently later on.
80       */
81      private void initializeCollections()
82      {
83          actionStates = new LinkedHashSet<StrutsActionState>();
84          actionForwards = new HashMap<StateVertexFacade, TransitionFacade>();
85          decisionTransitions = new LinkedHashSet<TransitionFacade>();
86          transitions = new LinkedHashSet<TransitionFacade>();
87          collectTransitions(this, transitions);
88      }
89  
90      /**
91       * Recursively collects all action states, action forwards, decision transitions and transitions.
92       *
93       * @param transition           the current transition that is being processed
94       * @param processedTransitions the set of transitions already processed
95       */
96      private void collectTransitions(TransitionFacade transition,
97                                      Collection<TransitionFacade> processedTransitions)
98      {
99          if (processedTransitions.contains(transition))
100         {
101             return;
102         }
103         processedTransitions.add(transition);
104 
105         final StateVertexFacade target = transition.getTarget();
106         if ((target instanceof StrutsJsp) || (target instanceof StrutsFinalState))
107         {
108             if (!actionForwards.containsKey(transition.getTarget()))
109             {
110                 actionForwards.put(transition.getTarget(), transition);
111             }
112         }
113         else if ((target instanceof PseudostateFacade) && ((PseudostateFacade) target).isDecisionPoint())
114         {
115             decisionTransitions.add(transition);
116             for (final TransitionFacade outcome : target.getOutgoings())
117             {
118                 collectTransitions(outcome, processedTransitions);
119             }
120         }
121         else if (target instanceof StrutsActionState)
122         {
123             actionStates.add((StrutsActionState)target);
124             final FrontEndForward forward = ((StrutsActionState) target).getForward();
125             if (forward != null)
126             {
127                 collectTransitions(forward, processedTransitions);
128             }
129         }
130         else // all the rest is ignored but outgoing transitions are further processed
131         {
132             for (final TransitionFacade outcome : target.getOutgoings())
133             {
134                 collectTransitions(outcome, processedTransitions);
135             }
136         }
137     }
138 
139     /**
140      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionName()
141      */
142     protected String handleGetActionName()
143     {
144         return getFormBeanName();
145     }
146 
147     /**
148      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionInput()
149      */
150     protected String handleGetActionInput()
151     {
152         final StateVertexFacade source = getSource();
153         return (source instanceof StrutsJsp) ? ((StrutsJsp) source).getFullPath() : "";
154     }
155 
156     /**
157      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsMultipartFormData()
158      */
159     protected boolean handleIsMultipartFormData()
160     {
161         boolean multipartFormPost = false;
162 
163         for (StrutsParameter field : this.getActionFormFields())
164         {
165             if (field.isFile())
166             {
167                 multipartFormPost = true;
168                 break;
169             }
170         }
171 
172         return multipartFormPost;
173     }
174 
175     /**
176      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsFormPost()
177      */
178     protected boolean handleIsFormPost()
179     {
180         final Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE);
181         return value == null || Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_FORM.equals(value);
182     }
183 
184     /**
185      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsHyperlink()
186      */
187     protected boolean handleIsHyperlink()
188     {
189         final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE);
190         return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_HYPERLINK
191             .equalsIgnoreCase(value == null ? null : value.toString());
192     }
193 
194     /**
195      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsImageLink()
196      */
197     protected boolean handleIsImageLink()
198     {
199         final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE);
200         return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_IMAGE
201             .equalsIgnoreCase(value == null ? null : value.toString());
202     }
203 
204     /**
205      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsTableAction()
206      */
207     protected boolean handleIsTableAction()
208     {
209         return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_TABLE
210             .equals(this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE));
211     }
212 
213     /**
214      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsTableRowAction()
215      */
216     protected boolean handleIsTableRowAction()
217     {
218         return this.isTableLink() && !this.isTableAction();
219     }
220 
221     /**
222      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsTableLink()
223      */
224     protected boolean handleIsTableLink()
225     {
226         return this.getTableLinkParameter() != null;
227     }
228 
229     /**
230      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableLinkParameter()
231      */
232     protected Object handleGetTableLinkParameter()
233     {
234         StrutsParameter tableLinkParameter = null;
235 
236         final String tableLinkName = getTableLinkName();
237         if (tableLinkName != null)
238         {
239             final StrutsJsp page = this.getInput();
240             if (page != null)
241             {
242                 for (FrontEndParameter table : page.getTables())
243                 {
244                     if (tableLinkName.equals(table.getName()))
245                     {
246                         tableLinkParameter = (StrutsParameter)table;
247                     }
248                 }
249             }
250         }
251 
252         return tableLinkParameter;
253     }
254 
255     /**
256      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableNonColumnFormParameters()
257      */
258     protected List<StrutsParameter> handleGetTableNonColumnFormParameters()
259     {
260         List<StrutsParameter> tableNonColumnActionParameters = null;
261 
262         final StrutsParameter table = getTableLinkParameter();
263         if (table != null)
264         {
265             final Map<String, StrutsParameter> tableNonColumnActionParametersMap = new LinkedHashMap<String, StrutsParameter>(4);
266             final Collection<String> columnNames = table.getTableColumnNames();
267             final List<StrutsAction> formActions = table.getTableFormActions();
268             int formSize = formActions.size();
269             for (int i = 0; i < formSize; i++)
270             {
271                 final StrutsAction action = formActions.get(i);
272                 int size = action.getActionParameters().size();
273                 for (int j = 0; j < size; j++)
274                 {
275                     final StrutsParameter parameter = action.getActionParameters().get(j);
276                     if (!columnNames.contains(parameter.getName()))
277                     {
278                         tableNonColumnActionParametersMap.put(parameter.getName(), parameter);
279                     }
280                 }
281             }
282 
283             tableNonColumnActionParameters = new ArrayList<StrutsParameter>(tableNonColumnActionParametersMap.values());
284         }
285 
286         return tableNonColumnActionParameters;
287     }
288 
289     /**
290      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableLinkName()
291      */
292     protected String handleGetTableLinkName()
293     {
294         String tableLink = null;
295 
296         final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TABLELINK);
297         if (value != null)
298         {
299             tableLink = StringUtils.trimToNull(value.toString());
300 
301             if (tableLink != null)
302             {
303                 final int columnOffset = tableLink.indexOf('.');
304                 tableLink = (columnOffset == -1) ? tableLink : tableLink.substring(0, columnOffset);
305             }
306         }
307 
308         return tableLink;
309     }
310 
311     /**
312      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableLinkColumnName()
313      */
314     protected String handleGetTableLinkColumnName()
315     {
316         String tableLink = null;
317 
318         final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TABLELINK);
319         if (value != null)
320         {
321             tableLink = StringUtils.trimToNull(value.toString());
322 
323             if (tableLink != null)
324             {
325                 final int columnOffset = tableLink.indexOf('.');
326                 tableLink = (columnOffset == -1 || columnOffset == tableLink.length() - 1)
327                     ? null
328                     : tableLink.substring(columnOffset + 1);
329             }
330         }
331 
332         return tableLink;
333     }
334 
335     /**
336      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetImagePath()
337      */
338     protected String handleGetImagePath()
339     {
340         return getPackagePath() + '/' + Bpm4StrutsUtils.toWebFileName(getActionClassName()) + ".gif";
341     }
342 
343     /**
344      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionPath()
345      */
346     protected String handleGetActionPath()
347     {
348         return getActionPathRoot() + '/' + getActionClassName();
349     }
350 
351     /**
352      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionPathRoot()
353      */
354     protected String handleGetActionPathRoot()
355     {
356         String actionPathRoot = null;
357 
358         final FrontEndUseCase useCase = this.getUseCase();
359         if (useCase != null)
360         {
361             final StringBuilder buffer = new StringBuilder();
362 
363             final String actionPathPrefix = Bpm4StrutsGlobals.PROPERTY_ACTION_PATH_PREFIX;
364             String prefix = this.isConfiguredProperty(actionPathPrefix) ? ObjectUtils
365                 .toString(this.getConfiguredProperty(actionPathPrefix)) : "";
366 
367             final ModelElementFacade useCasePackage = useCase.getPackage();
368             if (useCasePackage != null)
369             {
370                 prefix = prefix.replaceAll("\\{0\\}", useCasePackage.getPackagePath());
371             }
372 
373             buffer.append(prefix);
374             buffer.append('/');
375             buffer.append(StringUtilsHelper.upperCamelCaseName(useCase.getName()));
376 
377             actionPathRoot = buffer.toString();
378         }
379         return actionPathRoot;
380     }
381 
382     /**
383      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionScope()
384      */
385     protected String handleGetActionScope()
386     {
387         return "request";
388     }
389 
390     /**
391      * @return getRoleUsers()
392      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getActionRoles()
393      */
394     protected String handleGetActionRoles()
395     {
396         final Collection users = getRoleUsers();
397         final StringBuilder roles = new StringBuilder();
398         for (final Iterator userIterator = users.iterator(); userIterator.hasNext();)
399         {
400             roles.append(((ModelElementFacade) userIterator.next()).getName());
401             if (userIterator.hasNext())
402             {
403                 roles.append(',');
404             }
405         }
406         return roles.toString();
407     }
408 
409     /**
410      * Returns a collection containing StrutsUser instances representing the roles
411      * authorized to call this action. If this action starts the use-case that use-case's users
412      * are returned, otherwise it will return the users associated to the use-cases targeted by this
413      * action (which may be none at all)
414      */
415     private Collection<Role> getRoleUsers()
416     {
417         final Collection<Role> roleUsers = new ArrayList<Role>();
418 
419         if (this.isUseCaseStart())
420         {
421             final FrontEndUseCase useCase = getUseCase();
422             if (useCase != null)
423             {
424                 roleUsers.addAll(useCase.getRoles());
425             }
426         }
427         else
428         {
429             for (final StrutsForward forward : getActionForwards())
430             {
431                 if (forward.getTarget() instanceof StrutsFinalState)
432                 {
433                     final FrontEndUseCase useCase = ((StrutsFinalState) forward.getTarget()).getTargetUseCase();
434                     if (useCase != null)
435                     {
436                         roleUsers.addAll(useCase.getRoles());
437                     }
438                 }
439             }
440         }
441 
442         return roleUsers;
443     }
444 
445     /**
446      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionClassName()
447      */
448     protected String handleGetActionClassName()
449     {
450         String name = null;
451 
452         if (this.isExitingInitialState())
453         {
454             final UseCaseFacade useCase = this.getUseCase();
455             if (useCase != null)
456             {
457                 name = useCase.getName();
458             }
459         }
460         else
461         {
462             final EventFacade trigger = getTrigger();
463             final String suffix = (trigger == null) ? getTarget().getName() : trigger.getName();
464             name = getSource().getName() + ' ' + suffix;
465         }
466         return StringUtilsHelper.upperCamelCaseName(name);
467     }
468 
469     /**
470      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionType()
471      */
472     protected String handleGetActionType()
473     {
474         return getPackageName() + '.' + getActionClassName();
475     }
476 
477     /**
478      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanClassName()
479      */
480     protected String handleGetFormBeanClassName()
481     {
482         return getActionClassName() + Bpm4StrutsGlobals.FORM_IMPLEMENTATION_SUFFIX;
483     }
484 
485     /**
486      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanName()
487      */
488     protected String handleGetFormBeanName()
489     {
490         String formBeanName = null;
491 
492         final UseCaseFacade useCase = this.getUseCase();
493         if (useCase != null)
494         {
495             final String useCaseName = useCase.getName();
496             formBeanName = StringUtilsHelper.lowerCamelCaseName(useCaseName) + getActionClassName() + Bpm4StrutsGlobals
497                 .FORM_SUFFIX;
498         }
499         return formBeanName;
500     }
501 
502     /**
503      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormValidationMethodName()
504      */
505     protected String handleGetFormValidationMethodName()
506     {
507         return "validate" + this.getActionClassName() + Bpm4StrutsGlobals.FORM_SUFFIX;
508     }
509 
510     /**
511      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetMessageKey()
512      */
513     protected String handleGetMessageKey()
514     {
515         String messageKey = null;
516 
517         final StrutsTrigger actionTrigger = getActionTrigger();
518         if (actionTrigger != null)
519         {
520             messageKey = actionTrigger.getTriggerKey();
521         }
522 
523         return messageKey;
524     }
525 
526     /**
527      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetImageMessageKey()
528      */
529     protected String handleGetImageMessageKey()
530     {
531         return getMessageKey() + ".image";
532     }
533 
534     /**
535      * Overrides the method defined in the facade parent of StrutsAction, this is done because actions (transitions) are
536      * not directly contained in a UML namespace.
537      * @return useCase.getPackageName()
538      */
539     public String getPackageName()
540     {
541         String packageName = null;
542 
543         final UseCaseFacade useCase = this.getUseCase();
544         if (useCase != null)
545         {
546             packageName = useCase.getPackageName();
547         }
548         return packageName;
549     }
550 
551     /**
552      * @return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_RESETTABLE
553      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isResettable()
554      */
555     protected boolean handleIsResettable()
556     {
557         Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_RESETTABLE);
558         return isTrue(value == null ? null : value.toString());
559     }
560 
561     /**
562      * Convenient method to detect whether or not a String instance represents a boolean <code>true</code> value.
563      */
564     private boolean isTrue(String string)
565     {
566         return "yes".equalsIgnoreCase(string) ||
567             "true".equalsIgnoreCase(string) ||
568             "on".equalsIgnoreCase(string) ||
569             "1".equalsIgnoreCase(string);
570     }
571 
572     /**
573      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsUseCaseStart()
574      */
575     protected boolean handleIsUseCaseStart()
576     {
577         StateVertexFacade source = getSource();
578         return source instanceof PseudostateFacade && ((PseudostateFacade) source).isInitialState();
579     }
580 
581     /**
582      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFullActionPath()
583      */
584     protected String handleGetFullActionPath()
585     {
586         return getPackagePath() + '/' + getActionClassName();
587     }
588 
589     /**
590      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFullTilePath()
591      */
592     protected String handleGetFullTilePath()
593     {
594         return isUseCaseStart()
595             ? "empty-file"
596             : getPackagePath() + '/' + Bpm4StrutsUtils.toWebFileName(getActionClassName());
597     }
598 
599     /**
600      * We override this method here to make sure the actions end-up in the same package as their use-case. A transition
601      * (this class' parent type) does not have a real package as we need it here.
602      * @return this.getUseCase() / useCase.getPackagePath()
603      */
604     public String getPackagePath()
605     {
606         String packagePath = null;
607 
608         final UseCaseFacade useCase = this.getUseCase();
609         if (useCase != null)
610         {
611             packagePath = '/' + useCase.getPackagePath();
612         }
613         return packagePath;
614     }
615 
616     /**
617      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFullFormBeanPath()
618      */
619     protected String handleGetFullFormBeanPath()
620     {
621         return '/' + (getPackageName() + '/' + getFormBeanClassName()).replace('.', '/');
622     }
623 
624     /**
625      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsValidationRequired()
626      */
627     protected boolean handleIsValidationRequired()
628     {
629         for (final StrutsParameter parameter : getActionParameters())
630         {
631             if (parameter.isValidationRequired())
632             {
633                 return true;
634             }
635         }
636         return false;
637     }
638 
639     /**
640      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsDateFieldPresent()
641      */
642     protected boolean handleIsDateFieldPresent()
643     {
644         for (final StrutsParameter parameter : getActionParameters())
645         {
646             if (parameter.isDate())
647             {
648                 return true;
649             }
650         }
651         return false;
652     }
653 
654     /**
655      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsCalendarRequired()
656      */
657     protected boolean handleIsCalendarRequired()
658     {
659         for (final StrutsParameter parameter : getActionParameters())
660         {
661             if (parameter.isCalendarRequired())
662             {
663                 return true;
664             }
665         }
666         return false;
667     }
668 
669     /**
670      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanPackageName()
671      */
672     protected String handleGetFormBeanPackageName()
673     {
674         return getPackageName();
675     }
676 
677     /**
678      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanType()
679      */
680     protected String handleGetFormBeanType()
681     {
682         return getFormBeanPackageName() + '.' + getFormBeanClassName();
683     }
684 
685     /**
686      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDocumentationKey()
687      */
688     protected String handleGetDocumentationKey()
689     {
690         final StrutsTrigger trigger = getActionTrigger();
691         return ((trigger == null) ? getMessageKey() + ".is.an.action.without.trigger" : trigger.getTriggerKey()) +
692             ".documentation";
693     }
694 
695     /**
696      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDocumentationValue()
697      */
698     protected String handleGetDocumentationValue()
699     {
700         final String value = StringUtilsHelper.toResourceMessage(getDocumentation("", 64, false));
701         return (value == null) ? "" : value;
702     }
703 
704     /**
705      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetOnlineHelpKey()
706      */
707     protected String handleGetOnlineHelpKey()
708     {
709         final StrutsTrigger trigger = getActionTrigger();
710         return ((trigger == null) ? getMessageKey() + ".is.an.action.without.trigger" : trigger.getTriggerKey()) +
711             ".online.help";
712     }
713 
714     /**
715      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetOnlineHelpValue()
716      */
717     protected String handleGetOnlineHelpValue()
718     {
719         final String crlf = "<br/>";
720         final StringBuilder buffer = new StringBuilder();
721 
722         final String value = StringUtilsHelper.toResourceMessage(getDocumentation("", 64, false));
723         buffer.append((value == null) ? "No action documentation has been specified" : value);
724         buffer.append(crlf);
725 
726         return StringUtilsHelper.toResourceMessage(buffer.toString());
727     }
728 
729     /**
730      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionForwards()
731      */
732     protected List<TransitionFacade> handleGetActionForwards()
733     {
734         if (actionForwards == null) initializeCollections();
735         return new ArrayList<TransitionFacade>(actionForwards.values());
736     }
737 
738     /**
739      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDecisionTransitions()
740      */
741     protected List<TransitionFacade> handleGetDecisionTransitions()
742     {
743         if (decisionTransitions == null) initializeCollections();
744         return new ArrayList<TransitionFacade>(decisionTransitions);
745     }
746 
747     /**
748      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionStates()
749      */
750     protected List<StrutsActionState> handleGetActionStates()
751     {
752         if (actionStates == null) initializeCollections();
753         return new ArrayList<StrutsActionState>(actionStates);
754     }
755 
756     /**
757      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionExceptions()
758      */
759     protected List<FrontEndExceptionHandler> handleGetActionExceptions()
760     {
761         final Collection<FrontEndExceptionHandler> exceptions = new LinkedHashSet<FrontEndExceptionHandler>();
762         final Collection<StrutsActionState> actionStates = getActionStates();
763         for (final Iterator<StrutsActionState> iterator = actionStates.iterator(); iterator.hasNext();)
764         {
765             StrutsActionState actionState = iterator.next();
766             exceptions.addAll(actionState.getExceptions());
767         }
768 
769         return new ArrayList<FrontEndExceptionHandler>(exceptions);
770     }
771 
772     /**
773      * @return PseudostateFacade or STEREOTYPE_FRONT_END_VIEW
774      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getInput()
775      */
776     protected Object handleGetInput()
777     {
778         Object input = null;
779         final ModelElementFacade source = getSource();
780         if (source instanceof PseudostateFacade)
781         {
782             final PseudostateFacade pseudostate = (PseudostateFacade) source;
783             if (pseudostate.isInitialState())
784             {
785                 input = source;
786             }
787         }
788         else
789         {
790             if (source.hasStereotype(UMLProfile.STEREOTYPE_FRONT_END_VIEW))
791             {
792                 input = source;
793             }
794         }
795         return input;
796     }
797 
798     /**
799      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetController()
800      */
801     protected Object handleGetController()
802     {
803         final StrutsActivityGraph graph = this.getStrutsActivityGraph();
804         return graph == null ? null : graph.getController();
805     }
806 
807     /**
808      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionTrigger()
809      */
810     protected Object handleGetActionTrigger()
811     {
812         return this.getTrigger();
813     }
814 
815     /**
816      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionFormFields()
817      */
818     protected List<FrontEndParameter> handleGetActionFormFields()
819     {
820         final Map<String, FrontEndParameter> formFieldMap = new HashMap<String, FrontEndParameter>();
821 
822         /**
823          * for useCaseStart actions we need to detect all usecases forwarding to the one belonging to this action
824          * if there are any parameters in those requests we need to have them included in this action's form
825          */
826         if (this.isUseCaseStart())
827         {
828             final FrontEndUseCase useCase = this.getUseCase();
829             if (useCase != null)
830             {
831                 final Collection<FrontEndFinalState> finalStates = useCase.getReferencingFinalStates();
832                 for (final Iterator<FrontEndFinalState> finalStateIterator = finalStates.iterator(); finalStateIterator.hasNext();)
833                 {
834                     final Object finalStateObject = finalStateIterator.next();
835                     // we need to test for the type because a non struts-use-case final state might accidentally
836                     // be linking to this use-case (for example: the user temporarily wants to disable code generation
837                     // for a specific use-case and is not removing the final-state to use-case link(s))
838                     if (finalStateObject instanceof StrutsFinalState)
839                     {
840                         final StrutsFinalState finalState = (StrutsFinalState) finalStateObject;
841                         for (final FrontEndParameter parameter : finalState.getInterUseCaseParameters())
842                         {
843                             formFieldMap.put(parameter.getName(), parameter);
844                         }
845                     }
846                 }
847             }
848         }
849 
850         // if any action encountered by the execution of the complete action-graph path emits a forward
851         // containing one or more parameters they need to be included as a form field too
852         for (final StrutsActionState actionState : getActionStates())
853         {
854             final StrutsForward forward = (StrutsForward) actionState.getForward();
855             if (forward != null)
856             {
857                 for (final FrontEndParameter forwardParameter : forward.getForwardParameters())
858                 {
859                     formFieldMap.put(forwardParameter.getName(), forwardParameter);
860                 }
861             }
862         }
863 
864         // add page variables for all pages/final-states targeted
865         // also add the fields of the target page's actions (for preloading)
866         for (final StrutsForward forward : getActionForwards())
867         {
868             final StateVertexFacade target = forward.getTarget();
869             if (target instanceof StrutsJsp)
870             {
871                 final StrutsJsp jsp = (StrutsJsp) target;
872                 for (final StrutsParameter facade : jsp.getPageVariables())
873                 {
874                     formFieldMap.put(facade.getName(), facade);
875                 }
876                 for (final FrontEndParameter facade : jsp.getAllActionParameters())
877                 {
878                     formFieldMap.put(facade.getName(), facade);
879                 }
880             }
881             else if (target instanceof StrutsFinalState)
882             {
883                 // only add these if there is no parameter recorded yet with the same name
884                 for (final FrontEndParameter facade : forward.getForwardParameters())
885                 {
886                     if (!formFieldMap.containsKey(facade.getName()))
887                     {
888                         formFieldMap.put(facade.getName(), facade);
889                     }
890                 }
891             }
892         }
893 
894         // we do the action parameters in the end because they are allowed to overwrite existing properties
895         for (final StrutsParameter facade : getActionParameters())
896         {
897             formFieldMap.put(facade.getName(), facade);
898         }
899 
900         return new ArrayList<FrontEndParameter>(formFieldMap.values());
901     }
902 
903     /**
904      * FrontEndControllerOperation does not extend OperationFacade
905      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDeferredOperations()
906      */
907     protected List handleGetDeferredOperations()
908     {
909         final Collection deferredOperations = new LinkedHashSet();
910 
911         final StrutsController controller = getController();
912         if (controller != null)
913         {
914             final List<StrutsActionState> actionStates = getActionStates();
915             int size = actionStates.size();
916             for (int i = 0; i < size; i++)
917             {
918                 final StrutsActionState actionState = actionStates.get(i);
919                 deferredOperations.addAll(actionState.getControllerCalls());
920             }
921 
922             for (StrutsForward forward : this.getDecisionTransitions())
923             {
924                 final FrontEndEvent trigger = forward.getDecisionTrigger();
925                 if (trigger != null)
926                 {
927                     deferredOperations.add(trigger.getControllerCall());
928                 }
929             }
930         }
931         return new ArrayList(deferredOperations);
932     }
933 
934     /**
935      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionParameters()
936      */
937     protected List<ParameterFacade> handleGetActionParameters()
938     {
939         final StrutsTrigger trigger = getActionTrigger();
940         return (trigger == null) ? Collections.emptyList() : new ArrayList(trigger.getParameters());
941     }
942 
943     /**
944      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetInterUseCaseParameters(org.andromda.cartridges.bpm4struts.metafacades.StrutsFinalState)
945      */
946     protected List<FrontEndParameter> handleGetInterUseCaseParameters(StrutsFinalState finalState)
947     {
948         List<FrontEndParameter> parameters;
949 
950         if (finalState == null)
951         {
952             parameters = Collections.emptyList();
953         }
954         else
955         {
956             // we don't want to list parameters with the same name to we use a hash map
957             final Map<String, FrontEndParameter> parameterMap = new HashMap<String, FrontEndParameter>();
958 
959             for (final StrutsForward forward : this.getActionForwards())
960             {
961                 // only return those parameters that belong to both this action and the argument final state
962                 if (finalState.equals(forward.getTarget()))
963                 {
964                     for (FrontEndParameter parameter : forward.getForwardParameters())
965                     {
966                         parameterMap.put(parameter.getName(), parameter);
967                     }
968                 }
969             }
970             parameters = new ArrayList<FrontEndParameter>(parameterMap.values());
971         }
972 
973         return parameters;
974     }
975 
976     /**
977      * @return getActionForwards().getTarget()
978      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getTargetPages()
979      */
980     protected List<StateVertexFacade> handleGetTargetPages()
981     {
982         Collection<StateVertexFacade> targetPages = new LinkedHashSet<StateVertexFacade>();
983 
984         for (final StrutsForward forward : getActionForwards())
985         {
986             if (forward.isEnteringPage())
987             {
988                 targetPages.add(forward.getTarget());
989             }
990         }
991 
992         return new ArrayList<StateVertexFacade>(targetPages);
993     }
994 
995     /**
996      * @return new ArrayList(transitions)
997      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#getTransitions()
998      */
999     protected List<TransitionFacade> handleGetTransitions()
1000     {
1001         if (transitions == null)
1002         {
1003             initializeCollections();
1004         }
1005         return new ArrayList<TransitionFacade>(transitions);
1006     }
1007 
1008     /**
1009      * @return getActionTrigger().getName() lowerCamelCaseName
1010      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getStyleId()
1011      */
1012     protected String handleGetStyleId()
1013     {
1014         String styleId = null;
1015 
1016         StrutsTrigger trigger = getActionTrigger();
1017         if (trigger != null)
1018         {
1019             String triggerName = trigger.getName();
1020             styleId = StringUtilsHelper.lowerCamelCaseName(triggerName);
1021         }
1022         return styleId;
1023     }
1024 
1025     /**
1026      * @return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_REDIRECT
1027      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isRedirect()
1028      */
1029     protected boolean handleIsRedirect()
1030     {
1031         String redirect = (String) this.getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_DEFAULT_ACTION_REDIRECT);
1032         Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_REDIRECT);
1033         if (value != null)
1034         {
1035             redirect = (String) value;
1036         }
1037         return Boolean.valueOf(StringUtils.trimToEmpty(redirect));
1038     }
1039 
1040     /**
1041      * @return getActionParameters().isShouldReset()
1042      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getResettableActionParameters()
1043      */
1044     protected List<StrutsParameter> handleGetResettableActionParameters()
1045     {
1046         return new ArrayList<StrutsParameter>(new FilteredCollection(this.getActionParameters())
1047         {
1048             private static final long serialVersionUID = 34L;
1049             public boolean evaluate(Object object)
1050             {
1051                 return object != null && ((StrutsParameter)object).isShouldReset();
1052             }
1053         });
1054     }
1055 
1056     /**
1057      * The "session" action form scope.
1058      */
1059     private static final String FORM_SCOPE_SESSION = "session";
1060 
1061     /**
1062      * The "request" action form scope.
1063      */
1064     private static final String FORM_SCOPE_REQUEST = "request";
1065 
1066     /**
1067      * The "none" action form scope.
1068      */
1069     private static final String FORM_SCOPE_NONE = "none";
1070 
1071     /**
1072      * @return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_FORM_SCOPE
1073      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getFormScope()
1074      */
1075     protected String handleGetFormScope()
1076     {
1077         String actionFormScope = String
1078             .valueOf(this.getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_ACTION_FORM_SCOPE));
1079         Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_FORM_SCOPE);
1080         if (value != null)
1081         {
1082             actionFormScope = String.valueOf(value);
1083         }
1084         return StringUtils.trimToEmpty(actionFormScope);
1085     }
1086 
1087     /**
1088      * @return getFormScope().equalsIgnoreCase(FORM_SCOPE_SESSION)
1089      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isFormScopeSession()
1090      */
1091     protected boolean handleIsFormScopeSession()
1092     {
1093         return FORM_SCOPE_SESSION.equalsIgnoreCase(this.getFormScope());
1094     }
1095 
1096     /**
1097      * @return getFormScope().equalsIgnoreCase(FORM_SCOPE_REQUEST)
1098      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isFormScopeRequest()
1099      */
1100     protected boolean handleIsFormScopeRequest()
1101     {
1102         return FORM_SCOPE_REQUEST.equalsIgnoreCase(this.getFormScope());
1103     }
1104 
1105     /**
1106      * @return getFormScope().equalsIgnoreCase(FORM_SCOPE_NONE)
1107      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isFormScopeNone()
1108      */
1109     protected boolean handleIsFormScopeNone()
1110     {
1111         return this.getFormScope().equalsIgnoreCase(FORM_SCOPE_NONE);
1112     }
1113 
1114     /**
1115      * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetHiddenActionParameters()
1116      */
1117     protected List<StrutsParameter> handleGetHiddenActionParameters()
1118     {
1119         final List<StrutsParameter> hiddenActionParameters = new ArrayList<StrutsParameter>(this.getActionParameters());
1120         CollectionUtils.filter(hiddenActionParameters, new Predicate()
1121         {
1122             public boolean evaluate(final Object object)
1123             {
1124                 return StrutsParameterLogicImpl.HIDDEN_INPUT_TYPE.equals(((StrutsParameter) object).getWidgetType());
1125             }
1126         });
1127         return hiddenActionParameters;
1128     }
1129 }