001: package org.andromda.metafacades.emf.uml2;
002:
003: import java.util.ArrayList;
004: import java.util.Collection;
005: import java.util.Collections;
006: import java.util.Iterator;
007: import java.util.LinkedHashMap;
008: import java.util.LinkedHashSet;
009: import java.util.List;
010: import java.util.Map;
011:
012: import org.andromda.metafacades.uml.EventFacade;
013: import org.andromda.metafacades.uml.FrontEndActionState;
014: import org.andromda.metafacades.uml.FrontEndActivityGraph;
015: import org.andromda.metafacades.uml.FrontEndController;
016: import org.andromda.metafacades.uml.FrontEndEvent;
017: import org.andromda.metafacades.uml.FrontEndFinalState;
018: import org.andromda.metafacades.uml.FrontEndForward;
019: import org.andromda.metafacades.uml.FrontEndParameter;
020: import org.andromda.metafacades.uml.FrontEndUseCase;
021: import org.andromda.metafacades.uml.FrontEndView;
022: import org.andromda.metafacades.uml.ModelElementFacade;
023: import org.andromda.metafacades.uml.OperationFacade;
024: import org.andromda.metafacades.uml.ParameterFacade;
025: import org.andromda.metafacades.uml.PseudostateFacade;
026: import org.andromda.metafacades.uml.StateVertexFacade;
027: import org.andromda.metafacades.uml.TransitionFacade;
028: import org.andromda.metafacades.uml.UseCaseFacade;
029: import org.apache.commons.collections.CollectionUtils;
030: import org.apache.commons.collections.Predicate;
031: import org.apache.commons.lang.StringUtils;
032:
033: /**
034: * MetafacadeLogic implementation for
035: * org.andromda.metafacades.uml.FrontEndAction.
036: *
037: * @see org.andromda.metafacades.uml.FrontEndAction
038: */
039: public class FrontEndActionLogicImpl extends FrontEndActionLogic {
040: public FrontEndActionLogicImpl(final Object metaObject,
041: final String context) {
042: super (metaObject, context);
043: }
044:
045: /**
046: * @see org.andromda.metafacades.uml.FrontEndAction#getInput()
047: */
048: protected java.lang.Object handleGetInput() {
049: Object input = null;
050: final ModelElementFacade source = this .getSource();
051: if (source instanceof PseudostateFacade) {
052: final PseudostateFacade pseudostate = (PseudostateFacade) source;
053: if (pseudostate.isInitialState()) {
054: input = source;
055: }
056: } else {
057: if (source instanceof FrontEndView) {
058: input = source;
059: }
060: }
061: return input;
062: }
063:
064: /**
065: * @see org.andromda.metafacades.uml.FrontEndAction#getParameters()
066: */
067: protected java.util.List handleGetParameters() {
068: final EventFacade trigger = this .getTrigger();
069: return trigger == null ? Collections.EMPTY_LIST
070: : new ArrayList(trigger.getParameters());
071: }
072:
073: /**
074: * @see org.andromda.metafacades.uml.FrontEndAction#findParameter(java.lang.String)
075: */
076: protected ParameterFacade handleFindParameter(final String name) {
077: return (ParameterFacade) CollectionUtils.find(this
078: .getParameters(), new Predicate() {
079: public boolean evaluate(final Object object) {
080: final ParameterFacade parameter = (ParameterFacade) object;
081: return StringUtils.trimToEmpty(parameter.getName())
082: .equals(name);
083: }
084: });
085: }
086:
087: /**
088: * @see org.andromda.metafacades.uml.FrontEndAction#getDeferredOperations()
089: */
090: protected java.util.List handleGetDeferredOperations() {
091: final Collection deferredOperations = new LinkedHashSet();
092: final FrontEndController controller = this .getController();
093: if (controller != null) {
094: final List actionStates = this .getActionStates();
095: for (int ctr = 0; ctr < actionStates.size(); ctr++) {
096: final FrontEndActionState actionState = (FrontEndActionState) actionStates
097: .get(ctr);
098: deferredOperations.addAll(actionState
099: .getControllerCalls());
100: }
101:
102: final List transitions = this .getDecisionTransitions();
103: for (int ctr = 0; ctr < transitions.size(); ctr++) {
104: final FrontEndForward forward = (FrontEndForward) transitions
105: .get(ctr);
106: final FrontEndEvent trigger = forward
107: .getDecisionTrigger();
108: if (trigger != null) {
109: deferredOperations.add(trigger.getControllerCall());
110: }
111: }
112: }
113: return new ArrayList(deferredOperations);
114: }
115:
116: /**
117: * @see org.andromda.metafacades.uml.FrontEndAction#getDecisionTransitions()
118: */
119: protected List handleGetDecisionTransitions() {
120: if (this .decisionTransitions == null) {
121: this .initializeCollections();
122: }
123: return new ArrayList(this .decisionTransitions);
124: }
125:
126: /**
127: * @see org.andromda.metafacades.uml.FrontEndAction#getTargetViews()
128: */
129: protected List handleGetTargetViews() {
130: final Collection targetViews = new LinkedHashSet();
131: final Collection forwards = this .getActionForwards();
132: for (final Iterator iterator = forwards.iterator(); iterator
133: .hasNext();) {
134: final FrontEndForward forward = (FrontEndForward) iterator
135: .next();
136: if (forward.isEnteringView()) {
137: targetViews.add(forward.getTarget());
138: }
139: }
140: return new ArrayList(targetViews);
141: }
142:
143: /**
144: * All action states that make up this action, this includes all possible
145: * action states traversed after a decision point too.
146: */
147: private Collection actionStates = null;
148:
149: /**
150: * All transitions leading into either a page or final state that originated
151: * from a call to this action.
152: */
153: private Map actionForwards = null;
154:
155: /**
156: * All transitions leading into a decision point that originated from a call
157: * to this action.
158: */
159: private Collection decisionTransitions = null;
160:
161: /**
162: * All transitions that can be traversed when calling this action.
163: */
164: private Collection transitions = null;
165:
166: /**
167: * Initializes all action states, action forwards, decision transitions and
168: * transitions in one shot, so that they can be queried more effiencently
169: * later on.
170: */
171: private void initializeCollections() {
172: this .actionStates = new LinkedHashSet();
173: this .actionForwards = new LinkedHashMap();
174: this .decisionTransitions = new LinkedHashSet();
175: this .transitions = new LinkedHashSet();
176: this .collectTransitions((TransitionFacade) this .THIS(),
177: this .transitions);
178: }
179:
180: /**
181: * Recursively collects all action states, action forwards, decision
182: * transitions and transitions.
183: *
184: * @param transition
185: * the current transition that is being processed
186: * @param processedTransitions
187: * the set of transitions already processed
188: */
189: private void collectTransitions(final TransitionFacade transition,
190: final Collection processedTransitions) {
191: if (processedTransitions.contains(transition)) {
192: return;
193: }
194: processedTransitions.add(transition);
195: final StateVertexFacade target = transition.getTarget();
196: if (target instanceof FrontEndView
197: || target instanceof FrontEndFinalState) {
198: if (!this .actionForwards
199: .containsKey(transition.getTarget())) {
200: this .actionForwards.put(transition.getTarget(),
201: transition);
202: }
203: } else if (target instanceof PseudostateFacade
204: && ((PseudostateFacade) target).isDecisionPoint()) {
205: this .decisionTransitions.add(transition);
206: final Collection outcomes = target.getOutgoing();
207: for (final Iterator iterator = outcomes.iterator(); iterator
208: .hasNext();) {
209: final TransitionFacade outcome = (TransitionFacade) iterator
210: .next();
211: this .collectTransitions(outcome, processedTransitions);
212: }
213: } else if (target instanceof FrontEndActionState) {
214: this .actionStates.add(target);
215: final FrontEndForward forward = ((FrontEndActionState) target)
216: .getForward();
217: if (forward != null) {
218: this .collectTransitions(forward, processedTransitions);
219: }
220: } else// all the rest is ignored but outgoing transitions are further
221: // processed
222: {
223: final Collection outcomes = target.getOutgoing();
224: for (final Iterator iterator = outcomes.iterator(); iterator
225: .hasNext();) {
226: final TransitionFacade outcome = (TransitionFacade) iterator
227: .next();
228: this .collectTransitions(outcome, processedTransitions);
229: }
230: }
231: }
232:
233: /**
234: * @see org.andromda.metafacades.uml.FrontEndAction#getActionStates()
235: */
236: protected List handleGetActionStates() {
237: if (this .actionStates == null) {
238: this .initializeCollections();
239: }
240: return new ArrayList(this .actionStates);
241: }
242:
243: /**
244: * @see org.andromda.metafacades.uml.FrontEndAction#getTransitions()
245: */
246: protected List handleGetTransitions() {
247: if (this .transitions == null) {
248: this .initializeCollections();
249: }
250: return new ArrayList(this .transitions);
251: }
252:
253: /**
254: * @see org.andromda.metafacades.uml.FrontEndAction#getActionForwards()
255: */
256: protected List handleGetActionForwards() {
257: if (this .actionForwards == null) {
258: this .initializeCollections();
259: }
260: return new ArrayList(this .actionForwards.values());
261: }
262:
263: /**
264: * @see org.andromda.metafacades.uml.FrontEndAction#getController()
265: */
266: protected Object handleGetController() {
267: final FrontEndActivityGraph graph = this
268: .getFrontEndActivityGraph();
269: return graph == null ? null : graph.getController();
270: }
271:
272: /**
273: * Overridden because actions (transitions) are not directly contained in a
274: * UML namespace.
275: *
276: * @see org.andromda.metafacades.uml.ModelElementFacade#getPackageName()
277: */
278: public String handleGetPackageName() {
279: String packageName = null;
280:
281: final UseCaseFacade useCase = this .getUseCase();
282: if (useCase != null) {
283: packageName = useCase.getPackageName();
284: }
285: return packageName;
286: }
287:
288: /**
289: * @see org.andromda.metafacades.uml.FrontEndAction#isUseCaseStart()
290: */
291: protected boolean handleIsUseCaseStart() {
292: final StateVertexFacade source = this .getSource();
293: return source instanceof PseudostateFacade
294: && ((PseudostateFacade) source).isInitialState();
295: }
296:
297: /**
298: * @see org.andromda.metafacades.uml.FrontEndAction#getFormFields()
299: */
300: protected List handleGetFormFields() {
301: final Map formFieldMap = new LinkedHashMap();
302:
303: // - For an action that starts the use case, we need to detect all
304: // usecases forwarding to the one
305: // belonging to this action if there are any parameters in those
306: // transitions we need to have
307: // them included in this action's form
308: if (this .isUseCaseStart()) {
309: final FrontEndUseCase useCase = this .getUseCase();
310: if (useCase != null) {
311: final Collection finalStates = useCase
312: .getReferencingFinalStates();
313: for (final Iterator finalStateIterator = finalStates
314: .iterator(); finalStateIterator.hasNext();) {
315: final Object finalStateObject = finalStateIterator
316: .next();
317:
318: // we need to test for the type because a non
319: // struts-use-case final state might accidently
320: // we linking to this use-case (for example: the user
321: // temporarily wants to disable code generation
322: // for a specific use-case and is not removing the
323: // final-state to use-case link(s))
324: if (finalStateObject instanceof FrontEndFinalState) {
325: final FrontEndFinalState finalState = (FrontEndFinalState) finalStateObject;
326: final Collection parameters = finalState
327: .getInterUseCaseParameters();
328: for (final Iterator parameterIterator = parameters
329: .iterator(); parameterIterator
330: .hasNext();) {
331: final ParameterFacade parameter = (ParameterFacade) parameterIterator
332: .next();
333: formFieldMap.put(parameter.getName(),
334: parameter);
335: }
336: }
337: }
338: }
339: }
340:
341: // if any action encountered by the execution of the complete
342: // action-graph path emits a forward
343: // containing one or more parameters they need to be included as a form
344: // field too
345: final Collection actionStates = this .getActionStates();
346: for (final Iterator iterator = actionStates.iterator(); iterator
347: .hasNext();) {
348: final FrontEndActionState actionState = (FrontEndActionState) iterator
349: .next();
350: final FrontEndForward forward = actionState.getForward();
351: if (forward != null) {
352: final Collection forwardParameters = forward
353: .getForwardParameters();
354: for (final Iterator parameterIterator = forwardParameters
355: .iterator(); parameterIterator.hasNext();) {
356: final ModelElementFacade forwardParameter = (ModelElementFacade) parameterIterator
357: .next();
358: formFieldMap.put(forwardParameter.getName(),
359: forwardParameter);
360: }
361: }
362: }
363:
364: // add page variables for all pages/final-states targetted
365: // also add the fields of the target page's actions (for preloading)
366: final Collection forwards = this .getActionForwards();
367: for (final Iterator iterator = forwards.iterator(); iterator
368: .hasNext();) {
369: final FrontEndForward forward = (FrontEndForward) iterator
370: .next();
371: final StateVertexFacade target = forward.getTarget();
372: if (target instanceof FrontEndView) {
373: final FrontEndView view = (FrontEndView) target;
374: final Collection viewVariables = view.getVariables();
375: for (final Iterator pageVariableIterator = viewVariables
376: .iterator(); pageVariableIterator.hasNext();) {
377: final ModelElementFacade facade = (ModelElementFacade) pageVariableIterator
378: .next();
379: formFieldMap.put(facade.getName(), facade);
380: }
381: final Collection allActionParameters = view
382: .getAllFormFields();
383: for (final Iterator actionParameterIterator = allActionParameters
384: .iterator(); actionParameterIterator.hasNext();) {
385: // - don't allow existing parameters that are tables be
386: // overwritten (since they take
387: // precedence
388: final Object parameter = actionParameterIterator
389: .next();
390: if (parameter instanceof FrontEndParameter) {
391: FrontEndParameter variable = (FrontEndParameter) parameter;
392: final String name = variable.getName();
393: final Object existingParameter = formFieldMap
394: .get(name);
395: if (existingParameter instanceof FrontEndParameter) {
396: final FrontEndParameter existingVariable = (FrontEndParameter) existingParameter;
397: if (existingVariable != null) {
398: if (existingVariable.isTable()) {
399: variable = existingVariable;
400: }
401: }
402: }
403: formFieldMap.put(name, variable);
404: }
405: }
406: } else if (target instanceof FrontEndFinalState) {
407: // only add these if there is no parameter recorded yet with the
408: // same name
409: final Collection forwardParameters = forward
410: .getForwardParameters();
411: for (final Iterator parameterIterator = forwardParameters
412: .iterator(); parameterIterator.hasNext();) {
413: final ModelElementFacade facade = (ModelElementFacade) parameterIterator
414: .next();
415: if (!formFieldMap.containsKey(facade.getName())) {
416: formFieldMap.put(facade.getName(), facade);
417: }
418: }
419: }
420: }
421:
422: // we do the action parameters in the end because they are allowed to
423: // overwrite existing properties
424: final Collection actionParameters = this .getParameters();
425: for (final Iterator parameterIterator = actionParameters
426: .iterator(); parameterIterator.hasNext();) {
427: final Object parameter = parameterIterator.next();
428: if (parameter instanceof FrontEndParameter) {
429: final FrontEndParameter variable = (FrontEndParameter) parameter;
430: formFieldMap.put(variable.getName(), variable);
431: }
432: }
433:
434: // - if we don't have any fields defined on this action and there are no
435: // action forwards,
436: // take the parameters from the deferred operations (since we would want
437: // to stay on the same view)
438: if (formFieldMap.isEmpty()
439: && this .getActionForwards().isEmpty()) {
440: for (final Iterator iterator = this .getDeferredOperations()
441: .iterator(); iterator.hasNext();) {
442: final OperationFacade operation = (OperationFacade) iterator
443: .next();
444: for (final Iterator parameterIterator = operation
445: .getArguments().iterator(); parameterIterator
446: .hasNext();) {
447: final ParameterFacade parameter = (ParameterFacade) parameterIterator
448: .next();
449: formFieldMap.put(parameter.getName(), parameter);
450: }
451: }
452: }
453: return new ArrayList(formFieldMap.values());
454: }
455: }
|