001package org.andromda.cartridges.jsf2.metafacades;
002
003import java.security.MessageDigest;
004import java.security.NoSuchAlgorithmException;
005import java.util.ArrayList;
006import java.util.Collection;
007import java.util.Collections;
008import java.util.Iterator;
009import java.util.LinkedHashMap;
010import java.util.List;
011import java.util.Map;
012import org.andromda.cartridges.jsf2.JSFGlobals;
013import org.andromda.cartridges.jsf2.JSFProfile;
014import org.andromda.cartridges.jsf2.JSFUtils;
015import org.andromda.metafacades.uml.EventFacade;
016import org.andromda.metafacades.uml.FrontEndAction;
017import org.andromda.metafacades.uml.FrontEndActionState;
018import org.andromda.metafacades.uml.FrontEndControllerOperation;
019import org.andromda.metafacades.uml.FrontEndForward;
020import org.andromda.metafacades.uml.FrontEndParameter;
021import org.andromda.metafacades.uml.FrontEndView;
022import org.andromda.metafacades.uml.ModelElementFacade;
023import org.andromda.metafacades.uml.UseCaseFacade;
024import org.andromda.utils.StringUtilsHelper;
025import org.apache.commons.collections.CollectionUtils;
026import org.apache.commons.collections.Predicate;
027import org.apache.commons.lang.ObjectUtils;
028import org.apache.commons.lang.StringUtils;
029import org.apache.log4j.Logger;
030
031/**
032 * MetafacadeLogic implementation for org.andromda.cartridges.jsf2.metafacades.JSFAction.
033 *
034 * @see org.andromda.cartridges.jsf2.metafacades.JSFAction
035 */
036public class JSFActionLogicImpl
037    extends JSFActionLogic
038{
039    private static final long serialVersionUID = 34L;
040    /**
041     * @param metaObject
042     * @param context
043     */
044    public JSFActionLogicImpl(
045        Object metaObject,
046        String context)
047    {
048        super(metaObject, context);
049    }
050
051    /**
052     * The logger instance.
053     */
054    private static final Logger LOGGER = Logger.getLogger(JSFActionLogicImpl.class);
055
056    /**
057     * @return getFormBeanName(true)
058     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFormBeanName()
059     */
060    protected String handleGetFormBeanName()
061    {
062        return this.getFormBeanName(true);
063    }
064
065    /**
066     * Constructs the form bean name, with our without prefixing the use case name.
067     *
068     * @param withUseCaseName whether or not to prefix the use case name.
069     * @return the constructed form bean name.
070     */
071    private String getFormBeanName(boolean withUseCaseName)
072    {
073        final String pattern = ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.FORM_BEAN_PATTERN));
074        final ModelElementFacade useCase = this.getUseCase();
075        final String useCaseName = withUseCaseName && useCase != null
076            ? StringUtilsHelper.lowerCamelCaseName(useCase.getName()) : "";
077        final String formBeanName = pattern.replaceFirst("\\{0\\}", useCaseName);
078        final String triggerName = !pattern.equals(formBeanName)
079            ? StringUtils.capitalize(this.getTriggerName()) : this.getTriggerName();
080        return formBeanName.replaceFirst(
081            "\\{1\\}",
082            triggerName);
083    }
084
085    /**
086     * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
087     */
088    public String getName()
089    {
090        return JSFUtils.toWebResourceName(this.getUseCase().getName() + "-" + super.getName());
091    }
092
093    /**
094     * @return useCase.getName()
095     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getTriggerName()
096     */
097    protected String handleGetTriggerName()
098    {
099        String name = null;
100        if (this.isExitingInitialState())
101        {
102            final JSFUseCase useCase = (JSFUseCase)this.getUseCase();
103            if (useCase != null)
104            {
105                name = useCase.getName();
106            }
107        }
108        else
109        {
110            final EventFacade trigger = this.getTrigger();
111            final String suffix = trigger == null ? this.getTarget().getName() : trigger.getName();
112            name = this.getSource().getName() + ' ' + suffix;
113        }
114        return StringUtilsHelper.lowerCamelCaseName(name);
115    }
116
117    /**
118     * @return formImplementationName
119     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFormImplementationName()
120     */
121    protected String handleGetFormImplementationName()
122    {
123        final String pattern =
124            ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.FORM_IMPLEMENTATION_PATTERN));
125        return pattern.replaceFirst(
126            "\\{0\\}",
127            StringUtils.capitalize(this.getTriggerName()));
128    }
129
130    /**
131     * @return isTableAction
132     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFullyQualifiedFormImplementationName()
133     */
134    protected boolean handleIsTableAction()
135    {
136        return JSFGlobals.ACTION_TYPE_TABLE.equals(this.findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE));
137    }
138
139    /**
140     * @return fullyQualifiedFormImplementationName
141     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFullyQualifiedFormImplementationName()
142     */
143    protected String handleGetFullyQualifiedFormImplementationName()
144    {
145        final StringBuilder fullyQualifiedName = new StringBuilder();
146        final String packageName = this.getPackageName();
147        if (StringUtils.isNotBlank(packageName))
148        {
149            fullyQualifiedName.append(packageName + '.');
150        }
151        return fullyQualifiedName.append(this.getFormImplementationName()).toString();
152    }
153
154    /**
155     * @return fullyQualifiedFormImplementationPath
156     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFullyQualifiedFormImplementationPath()
157     */
158    protected String handleGetFullyQualifiedFormImplementationPath()
159    {
160        return this.getFullyQualifiedFormImplementationName().replace(
161            '.',
162            '/');
163    }
164
165    /**
166     * @return scope
167     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFullyQualifiedFormImplementationPath()
168     */
169    protected String handleGetFormScope()
170    {
171        String scope = ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_FORM_SCOPE));
172        if (StringUtils.isEmpty(scope))
173        {
174            scope = ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.FORM_SCOPE));
175        }
176        return scope;
177    }
178
179    /**
180     * @return formImplementationInterfaceList
181     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFormImplementationInterfaceList()
182     */
183    protected String handleGetFormImplementationInterfaceList()
184    {
185        final List<FrontEndControllerOperation> deferredOperations = this.getDeferredOperations();
186        for (final Iterator<FrontEndControllerOperation> iterator = deferredOperations.iterator(); iterator.hasNext();)
187        {
188            // - remove any forms that don't have arguments
189            final JSFControllerOperation operation = (JSFControllerOperation)iterator.next();
190            if (operation.getArguments().isEmpty())
191            {
192                iterator.remove();
193            }
194        }
195        final StringBuilder list = new StringBuilder();
196        for (final Iterator<FrontEndControllerOperation> iterator = deferredOperations.iterator(); iterator.hasNext();)
197        {
198            final JSFControllerOperation operation = (JSFControllerOperation)iterator.next();
199            list.append(operation.getFormName());
200            if (iterator.hasNext())
201            {
202                list.append(", ");
203            }
204        }
205        return list.toString();
206    }
207
208    /**
209     * @see org.andromda.cartridges.jsf2.metafacades.JSFActionLogic#handleGetPath()
210     */
211    protected String handleGetPath()
212    {
213        String path = this.getPathRoot() + '/' + JSFUtils.toWebResourceName(this.getTriggerName());
214        if (this.isExitingInitialState())
215        {
216            final JSFUseCase useCase = (JSFUseCase)this.getUseCase();
217            if (useCase != null && useCase.isViewHasNameOfUseCase())
218            {
219                // - add the uc prefix to make the trigger name unique
220                //   when a view contained within the use case has the same name
221                //   as the use case
222                path = path + "uc";
223            }
224        }
225        return path;
226    }
227
228    /**
229     * @return pathRoot
230     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getPathRoot()
231     */
232    protected String handleGetPathRoot()
233    {
234        final StringBuilder pathRoot = new StringBuilder();
235        final JSFUseCase useCase = (JSFUseCase)this.getUseCase();
236        if (useCase != null)
237        {
238            pathRoot.append(useCase.getPathRoot());
239        }
240        return pathRoot.toString();
241    }
242
243    /**
244     * @return messageKey
245     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getMessageKey()
246     */
247    protected String handleGetMessageKey()
248    {
249        String messageKey = null;
250
251        final Object trigger = this.getTrigger();
252        if (trigger instanceof JSFEvent)
253        {
254            final JSFEvent actionTrigger = (JSFEvent)trigger;
255            messageKey = actionTrigger.getMessageKey();
256        }
257        return messageKey;
258    }
259
260    /**
261     * @return documentationKey
262     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getDocumentationKey()
263     */
264    protected String handleGetDocumentationKey()
265    {
266        final Object trigger = this.getTrigger();
267        JSFEvent event = null;
268        if (trigger instanceof JSFEvent)
269        {
270            event = (JSFEvent)trigger;
271        }
272        return (event == null ? this.getMessageKey() + ".is.an.action.without.trigger" : event.getMessageKey()) +
273            '.' + JSFGlobals.DOCUMENTATION_MESSAGE_KEY_SUFFIX;
274    }
275
276    /**
277     * @return documentationValue
278     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getDocumentationValue()
279     */
280    protected String handleGetDocumentationValue()
281    {
282        final String value = StringUtilsHelper.toResourceMessage(getDocumentation(
283                    "",
284                    64,
285                    false));
286        return value == null ? "" : value;
287    }
288
289    /**
290     * @return viewFragmentPath
291     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getViewFragmentPath()
292     */
293    protected String handleGetViewFragmentPath()
294    {
295        return '/' + this.getPackageName().replace(
296            '.',
297            '/') + '/' + JSFUtils.toWebResourceName(this.getTriggerName());
298    }
299
300    /**
301     * @return tableLink
302     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getTableLinkName()
303     */
304    protected String handleGetTableLinkName()
305    {
306        String tableLink = null;
307
308        final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TABLELINK);
309        if (value != null)
310        {
311            tableLink = StringUtils.trimToNull(value.toString());
312
313            if (tableLink != null)
314            {
315                final int columnOffset = tableLink.indexOf('.');
316                tableLink = columnOffset == -1 ? tableLink : tableLink.substring(
317                        0,
318                        columnOffset);
319            }
320        }
321
322        return tableLink;
323    }
324
325    /**
326     * @return tableLink
327     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getTableLinkColumnName()
328     */
329    protected String handleGetTableLinkColumnName()
330    {
331        String tableLink = null;
332        final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TABLELINK);
333        if (value != null)
334        {
335            tableLink = StringUtils.trimToNull(value.toString());
336
337            if (tableLink != null)
338            {
339                final int columnOffset = tableLink.indexOf('.');
340                tableLink = (columnOffset == -1 || columnOffset == tableLink.length() - 1)
341                    ? null : tableLink.substring(columnOffset + 1);
342            }
343        }
344        return tableLink;
345    }
346
347    /**
348     * @return tableLinkParameter
349     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isTableLink()
350     */
351    protected Object handleGetTableLinkParameter()
352    {
353        JSFParameter tableLinkParameter = null;
354        final String tableLinkName = this.getTableLinkName();
355        if (tableLinkName != null)
356        {
357            final JSFView view = (JSFView)this.getInput();
358            if (view != null)
359            {
360                final List<FrontEndParameter> tables = view.getTables();
361                for (int ctr = 0; ctr < tables.size() && tableLinkParameter == null; ctr++)
362                {
363                    final Object object = tables.get(ctr);
364                    if (object instanceof JSFParameter)
365                    {
366                        final JSFParameter table = (JSFParameter)object;
367                        if (tableLinkName.equals(table.getName()))
368                        {
369                            tableLinkParameter = table;
370                        }
371                    }
372                }
373            }
374        }
375        return tableLinkParameter;
376    }
377
378    /**
379     * @return getTableLinkParameter() != null
380     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isTableLink()
381     */
382    protected boolean handleIsTableLink()
383    {
384        return this.getTableLinkParameter() != null;
385    }
386
387    /**
388     * @return hyperlink
389     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isHyperlink()
390     */
391    protected boolean handleIsHyperlink()
392    {
393        final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE);
394        return JSFGlobals.ACTION_TYPE_HYPERLINK.equalsIgnoreCase(value == null ? null : value.toString());
395    }
396
397    /**
398     * @return StringUtilsHelper.upperCamelCaseName(this.getTriggerName())
399     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getActionClassName()
400     */
401    protected String handleGetActionClassName()
402    {
403        return StringUtilsHelper.upperCamelCaseName(this.getTriggerName());
404    }
405
406    /**
407     * @return fullyQualifiedActionClassPath
408     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFullyQualifiedActionClassPath()
409     */
410    protected String handleGetFullyQualifiedActionClassPath()
411    {
412        return this.getFullyQualifiedActionClassName().replace(
413            '.',
414            '/') + ".java";
415    }
416
417    /**
418     * Overridden to provide the owning use case's package name.
419     *
420     * @see org.andromda.metafacades.uml.ModelElementFacade#getPackageName()
421     */
422    public String getPackageName()
423    {
424        final UseCaseFacade useCase = this.getUseCase();
425        return useCase != null ? useCase.getPackageName() : "";
426    }
427
428    /**
429     * @return getTriggerName()
430     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getControllerAction()
431     */
432    protected String handleGetControllerAction()
433    {
434        return this.getTriggerName();
435    }
436
437    /**
438     * @return fullyQualifiedActionClassName
439     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFullyQualifiedActionClassName()
440     */
441    protected String handleGetFullyQualifiedActionClassName()
442    {
443        final StringBuilder path = new StringBuilder();
444        final JSFUseCase useCase = (JSFUseCase)this.getUseCase();
445        if (useCase != null)
446        {
447            final String packageName = useCase.getPackageName();
448            if (StringUtils.isNotBlank(packageName))
449            {
450                path.append(packageName);
451                path.append('.');
452            }
453        }
454        path.append(this.getActionClassName());
455        return path.toString();
456    }
457
458    /**
459     * @return findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_RESETTABLE) isTrue
460     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isResettable()
461     */
462    protected boolean handleIsResettable()
463    {
464        final Object value = findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_RESETTABLE);
465        return this.isTrue(value == null ? null : value.toString());
466    }
467
468    /**
469     * Convenient method to detect whether or not a String instance represents a boolean <code>true</code> value.
470     */
471    private boolean isTrue(String string)
472    {
473        return "yes".equalsIgnoreCase(string) || "true".equalsIgnoreCase(string) || "on".equalsIgnoreCase(string) ||
474        "1".equalsIgnoreCase(string);
475    }
476
477    /**
478     * @return otherActions
479     */
480    protected List<FrontEndAction> handleGetOtherUseCaseFormActions()
481    {
482        final List<FrontEndAction> otherActions = new ArrayList<FrontEndAction>(this.getUseCase().getActions());
483        for (final Iterator<FrontEndAction> iterator = otherActions.iterator(); iterator.hasNext();)
484        {
485            final FrontEndAction action = iterator.next();
486
487            // - remove this action and any forms that don't have form fields
488            if (action.equals(this.THIS()) || action.getFormFields().isEmpty())
489            {
490                iterator.remove();
491            }
492        }
493        return otherActions;
494    }
495
496    /**
497     * @return hiddenParameters
498     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFormKey()
499     */
500    protected String handleGetFormKey()
501    {
502        final Object formKeyValue = this.findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_FORM_KEY);
503        return formKeyValue == null ? ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.ACTION_FORM_KEY))
504                                    : String.valueOf(formKeyValue);
505    }
506
507    /**
508     * @return hiddenParameters
509     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getHiddenParameters()
510     */
511    protected List<FrontEndParameter> handleGetHiddenParameters()
512    {
513        final List<FrontEndParameter> hiddenParameters = new ArrayList<FrontEndParameter>(this.getParameters());
514        CollectionUtils.filter(
515            hiddenParameters,
516            new Predicate()
517            {
518                public boolean evaluate(final Object object)
519                {
520                    boolean valid = false;
521                    if (object instanceof JSFParameter)
522                    {
523                        final JSFParameter parameter = (JSFParameter)object;
524                        valid = parameter.isInputHidden();
525                        if (!valid)
526                        {
527                            for (final Iterator iterator = parameter.getAttributes().iterator(); iterator.hasNext();)
528                            {
529                                JSFAttribute attribute = (JSFAttribute)iterator.next();
530                                valid = attribute.isInputHidden();
531                                if (valid)
532                                {
533                                    break;
534                                }
535                            }
536                        }
537                    }
538                    return valid;
539                }
540            });
541        return hiddenParameters;
542    }
543
544    /**
545     * @return required
546     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getHiddenParameters()
547     */
548    protected boolean handleIsValidationRequired()
549    {
550        boolean required = false;
551        for (final FrontEndParameter frontEndParam : this.getParameters())
552        {
553            if (frontEndParam instanceof JSFParameter)
554            {
555                final JSFParameter parameter = (JSFParameter)frontEndParam;
556                if (parameter.isValidationRequired())
557                {
558                    required = true;
559                    break;
560                }
561            }
562        }
563        return required;
564    }
565
566    /**
567     * @return popup
568     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isPopup()
569     */
570    protected boolean handleIsPopup()
571    {
572        boolean popup = ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE)).equalsIgnoreCase(
573            JSFGlobals.ACTION_TYPE_POPUP);
574        return popup;
575    }
576
577    /**
578     * @return dialog
579     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isDialog()
580     */
581    protected boolean handleIsDialog()
582    {
583        return this.isPopup();
584        //currently only popup dialogs are supported and all dialog = popup.
585        //It should change when JSF
586        //starts supporting some conversation scope, or the jsf cartridge supports
587        //some extension that adds this kind of feature
588        
589//        boolean dialog = ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_TYPE)).equalsIgnoreCase(
590//            JSFGlobals.ACTION_TYPE_DIALOG);
591//        return dialog;
592    }
593
594    /**
595     * @return resetRequired
596     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isFormResetRequired()
597     */
598    protected boolean handleIsFormResetRequired()
599    {
600        boolean resetRequired = this.isFormReset();
601        if (!resetRequired)
602        {
603            for (final FrontEndParameter feParameter : this.getParameters())
604            {
605                if (feParameter instanceof JSFParameter)
606                {
607                    final JSFParameter parameter = (JSFParameter)feParameter;
608                    resetRequired = parameter.isReset();
609                    if (resetRequired)
610                    {
611                        break;
612                    }
613                }
614            }
615        }
616        return resetRequired;
617    }
618
619    //TODO remove after 3.4 release
620    /**
621     * Hack to keep the compatibility with Andromda 3.4-SNAPSHOT
622     * @return getSource() instanceof FrontEndView
623     */
624    public FrontEndView getInput()
625    {
626        FrontEndView input = null;
627        final ModelElementFacade source = this.getSource();
628        if (source instanceof FrontEndView)
629        {
630            input = (FrontEndView)source;
631        }
632        return input;
633    }
634
635    /**
636     * @return formSerialVersionUID
637     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFormSerialVersionUID()
638     */
639    protected String handleGetFormSerialVersionUID()
640    {
641        final StringBuilder buffer = new StringBuilder();
642
643        buffer.append(this.getName());
644
645        final ModelElementFacade input = (ModelElementFacade)this.getInput();
646        buffer.append(input != null ? input.getName() : "");
647
648        final ModelElementFacade guard = this.getGuard();
649        buffer.append(guard != null ? guard.getName() : "");
650
651        final ModelElementFacade effect = this.getEffect();
652        buffer.append(effect != null ? effect.getName() : "");
653
654        final ModelElementFacade decisionsTrigger = this.getDecisionTrigger();
655        buffer.append(decisionsTrigger != null ? decisionsTrigger.getName() : "");
656
657        buffer.append(StringUtils.trimToEmpty(this.getActionClassName()));
658
659        for (final FrontEndParameter parameter : this.getParameters())
660        {
661            buffer.append(parameter.getName());
662        }
663
664        for (final FrontEndForward forward : this.getActionForwards())
665        {
666            buffer.append(forward.getName());
667        }
668
669        for (final FrontEndAction action : this.getActions())
670        {
671            buffer.append(action.getName());
672        }
673
674        for (final FrontEndActionState state : this.getActionStates())
675        {
676            buffer.append(state.getName());
677        }
678        final String signature = buffer.toString();
679
680        String serialVersionUID = String.valueOf(0L);
681        try
682        {
683            MessageDigest md = MessageDigest.getInstance("SHA");
684            byte[] hashBytes = md.digest(signature.getBytes());
685
686            long hash = 0;
687            for (int ctr = Math.min(
688                        hashBytes.length,
689                        8) - 1; ctr >= 0; ctr--)
690            {
691                hash = (hash << 8) | (hashBytes[ctr] & 0xFF);
692            }
693            serialVersionUID = String.valueOf(hash);
694        }
695        catch (final NoSuchAlgorithmException exception)
696        {
697            final String message = "Error performing JSFAction.getFormSerialVersionUID";
698            LOGGER.error(
699                message,
700                exception);
701        }
702        return serialVersionUID;
703    }
704
705    /**
706     * @return findTaggedValue(JSFProfile.TAGGEDVALUE_ACTION_FORM_RESET)
707     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isFormResetRequired()
708     */
709    protected boolean handleIsFormReset()
710    {
711        return Boolean.valueOf(ObjectUtils.toString(this.findTaggedValue(
712            JSFProfile.TAGGEDVALUE_ACTION_FORM_RESET))).booleanValue();
713    }
714
715    /**
716     * @return "get" + StringUtils.capitalize(this.getFormBeanName(false)) + "()"
717     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFormImplementationGetter()
718     */
719    protected String handleGetFormImplementationGetter()
720    {
721        return "get" + StringUtils.capitalize(this.getFormBeanName(false)) + "()";
722    }
723
724    /**
725     * @return getTarget() instanceof JSFFinalState
726     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isFinalStateTarget()
727     */
728    protected boolean handleIsFinalStateTarget()
729    {
730        return this.getTarget() instanceof JSFFinalState;
731    }
732
733    /**
734     * @return getName()
735     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getFromOutcome()
736     */
737    protected String handleGetFromOutcome()
738    {
739        return this.getName();
740    }
741
742    /**
743     * @see org.andromda.cartridges.jsf2.metafacades.JSFActionLogic#handleIsSuccessMessagesPresent()
744     */
745    protected boolean handleIsSuccessMessagesPresent()
746    {
747        return !this.getSuccessMessages().isEmpty();
748    }
749
750    /**
751     * @see org.andromda.cartridges.jsf2.metafacades.JSFActionLogic#handleIsWarningMessagesPresent()
752     */
753    protected boolean handleIsWarningMessagesPresent()
754    {
755        return !this.getWarningMessages().isEmpty();
756    }
757
758    /**
759     * Collects specific messages in a map.
760     *
761     * @param taggedValue the tagged value from which to read the message
762     * @return maps message keys to message values, but only those that match the arguments
763     *         will have been recorded
764     */
765    private Map<String, String> getMessages(String taggedValue)
766    {
767        Map<String, String> messages;
768
769        final Collection taggedValues = this.findTaggedValues(taggedValue);
770        if (taggedValues.isEmpty())
771        {
772            messages = Collections.EMPTY_MAP;
773        }
774        else
775        {
776            messages = new LinkedHashMap<String, String>(); // we want to keep the order
777            for (final Object tag : taggedValues)
778            {
779                final String value = (String)tag;
780                messages.put(StringUtilsHelper.toResourceMessageKey(value), value);
781            }
782        }
783
784        return messages;
785    }
786
787    /**
788     * @see org.andromda.cartridges.jsf2.metafacades.JSFActionLogic#handleGetSuccessMessages()
789     */
790    protected Map<String, String> handleGetSuccessMessages()
791    {
792        return this.getMessages(JSFProfile.TAGGEDVALUE_ACTION_SUCCESS_MESSAGE);
793    }
794
795    /**
796     * @see org.andromda.cartridges.jsf2.metafacades.JSFActionLogic#handleGetWarningMessages()
797     */
798    protected Map<String, String> handleGetWarningMessages()
799    {
800        return this.getMessages(JSFProfile.TAGGEDVALUE_ACTION_WARNING_MESSAGE);
801    }
802
803    /**
804     * @return needsFileUpload
805     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#isNeedsFileUpload()
806     */
807    protected boolean handleIsNeedsFileUpload()
808    {
809        if(this.getParameters().size() == 0)
810        {
811            return false;
812        }
813
814        for (final FrontEndParameter feParameter : this.getParameters())
815        {
816            if (feParameter instanceof JSFParameter)
817            {
818                final JSFParameter parameter = (JSFParameter)feParameter;
819                if(parameter.isInputFile())
820                {
821                    return true;
822                }
823                if(parameter.isComplex())
824                {
825                    for(final Iterator attributes = parameter.getAttributes().iterator(); attributes.hasNext();)
826                        if(((JSFAttribute)attributes.next()).isInputFile())
827                            return true;
828                }
829            }
830        }
831        return false;
832    }
833
834    /**
835     * @see org.andromda.cartridges.jsf2.metafacades.JSFAction#getTriggerMethodName
836     */
837    @Override
838    protected String handleGetTriggerMethodName()
839    {
840        final StringBuilder methodName = new StringBuilder();
841        if (this.isExitingInitialState())
842        {
843            final JSFUseCase useCase = (JSFUseCase)this.getUseCase();
844            methodName.append(StringUtilsHelper.lowerCamelCaseName(useCase.getName())+"_started");
845        }
846        else
847        {
848            methodName.append(StringUtilsHelper.lowerCamelCaseName(this.getSource().getName()));
849            methodName.append('_');
850            final EventFacade trigger = this.getTrigger();
851            final String suffix = trigger == null ? this.getTarget().getName() : trigger.getName();
852            methodName.append(StringUtilsHelper.lowerCamelCaseName(suffix));
853        }
854        return "_"+methodName.toString();
855    }
856}