View Javadoc
1   package org.andromda.metafacades.uml14;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Iterator;
6   import java.util.LinkedHashMap;
7   import java.util.LinkedHashSet;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Set;
11  import org.andromda.metafacades.uml.ActionStateFacade;
12  import org.andromda.metafacades.uml.ClassifierFacade;
13  import org.andromda.metafacades.uml.EventFacade;
14  import org.andromda.metafacades.uml.FrontEndAction;
15  import org.andromda.metafacades.uml.FrontEndActionState;
16  import org.andromda.metafacades.uml.FrontEndActivityGraph;
17  import org.andromda.metafacades.uml.FrontEndController;
18  import org.andromda.metafacades.uml.FrontEndControllerOperation;
19  import org.andromda.metafacades.uml.FrontEndEvent;
20  import org.andromda.metafacades.uml.FrontEndForward;
21  import org.andromda.metafacades.uml.FrontEndParameter;
22  import org.andromda.metafacades.uml.FrontEndPseudostate;
23  import org.andromda.metafacades.uml.FrontEndUseCase;
24  import org.andromda.metafacades.uml.ModelElementFacade;
25  import org.andromda.metafacades.uml.OperationFacade;
26  import org.andromda.metafacades.uml.ParameterFacade;
27  import org.andromda.metafacades.uml.StateVertexFacade;
28  import org.andromda.metafacades.uml.TransitionFacade;
29  import org.apache.log4j.Logger;
30  
31  /**
32   * MetafacadeLogic implementation for org.andromda.metafacades.uml.FrontEndControllerOperation.
33   *
34   * @see org.andromda.metafacades.uml.FrontEndControllerOperation
35   * @author Bob Fields
36   */
37  public class FrontEndControllerOperationLogicImpl
38      extends FrontEndControllerOperationLogic
39  {
40      private static final long serialVersionUID = 6536778815148740646L;
41  
42      /**
43       * @param metaObject
44       * @param context
45       */
46      public FrontEndControllerOperationLogicImpl(
47          Object metaObject,
48          String context)
49      {
50          super(metaObject, context);
51      }
52  
53      /**
54       * The logger instance.
55       */
56      private static final Logger logger = Logger.getLogger(FrontEndControllerOperationLogicImpl.class);
57  
58      /**
59       * Override to return the owner's package as the package name.
60       *
61       * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleGetPackageName()
62       */
63      public String handleGetPackageName()
64      {
65          final ClassifierFacade owner = this.getOwner();
66          return owner != null ? owner.getPackageName() : "";
67      }
68  
69      /**
70       * @see org.andromda.metafacades.uml.FrontEndControllerOperation#isOwnerIsController()
71       */
72      @Override
73      protected boolean handleIsOwnerIsController()
74      {
75          return this.getOwner() instanceof FrontEndController;
76      }
77  
78      /**
79       * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getFormFields()
80       */
81      @Override
82      protected List<FrontEndParameter> handleGetFormFields()
83      {
84          final Map<String, FrontEndParameter> formFieldsMap = new LinkedHashMap<String, FrontEndParameter>();
85  
86          // for quick lookup we use a hashset for the argument names, we only consider parameters with a name
87          // which is also present in this set
88          final Set argumentNames = new LinkedHashSet();
89          final Collection<ParameterFacade> arguments = this.getArguments();
90          for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();)
91          {
92              final ModelElementFacade element = (ModelElementFacade)argumentIterator.next();
93              argumentNames.add(element.getName());
94          }
95  
96          // - get all actions deferring to this operation
97          final List<FrontEndAction> deferringActions = this.getDeferringActions();
98          for (final Iterator<FrontEndAction> iterator = deferringActions.iterator(); iterator.hasNext();)
99          {
100             final FrontEndAction action = iterator.next();
101             // store the action parameters
102             final List<FrontEndParameter> actionFormFields = action.getFormFields();
103             for (final Iterator<FrontEndParameter> fieldIterator = actionFormFields.iterator(); fieldIterator.hasNext();)
104             {
105                 final FrontEndParameter parameter = fieldIterator.next();
106                 final String name = parameter.getName();
107                 // - only add if the parameter is an action parameter and its an argument of this operation
108                 if (parameter.getAction() != null && argumentNames.contains(name))
109                 {
110                     formFieldsMap.put(name, parameter);
111                 }
112             }
113             // get all forwards and overwrite when we find a table (or add when not yet present)
114             final List<FrontEndForward> forwards = action.getActionForwards();
115             for (final Iterator<FrontEndForward> forwardIterator = forwards.iterator(); forwardIterator.hasNext();)
116             {
117                 final FrontEndForward forward = forwardIterator.next();
118                 // - only consider forwards directly entering a view
119                 if (forward.isEnteringView())
120                 {
121                     final List<FrontEndParameter> viewVariables = forward.getForwardParameters();
122                     for (final Iterator<FrontEndParameter> variableIterator = viewVariables.iterator(); variableIterator.hasNext();)
123                     {
124                         final FrontEndParameter viewVariable = variableIterator.next();
125                         final String name = viewVariable.getName();
126                         if (argumentNames.contains(name))
127                         {
128                             if (!formFieldsMap.containsKey(name) || viewVariable.isTable())
129                             {
130                                 formFieldsMap.put(name, viewVariable);
131                             }
132                         }
133                     }
134                 }
135             }
136         }
137 
138         // since all arguments need to be present we add those that haven't yet been stored in the map
139         for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();)
140         {
141             final FrontEndParameter argument = (FrontEndParameter)argumentIterator.next();
142             final String name = argument.getName();
143             if (!formFieldsMap.containsKey(name))
144             {
145                 formFieldsMap.put(name, argument);
146             }
147         }
148         return new ArrayList<FrontEndParameter>(formFieldsMap.values());
149     }
150 
151     /**
152      * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getActivityGraph()
153      */
154     @Override
155     protected FrontEndActivityGraph handleGetActivityGraph()
156     {
157         FrontEndActivityGraph graph = null;
158 
159         final ClassifierFacade owner = getOwner();
160         if (owner instanceof FrontEndController)
161         {
162             final FrontEndController controller = (FrontEndController)owner;
163             final FrontEndUseCase useCase = controller.getUseCase();
164             if (useCase != null)
165             {
166                 graph = useCase.getActivityGraph();
167             }
168         }
169         return graph;
170     }
171 
172     /**
173      * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getDeferringActions()
174      */
175     @Override
176     protected List<FrontEndAction> handleGetDeferringActions()
177     {
178         final Collection<FrontEndAction> deferringActions = new LinkedHashSet<FrontEndAction>();
179 
180         final FrontEndActivityGraph graph = this.getActivityGraph();
181         if (graph != null)
182         {
183             final Collection<ActionStateFacade> actionStates = graph.getActionStates();
184             for (final Iterator<ActionStateFacade> actionStateIterator = actionStates.iterator(); actionStateIterator.hasNext();)
185             {
186                 final ActionStateFacade actionStateObject = actionStateIterator.next();
187                 if (actionStateObject instanceof FrontEndActionState)
188                 {
189                     final FrontEndActionState actionState = (FrontEndActionState)actionStateObject;
190                     final Collection<OperationFacade> controllerCalls = actionState.getControllerCalls();
191                     for (final Iterator<OperationFacade> controllerCallIterator = controllerCalls.iterator();
192                         controllerCallIterator.hasNext();)
193                     {
194                         final OperationFacade operation = controllerCallIterator.next();
195                         if (this.equals(operation))
196                         {
197                             deferringActions.addAll(actionState.getContainerActions());
198                         }
199                     }
200                 }
201             }
202 
203             final Collection<TransitionFacade> transitions = graph.getTransitions();
204             for (final Iterator<TransitionFacade> transitionIterator = transitions.iterator(); transitionIterator.hasNext();)
205             {
206                 final FrontEndForward transition = (FrontEndForward)transitionIterator.next();
207                 final EventFacade event = transition.getTrigger();
208                 if (event instanceof FrontEndEvent)
209                 {
210                     final FrontEndEvent trigger = (FrontEndEvent)event;
211                     final FrontEndControllerOperation operation = trigger.getControllerCall();
212                     if (this.equals(operation))
213                     {
214                         // we have two types of controller calls: the ones in action states and the ones for decisions
215                         final StateVertexFacade source = transition.getSource();
216                         if (source instanceof FrontEndActionState)
217                         {
218                             final FrontEndActionState sourceActionState = (FrontEndActionState)source;
219                             deferringActions.addAll(sourceActionState.getContainerActions());
220                         }
221 
222                         // test for decision
223                         final StateVertexFacade target = transition.getTarget();
224                         if (target instanceof FrontEndPseudostate)
225                         {
226                             final FrontEndPseudostate targetPseudoState = (FrontEndPseudostate)target;
227                             if (targetPseudoState.isDecisionPoint())
228                             {
229                                 deferringActions.addAll(targetPseudoState.getContainerActions());
230                             }
231                         }
232                     }
233                 }
234             }
235         }
236         return new ArrayList(deferringActions);
237     }
238 
239     /**
240      * @see org.andromda.metafacades.uml.FrontEndControllerOperation#isAllArgumentsHaveFormFields()
241      */
242     @Override
243     protected boolean handleIsAllArgumentsHaveFormFields()
244     {
245         final Collection<ParameterFacade> arguments = this.getArguments();
246         final Collection<FrontEndAction> deferringActions = this.getDeferringActions();
247 
248         boolean allArgumentsHaveFormFields = true;
249         for (final Iterator<ParameterFacade> iterator = arguments.iterator(); iterator.hasNext() && allArgumentsHaveFormFields;)
250         {
251             final ParameterFacade parameter = iterator.next();
252             final String parameterName = parameter.getName();
253             final ClassifierFacade parameterType = parameter.getType();
254             final String parameterTypeName = parameterType != null ? parameterType.getFullyQualifiedName() : "";
255 
256             boolean actionMissingField = false;
257             for (final Iterator<FrontEndAction> actionIterator = deferringActions.iterator();
258                 actionIterator.hasNext() && !actionMissingField;)
259             {
260                 final Object obj = actionIterator.next();
261                 // BPM4Struts throws a ClassCastException when validating model unless we add try/catch
262                 try
263                 {
264                     final FrontEndAction action = (FrontEndAction)obj;
265                     final Collection<FrontEndParameter> actionFormFields = action.getFormFields();
266 
267                     boolean fieldPresent = false;
268                     for (final Iterator<FrontEndParameter> fieldIterator = actionFormFields.iterator();
269                         fieldIterator.hasNext() && !fieldPresent;)
270                     {
271                         final ParameterFacade field = (ParameterFacade)fieldIterator.next();
272                         final ClassifierFacade fieldType = field.getType();
273                         final String fieldTypeName = fieldType != null ? fieldType.getFullyQualifiedName() : "";
274                         if (parameterName.equals(field.getName()) && parameterTypeName.equals(fieldTypeName))
275                         {
276                             fieldPresent = true;
277                         }
278                     }
279                     actionMissingField = !fieldPresent;
280                 }
281                 catch (ClassCastException e)
282                 {
283                     logger.error("ClassCastException on handleIsAllArgumentsHaveFormFields for " + obj + ' ' + e.getMessage());
284                 }
285             }
286             allArgumentsHaveFormFields = !actionMissingField;
287         }
288         return allArgumentsHaveFormFields;
289     }
290 }