001package org.andromda.metafacades.uml14;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Collections;
006import java.util.Iterator;
007import java.util.LinkedHashMap;
008import java.util.LinkedHashSet;
009import java.util.List;
010import java.util.Map;
011import org.andromda.metafacades.uml.ActivityGraphFacade;
012import org.andromda.metafacades.uml.ActorFacade;
013import org.andromda.metafacades.uml.AssociationEndFacade;
014import org.andromda.metafacades.uml.ClassifierFacade;
015import org.andromda.metafacades.uml.FrontEndAction;
016import org.andromda.metafacades.uml.FrontEndActivityGraph;
017import org.andromda.metafacades.uml.FrontEndController;
018import org.andromda.metafacades.uml.FrontEndFinalState;
019import org.andromda.metafacades.uml.FrontEndForward;
020import org.andromda.metafacades.uml.FrontEndParameter;
021import org.andromda.metafacades.uml.FrontEndUseCase;
022import org.andromda.metafacades.uml.FrontEndView;
023import org.andromda.metafacades.uml.ModelElementFacade;
024import org.andromda.metafacades.uml.Role;
025import org.andromda.metafacades.uml.StateVertexFacade;
026import org.andromda.metafacades.uml.UMLProfile;
027import org.apache.commons.lang.StringUtils;
028
029/**
030 * MetafacadeLogic implementation for org.andromda.metafacades.uml.FrontEndUseCase.
031 *
032 * @see org.andromda.metafacades.uml.FrontEndUseCase
033 * @author Bob Fields
034 */
035public class FrontEndUseCaseLogicImpl
036    extends FrontEndUseCaseLogic
037{
038    private static final long serialVersionUID = -2917211873092559876L;
039
040    /**
041     * @param metaObject
042     * @param context
043     */
044    public FrontEndUseCaseLogicImpl(
045        Object metaObject,
046        String context)
047    {
048        super(metaObject, context);
049    }
050
051    /**
052     * @see org.andromda.metafacades.uml.FrontEndUseCase#isEntryUseCase()
053     */
054    @Override
055    protected boolean handleIsEntryUseCase()
056    {
057        return hasStereotype(UMLProfile.STEREOTYPE_FRONT_END_APPLICATION);
058    }
059
060    /**
061     * @see org.andromda.metafacades.uml.FrontEndUseCase#getController()
062     */
063    @Override
064    protected FrontEndController handleGetController()
065    {
066        final FrontEndActivityGraph graph = this.getActivityGraph();
067        return graph == null ? null : graph.getController();
068    }
069
070    /**
071     * @see org.andromda.metafacades.uml.FrontEndUseCase#getActivityGraph()
072     */
073    @Override
074    protected ActivityGraphFacade handleGetActivityGraph()
075    {
076        ActivityGraphFacade activityGraph = null;
077
078        // - in case there is a tagged value pointing to an activity graph, and this graph is found,
079        //   return it.
080        final Object activity = this.findTaggedValue(UMLProfile.TAGGEDVALUE_PRESENTATION_USECASE_ACTIVITY);
081        if (activity != null)
082        {
083            final String activityName = String.valueOf(activity.toString());
084            activityGraph = this.getModel().findActivityGraphByName(activityName);
085        }
086
087        // - otherwise just take the first one in this use-case's namespace.
088        if (activityGraph == null)
089        {
090            final Collection<ModelElementFacade> ownedElements = this.getOwnedElements();
091            for (final Iterator<ModelElementFacade> iterator = ownedElements.iterator(); iterator.hasNext();)
092            {
093                final Object object = iterator.next();
094                if (object instanceof FrontEndActivityGraph)
095                {
096                    return (ActivityGraphFacade)object;
097                }
098            }
099        }
100        return activityGraph;
101    }
102
103    /**
104     * @see org.andromda.metafacades.uml.FrontEndUseCase#getReferencingFinalStates()
105     */
106    @Override
107    protected List handleGetReferencingFinalStates()
108    {
109        return new ArrayList(this.getModel().findFinalStatesWithNameOrHyperlink(this));
110    }
111
112    /**
113     * @see org.andromda.metafacades.uml.FrontEndUseCase#getAllUseCases()
114     */
115    @Override
116    protected List handleGetAllUseCases()
117    {
118        final List useCases = new ArrayList();
119        for (final Iterator useCaseIterator = getModel().getAllUseCases().iterator(); useCaseIterator.hasNext();)
120        {
121            final Object object = useCaseIterator.next();
122            if (object instanceof FrontEndUseCase)
123            {
124                useCases.add(object);
125            }
126        }
127        return useCases;
128    }
129
130    /**
131     * Gets those roles directly associated to this use-case.
132     */
133    private Collection<Role> getAssociatedRoles()
134    {
135        final Collection<Role> usersList = new ArrayList<Role>();
136        final Collection<AssociationEndFacade> associationEnds = getAssociationEnds();
137        for (final Iterator<AssociationEndFacade> iterator = associationEnds.iterator(); iterator.hasNext();)
138        {
139            final AssociationEndFacade associationEnd = iterator.next();
140            final ClassifierFacade classifier = associationEnd.getOtherEnd().getType();
141            if (classifier instanceof Role)
142            {
143                usersList.add((Role)classifier);
144            }
145        }
146        return usersList;
147    }
148
149    /**
150     * Recursively collects all roles generalizing the argument user, in the specified collection.
151     */
152    private void collectRoles(
153        final Role role,
154        final Collection<Role> roles)
155    {
156        if (!roles.contains(role))
157        {
158            roles.add(role);
159            final Collection<ActorFacade> childUsers = role.getGeneralizedByActors();
160            for (final Iterator<ActorFacade> iterator = childUsers.iterator(); iterator.hasNext();)
161            {
162                final Role childUser = (Role)iterator.next();
163                this.collectRoles(
164                    childUser,
165                    roles);
166            }
167        }
168    }
169
170    /**
171     * @see org.andromda.metafacades.uml.FrontEndUseCase#getRoles()
172     */
173    @Override
174    protected List<Role> handleGetRoles()
175    {
176        final Collection<Role> allRoles = new LinkedHashSet<Role>();
177        final Collection<Role> associatedUsers = this.getAssociatedRoles();
178        for (final Iterator iterator = associatedUsers.iterator(); iterator.hasNext();)
179        {
180            final Role user = (Role)iterator.next();
181            this.collectRoles(
182                user,
183                allRoles);
184        }
185        return new ArrayList<Role>(allRoles);
186    }
187
188    /**
189     * @see org.andromda.metafacades.uml.FrontEndUseCase#getAllRoles()
190     */
191    @Override
192    protected List<Role> handleGetAllRoles()
193    {
194        final Collection<Role> allRoles = new LinkedHashSet<Role>();
195        for (final Iterator iterator = this.getAllUseCases().iterator(); iterator.hasNext();)
196        {
197            allRoles.addAll(((FrontEndUseCase)iterator.next()).getRoles());
198        }
199        return new ArrayList(allRoles);
200    }
201
202    /**
203     * @see org.andromda.metafacades.uml.FrontEndUseCase#isSecured()
204     */
205    @Override
206    protected boolean handleIsSecured()
207    {
208        return !this.getRoles().isEmpty();
209    }
210
211    /**
212     * @see org.andromda.metafacades.uml.FrontEndUseCase#getViews()
213     */
214    @Override
215    protected List handleGetViews()
216    {
217        List views;
218        final ActivityGraphFacade graph = this.getActivityGraph();
219        if (graph == null)
220        {
221            views = Collections.emptyList();
222        }
223        else
224        {
225            views =
226                new ArrayList(getModel().getAllActionStatesWithStereotype(
227                        graph,
228                        UMLProfile.STEREOTYPE_FRONT_END_VIEW));
229        }
230        return views;
231    }
232
233    /**
234     * @see org.andromda.metafacades.uml.FrontEndUseCase#getViews()
235     */
236    @Override
237    protected List<FrontEndAction> handleGetActions()
238    {
239        final Collection<FrontEndAction> actions = new LinkedHashSet<FrontEndAction> ();
240        final Collection<FrontEndView> pages = this.getViews();
241        for (final Iterator<FrontEndView> pageIterator = pages.iterator(); pageIterator.hasNext();)
242        {
243            final FrontEndView view = pageIterator.next();
244            actions.addAll(view.getActions());
245        }
246
247        final FrontEndActivityGraph graph = this.getActivityGraph();
248        if (graph != null)
249        {
250            final FrontEndAction action = graph.getInitialAction();
251            if (action != null)
252            {
253                actions.add(action);
254            }
255        }
256        return new ArrayList<FrontEndAction>(actions);
257    }
258
259    /**
260     * @see org.andromda.metafacades.uml.FrontEndUseCase#getInitialView()
261     */
262    @Override
263    protected FrontEndView handleGetInitialView()
264    {
265        FrontEndView view = null;
266        final FrontEndActivityGraph graph = this.getActivityGraph();
267        final FrontEndAction action = graph != null ? this.getActivityGraph().getInitialAction() : null;
268        final Collection<FrontEndForward> forwards = action != null ? action.getActionForwards() : null;
269        if (forwards != null)
270        {
271            for (final Iterator<FrontEndForward> iterator = forwards.iterator(); iterator.hasNext();)
272            {
273                final FrontEndForward forward = iterator.next();
274                final StateVertexFacade target = forward.getTarget();
275                if (target instanceof FrontEndView)
276                {
277                    view = (FrontEndView)target;
278                }
279                else if (target instanceof FrontEndFinalState)
280                {
281                    final FrontEndFinalState finalState = (FrontEndFinalState)target;
282                    final FrontEndUseCase targetUseCase = finalState.getTargetUseCase();
283                    if (targetUseCase != null && !targetUseCase.equals(this.THIS()))
284                    {
285                        view = targetUseCase.getInitialView();
286                    }
287                }
288            }
289        }
290        return view;
291    }
292
293    /**
294     * @see org.andromda.metafacades.uml.FrontEndUseCase#getViewVariables()
295     */
296    @Override
297    protected List<FrontEndParameter> handleGetViewVariables()
298    {
299        final Map<String, FrontEndParameter> pageVariableMap = new LinkedHashMap<String, FrontEndParameter>();
300
301        // - page variables can occur twice or more in the usecase if their
302        //   names are the same for different forms, storing them in a map
303        //   solves this issue because those names do not have the action-name prefix
304        final Collection<FrontEndView> views = this.getViews();
305        for (final Iterator pageIterator = views.iterator(); pageIterator.hasNext();)
306        {
307            final FrontEndView view = (FrontEndView)pageIterator.next();
308            final Collection<FrontEndParameter> variables = view.getVariables();
309            for (final Iterator<FrontEndParameter> variableIterator = variables.iterator(); variableIterator.hasNext();)
310            {
311                FrontEndParameter variable = variableIterator.next();
312                final String name = variable.getName();
313                if (StringUtils.isNotBlank(name))
314                {
315                    final FrontEndParameter existingVariable = pageVariableMap.get(name);
316                    if (existingVariable != null)
317                    {
318                        if (existingVariable.isTable())
319                        {
320                            variable = existingVariable;
321                        }
322                    }
323                    pageVariableMap.put(
324                        name,
325                        variable);
326                }
327            }
328        }
329        return new ArrayList<FrontEndParameter>(pageVariableMap.values());
330    }
331}