001package org.andromda.cartridges.bpm4struts.metafacades;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.HashMap;
006import java.util.Iterator;
007import java.util.LinkedHashMap;
008import java.util.LinkedHashSet;
009import java.util.List;
010import java.util.Map;
011import java.util.Set;
012import org.andromda.cartridges.bpm4struts.Bpm4StrutsGlobals;
013import org.andromda.metafacades.uml.ClassifierFacade;
014import org.andromda.metafacades.uml.DependencyFacade;
015import org.andromda.metafacades.uml.EventFacade;
016import org.andromda.metafacades.uml.FrontEndActivityGraph;
017import org.andromda.metafacades.uml.FrontEndControllerOperation;
018import org.andromda.metafacades.uml.ModelElementFacade;
019import org.andromda.metafacades.uml.OperationFacade;
020import org.andromda.metafacades.uml.ParameterFacade;
021import org.andromda.metafacades.uml.ServiceOperation;
022import org.andromda.metafacades.uml.StateVertexFacade;
023import org.andromda.utils.StringUtilsHelper;
024
025/**
026 * MetafacadeLogic implementation for org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperation.
027 *
028 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperation
029 */
030public class StrutsControllerOperationLogicImpl
031    extends StrutsControllerOperationLogic
032{
033    private static final long serialVersionUID = 34L;
034    /**
035     * @param metaObject
036     * @param context
037     */
038    public StrutsControllerOperationLogicImpl(
039        Object metaObject,
040        String context)
041    {
042        super(metaObject, context);
043    }
044
045    /**
046     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfaceName()
047     */
048    protected String handleGetInterfaceName()
049    {
050        return StringUtilsHelper.upperCamelCaseName(getName()) + Bpm4StrutsGlobals.FORM_SUFFIX;
051    }
052
053    /**
054     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfacePackageName()
055     */
056    protected String handleGetInterfacePackageName()
057    {
058        return getOwner().getPackageName();
059    }
060
061    /**
062     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfaceType()
063     */
064    protected String handleGetInterfaceType()
065    {
066        return getInterfacePackageName() + '.' + getInterfaceName();
067    }
068
069    /**
070     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfaceFullPath()
071     */
072    protected String handleGetInterfaceFullPath()
073    {
074        return '/' + getInterfaceType().replace('.', '/');
075    }
076
077    /**
078     * Overridden because StrutsAction does not extend FrontEndAction.
079     *
080     * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getDeferringActions()
081     */
082    public java.util.List getDeferringActions()
083    {
084        final Collection deferringActions = new LinkedHashSet();
085
086        final FrontEndActivityGraph graph = getActivityGraph();
087        if (graph != null)
088        {
089            final Collection actionStates = graph.getActionStates();
090            for (final Iterator actionStateIterator = actionStates.iterator(); actionStateIterator.hasNext();)
091            {
092                final Object actionStateObject = actionStateIterator.next();
093                if (actionStateObject instanceof StrutsActionState)
094                {
095                    final StrutsActionState actionState = (StrutsActionState)actionStateObject;
096                    final Collection controllerCalls = actionState.getControllerCalls();
097                    for (final Iterator controllerCallIterator = controllerCalls.iterator();
098                         controllerCallIterator.hasNext();)
099                    {
100                        final OperationFacade operation = (OperationFacade)controllerCallIterator.next();
101                        if (this.equals(operation))
102                        {
103                            deferringActions.addAll(actionState.getContainerActions());
104                        }
105                    }
106                }
107            }
108
109            final Collection transitions = graph.getTransitions();
110            for (final Iterator transitionIterator = transitions.iterator(); transitionIterator.hasNext();)
111            {
112                final StrutsForward transition = (StrutsForward)transitionIterator.next();
113                final EventFacade event = transition.getTrigger();
114                if (event instanceof StrutsTrigger)
115                {
116                    final StrutsTrigger trigger = (StrutsTrigger)event;
117                    final FrontEndControllerOperation operation = trigger.getControllerCall();
118                    if (this.equals(operation))
119                    {
120                        // we have two types of controller calls: the ones in action states and the ones for decisions
121                        final StateVertexFacade source = transition.getSource();
122                        if (source instanceof StrutsActionState)
123                        {
124                            final StrutsActionState sourceActionState = (StrutsActionState)source;
125                            deferringActions.addAll(sourceActionState.getContainerActions());
126                        }
127
128                        // test for decision
129                        final StateVertexFacade target = transition.getTarget();
130                        if (target instanceof StrutsPseudostate)
131                        {
132                            final StrutsPseudostate targetPseudoState = (StrutsPseudostate)target;
133                            if (targetPseudoState.isDecisionPoint())
134                            {
135                                deferringActions.addAll(targetPseudoState.getContainerActions());
136                            }
137                        }
138                    }
139                }
140            }
141        }
142        return new ArrayList(deferringActions);
143    }
144
145    /**
146     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetController()
147     */
148    protected Object handleGetController()
149    {
150        final Object owner = getOwner();
151        return (owner instanceof StrutsController) ? owner : null;
152    }
153
154    /**
155     * Overridden since StrutsAction does not extend FrontEndAction.
156     *
157     * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getFormFields()
158     */
159    public List getFormFields()
160    {
161        final Map formFieldsMap = new LinkedHashMap();
162
163        // for quick lookup we use a hashset for the argument names, we only consider parameters with a name
164        // which is also present in this set
165        final Set argumentNames = new LinkedHashSet();
166        final Collection arguments = this.getArguments();
167        for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();)
168        {
169            final ModelElementFacade element = (ModelElementFacade)argumentIterator.next();
170            argumentNames.add(element.getName());
171        }
172
173        // get all actions deferring to this operation
174        final List deferringActions = this.getDeferringActions();
175        for (int i = 0; i < deferringActions.size(); i++)
176        {
177            final StrutsAction action = (StrutsAction)deferringActions.get(i);
178            // store the action parameters
179            final List actionFormFields = action.getActionFormFields();
180            for (int j = 0; j < actionFormFields.size(); j++)
181            {
182                final ModelElementFacade parameter = (ModelElementFacade)actionFormFields.get(j);
183                if (argumentNames.contains(parameter.getName()))
184                {
185                    formFieldsMap.put(parameter.getName(), parameter);
186                }
187            }
188            // get all forwards and overwrite when we find a table (or add when not yet present)
189            final List forwards = action.getActionForwards();
190            for (int j = 0; j < forwards.size(); j++)
191            {
192                final StrutsForward forward = (StrutsForward)forwards.get(j);
193                // only consider forwards directly entering a page
194                if (forward.isEnteringPage())
195                {
196                    final List pageVariables = forward.getForwardParameters();
197                    for (int k = 0; k < pageVariables.size(); k++)
198                    {
199                        final StrutsParameter pageVariable = (StrutsParameter)pageVariables.get(k);
200                        if (argumentNames.contains(pageVariable.getName()))
201                        {
202                            if (!formFieldsMap.containsKey(pageVariable.getName()) || pageVariable.isTable())
203                            {
204                                formFieldsMap.put(pageVariable.getName(), pageVariable);
205                            }
206                        }
207                    }
208                }
209            }
210        }
211
212        // since all arguments need to be present we add those that haven't yet been stored in the map
213        for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();)
214        {
215            final StrutsParameter argument = (StrutsParameter)argumentIterator.next();
216            if (!formFieldsMap.containsKey(argument.getName()))
217            {
218                formFieldsMap.put(argument.getName(), argument);
219            }
220        }
221
222        return new ArrayList(formFieldsMap.values());
223    }
224
225    /**
226     * Overridden because StrutsAction does not extend FrontEndAction
227     *
228     * @see org.andromda.metafacades.uml.FrontEndControllerOperation#isAllArgumentsHaveFormFields()
229     */
230    public boolean isAllArgumentsHaveFormFields()
231    {
232        final Collection<ParameterFacade> arguments = this.getArguments();
233        final Collection deferringActions = this.getDeferringActions();
234
235        boolean allArgumentsHaveFormFields = true;
236        for (final Iterator iterator = arguments.iterator(); iterator.hasNext() && allArgumentsHaveFormFields;)
237        {
238            final ParameterFacade parameter = (ParameterFacade)iterator.next();
239            final String parameterName = parameter.getName();
240            final ClassifierFacade parameterType = parameter.getType();
241            final String parameterTypeName = parameterType != null ? parameterType.getFullyQualifiedName() : "";
242
243            boolean actionMissingField = false;
244            for (final Iterator actionIterator = deferringActions.iterator();
245                actionIterator.hasNext() && !actionMissingField;)
246            {
247                final StrutsAction action = (StrutsAction)actionIterator.next();
248                final Collection<StrutsParameter> actionFormFields = action.getActionFormFields();
249
250                boolean fieldPresent = false;
251                for (final Iterator fieldIterator = actionFormFields.iterator();
252                    fieldIterator.hasNext() && !fieldPresent;)
253                {
254                    final ParameterFacade field = (ParameterFacade)fieldIterator.next();
255                    final ClassifierFacade fieldType = field.getType();
256                    final String fieldTypeName = fieldType != null ? fieldType.getFullyQualifiedName() : "";
257                    if (parameterName.equals(field.getName()) && parameterTypeName.equals(fieldTypeName))
258                    {
259                        fieldPresent = true;
260                    }
261                }
262                actionMissingField = !fieldPresent;
263            }
264            allArgumentsHaveFormFields = !actionMissingField;
265        }
266        return allArgumentsHaveFormFields;
267    }
268
269    /**
270     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleIsBackEndServiceOperationMatchingParameters()
271     */
272    protected boolean handleIsBackEndServiceOperationMatchingParameters()
273    {
274        boolean matches = true;
275
276        final ServiceOperation serviceOperation = getBackEndServiceOperation();
277
278        // cache this operation's parameters for easy lookup
279        final Map parameterMap = new HashMap();
280        final Collection<ParameterFacade> controllerParameters = getParameters();
281        for (final Iterator iterator = controllerParameters.iterator(); iterator.hasNext();)
282        {
283            final ParameterFacade parameter = (ParameterFacade)iterator.next();
284            parameterMap.put(parameter.getName(), parameter.getType());
285        }
286
287        // make sure that any service parameter exists here too
288        final Collection<ParameterFacade> serviceParameters = serviceOperation.getParameters();
289        for (final Iterator iterator = serviceParameters.iterator(); iterator.hasNext() && matches;)
290        {
291            final ParameterFacade serviceParameter = (ParameterFacade)iterator.next();
292            final ClassifierFacade controllerParameterType = (ClassifierFacade)parameterMap.get(
293                serviceParameter.getName());
294            matches = (controllerParameterType != null) && controllerParameterType.equals(serviceParameter.getType());
295        }
296
297        return matches;
298    }
299
300    /**
301     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetBackEndServiceOperation()
302     */
303    protected Object handleGetBackEndServiceOperation()
304    {
305        Object operation = null;
306
307        final Collection<DependencyFacade> dependencies = getSourceDependencies();
308        for (final Iterator dependencyIterator = dependencies.iterator();
309             dependencyIterator.hasNext() && operation == null;)
310        {
311            final DependencyFacade dependency = (DependencyFacade)dependencyIterator.next();
312            final Object target = dependency.getTargetElement();
313            if (target instanceof ServiceOperation)
314            {
315                operation = target;
316            }
317        }
318
319        return operation;
320    }
321
322    /**
323     * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleIsCallingBackEnd()
324     */
325    protected boolean handleIsCallingBackEnd()
326    {
327        return getBackEndServiceOperation() != null;
328    }
329}