View Javadoc
1   package org.andromda.metafacades.emf.uml22;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.LinkedHashSet;
7   import java.util.List;
8   import java.util.Set;
9   import org.andromda.core.metafacade.MetafacadeBase;
10  import org.andromda.metafacades.uml.EventFacade;
11  import org.andromda.metafacades.uml.FrontEndAction;
12  import org.andromda.metafacades.uml.FrontEndActionState;
13  import org.andromda.metafacades.uml.FrontEndActivityGraph;
14  import org.andromda.metafacades.uml.FrontEndControllerOperation;
15  import org.andromda.metafacades.uml.FrontEndEvent;
16  import org.andromda.metafacades.uml.FrontEndForward;
17  import org.andromda.metafacades.uml.FrontEndUseCase;
18  import org.andromda.metafacades.uml.FrontEndView;
19  import org.andromda.metafacades.uml.ParameterFacade;
20  import org.andromda.metafacades.uml.PseudostateFacade;
21  import org.andromda.metafacades.uml.StateVertexFacade;
22  import org.andromda.metafacades.uml.TransitionFacade;
23  import org.andromda.metafacades.uml.UseCaseFacade;
24  import org.andromda.utils.StringUtilsHelper;
25  import org.apache.commons.lang.StringUtils;
26  import org.apache.log4j.Logger;
27  
28  /**
29   * MetafacadeLogic implementation for
30   * org.andromda.metafacades.uml.FrontEndForward.
31   *
32   * @see org.andromda.metafacades.uml.FrontEndForward
33   */
34  public class FrontEndForwardLogicImpl
35      extends FrontEndForwardLogic
36  {
37      private static final long serialVersionUID = 34L;
38  
39      /**
40       * The logger instance.
41       */
42      private static final Logger LOGGER = Logger.getLogger(FrontEndForwardLogicImpl.class);
43  
44      /**
45       * @param metaObject
46       * @param context
47       */
48      public FrontEndForwardLogicImpl(
49          final Object metaObject,
50          final String context)
51      {
52          super(metaObject, context);
53      }
54  
55      /**
56       * @see org.andromda.metafacades.uml.FrontEndForward#isContainedInFrontEndUseCase()
57       */
58      @Override
59      protected boolean handleIsContainedInFrontEndUseCase()
60      {
61          return this.getFrontEndActivityGraph() != null;
62      }
63  
64      /**
65       * @see org.andromda.metafacades.uml.FrontEndForward#getFrontEndActivityGraph()
66       */
67      @Override
68      protected FrontEndActivityGraph handleGetFrontEndActivityGraph()
69      {
70          final Object graph = this.getSource().getStateMachine();
71          return (FrontEndActivityGraph)(graph instanceof FrontEndActivityGraph ? graph : null);
72      }
73  
74      /**
75       * If this forward has a trigger this method returns that trigger's name,
76       * otherwise if this forward has a name this method returns that name,
77       * otherwise if this forward's target has a name this method returns that
78       * name, otherwise simply returns <code>"unknown"</code>
79       *
80       * @see org.andromda.metafacades.emf.uml22.ModelElementFacadeLogic#handleGetName()
81       */
82      @Override
83      protected final String handleGetName()
84      {
85          String forwardName = null;
86  
87          // - trigger
88          final EventFacade trigger = this.getTrigger();
89          if (trigger != null)
90          {
91              forwardName = trigger.getName();
92          }
93  
94          // - name
95          if (StringUtils.isBlank(forwardName))
96          {
97              forwardName = super.handleGetName();
98          }
99  
100         // - target
101         if (StringUtils.isBlank(forwardName))
102         {
103             forwardName = this.getTarget().getName();
104         }
105 
106         // - else
107         if (StringUtils.isBlank(forwardName))
108         {
109             forwardName = "unknown";
110         }
111         return forwardName;
112     }
113 
114     /**
115      * @see org.andromda.metafacades.uml.FrontEndForward#getActionMethodName()
116      */
117     @Override
118     protected String handleGetActionMethodName()
119     {
120         return StringUtilsHelper.lowerCamelCaseName(this.handleGetName());
121     }
122 
123     /**
124      * @see org.andromda.metafacades.uml.FrontEndForward#isEnteringView()
125      */
126     @Override
127     protected boolean handleIsEnteringView()
128     {
129         return this.getTarget() instanceof FrontEndView;
130     }
131 
132     /**
133      * @see org.andromda.metafacades.uml.FrontEndForward#isExitingView()
134      */
135     @Override
136     protected boolean handleIsExitingView()
137     {
138         return this.getSource() instanceof FrontEndView;
139     }
140 
141     /**
142      * @see org.andromda.metafacades.uml.FrontEndForward#getUseCase()
143      */
144     @Override
145     protected FrontEndUseCase handleGetUseCase()
146     {
147         FrontEndUseCase useCase = null;
148         final FrontEndActivityGraph graph = this.getFrontEndActivityGraph();
149         if (graph != null)
150         {
151             final UseCaseFacade graphUseCase = graph.getUseCase();
152             if (graphUseCase instanceof FrontEndUseCase)
153             {
154                 useCase = (FrontEndUseCase)graphUseCase;
155             }
156         }
157         return useCase;
158     }
159 
160     /**
161      * All action states that make up this action, this includes all possible
162      * action states traversed after a decision point too.
163      */
164     private Collection<FrontEndActionState> actionStates = null;
165 
166     /**
167      * @return new ArrayList<FrontEndActionState>(this.actionStates)
168      * @see org.andromda.metafacades.uml.FrontEndAction#getActionStates()
169      */
170     protected List<FrontEndActionState> handleGetActionStates()
171     {
172         if (this.actionStates == null)
173         {
174             this.initializeCollections();
175         }
176         return new ArrayList<FrontEndActionState>(this.actionStates);
177     }
178 
179     /**
180      * Initializes all action states, action forwards, decision transitions and
181      * transitions in one shot, so that they can be queried more efficiently
182      * later on.
183      */
184     private void initializeCollections()
185     {
186         this.actionStates = new LinkedHashSet<FrontEndActionState>();
187         this.collectTransitions(
188             this,
189             new LinkedHashSet<TransitionFacade>());
190     }
191 
192     /**
193      * Recursively collects all action states, action forwards, decision
194      * transitions and transitions.
195      *
196      * @param transition
197      *            the current transition that is being processed
198      * @param processedTransitions
199      *            the set of transitions already processed
200      */
201     private void collectTransitions(
202         final TransitionFacade transition,
203         final Set<TransitionFacade> processedTransitions)
204     {
205         if (processedTransitions.contains(transition))
206         {
207             return;
208         }
209         processedTransitions.add(transition);
210 
211         final StateVertexFacade target = transition.getTarget();
212         if (target instanceof FrontEndActionState)
213         {
214             this.actionStates.add((FrontEndActionState)target);
215             final FrontEndForward forward = ((FrontEndActionState)target).getForward();
216             if (forward != null)
217             {
218                 this.collectTransitions(
219                     forward,
220                     processedTransitions);
221             }
222         }
223     }
224 
225     /**
226      * @see org.andromda.metafacades.uml.FrontEndAction#getDecisionTrigger()
227      */
228     @Override
229     protected FrontEndEvent handleGetDecisionTrigger()
230     {
231         return (FrontEndEvent)(this.isEnteringDecisionPoint() ? this.shieldedElement(this.getTrigger()) : null);
232     }
233 
234     /**
235      * @see org.andromda.metafacades.uml.FrontEndAction#getActions()
236      */
237     @Override
238     protected List<FrontEndAction> handleGetActions()
239     {
240         final Set<FrontEndAction> actions = new LinkedHashSet<FrontEndAction>();
241         this.findActions(
242             actions,
243             new LinkedHashSet<MetafacadeBase>());
244         return new ArrayList<FrontEndAction>(actions);
245     }
246 
247     /**
248      * Recursively finds all actions for this forward, what this means depends
249      * on the context in which this forward is used: if the source is a page
250      * action state it will collect all actions going out of this page, if the
251      * source is a regular action state it will collect all actions that might
252      * traverse this action state, if the source is the initial state it will
253      * collect all actions forwarding to this forward's use-case (please not
254      * that those actions most likely are defined in other use-cases).
255      *
256      * @param actions
257      *            the default set of actions, duplicates will not be recorded
258      * @param handledForwards
259      *            the forwards already processed
260      */
261     private void findActions(
262         final Set<FrontEndAction> actions,
263         final Set<MetafacadeBase> handledForwards)
264     {
265         if (!handledForwards.contains(this.THIS()))
266         {
267             handledForwards.add(this);
268 
269             // TODO this is not so nice because FrontEndAction extends FrontEndForward, solution would be to override in FrontEndAction
270             if (this instanceof FrontEndAction)
271             {
272                 actions.add((FrontEndAction)this.THIS());
273             }
274             else
275             {
276                 final StateVertexFacade vertex = this.getSource();
277                 if (vertex instanceof FrontEndView)
278                 {
279                     final FrontEndView view = (FrontEndView)vertex;
280                     actions.addAll(view.getActions());
281                 }
282                 else if (vertex instanceof FrontEndActionState)
283                 {
284                     final FrontEndActionState actionState = (FrontEndActionState)vertex;
285                     actions.addAll(actionState.getContainerActions());
286                 }
287                 else if (vertex instanceof PseudostateFacade)
288                 {
289                     final PseudostateFacade pseudostate = (PseudostateFacade)vertex;
290                     if (!pseudostate.isInitialState())
291                     {
292                         final Collection<TransitionFacade> incomingForwards = pseudostate.getIncomings();
293                         for (TransitionFacade incomingForward : incomingForwards)
294                         {
295                             final FrontEndForward forward = (FrontEndForward) incomingForward;
296                             actions.addAll(forward.getActions());
297                         }
298                     }
299                 }
300             }
301         }
302     }
303 
304     /**
305      * Overridden since a transition doesn't exist in a package.
306      *
307      * @see org.andromda.metafacades.emf.uml22.ModelElementFacadeLogic#handleGetPackageName()
308      */
309     @Override
310     protected String handleGetPackageName()
311     {
312         String packageName = null;
313 
314         final UseCaseFacade useCase = this.getUseCase();
315         if (useCase != null)
316         {
317             packageName = useCase.getPackageName();
318         }
319         return packageName;
320     }
321 
322     /**
323      * @see org.andromda.metafacades.uml.FrontEndAction#getForwardParameters()
324      */
325     @Override
326     protected List<ParameterFacade> handleGetForwardParameters()
327     {
328         final EventFacade trigger = this.getTrigger();
329         return trigger == null ? Collections.<ParameterFacade>emptyList() : new ArrayList<ParameterFacade>(trigger.getParameters());
330     }
331 
332     /**
333      * @see org.andromda.metafacades.uml.FrontEndAction#getOperationCall()
334      */
335     @Override
336     protected FrontEndControllerOperation handleGetOperationCall()
337     {
338         FrontEndControllerOperation operation = null;
339         final EventFacade trigger = this.getTrigger();
340         if (trigger instanceof FrontEndEvent)
341         {
342             final FrontEndEvent triggerEvent = (FrontEndEvent)trigger;
343             operation = triggerEvent.getControllerCall();
344         }
345         else
346         {
347             LOGGER.info("FrontEndForward has no FrontEndEvent trigger defined. forward=" + this.getFullyQualifiedName(false) + " trigger=" + trigger);
348         }
349         return operation;
350     }
351 }