001package org.andromda.metafacades.uml14; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Collections; 006import java.util.LinkedHashSet; 007import java.util.List; 008import java.util.Set; 009import org.andromda.metafacades.uml.EventFacade; 010import org.andromda.metafacades.uml.FrontEndAction; 011import org.andromda.metafacades.uml.FrontEndActionState; 012import org.andromda.metafacades.uml.FrontEndActivityGraph; 013import org.andromda.metafacades.uml.FrontEndControllerOperation; 014import org.andromda.metafacades.uml.FrontEndEvent; 015import org.andromda.metafacades.uml.FrontEndForward; 016import org.andromda.metafacades.uml.FrontEndUseCase; 017import org.andromda.metafacades.uml.FrontEndView; 018import org.andromda.metafacades.uml.ParameterFacade; 019import org.andromda.metafacades.uml.PseudostateFacade; 020import org.andromda.metafacades.uml.StateVertexFacade; 021import org.andromda.metafacades.uml.TransitionFacade; 022import org.andromda.metafacades.uml.UseCaseFacade; 023import org.andromda.utils.StringUtilsHelper; 024 025/** 026 * MetafacadeLogic implementation for org.andromda.metafacades.uml.FrontEndForward. 027 * 028 * @see org.andromda.metafacades.uml.FrontEndForward 029 * @author Bob Fields 030 */ 031public class FrontEndForwardLogicImpl 032 extends FrontEndForwardLogic 033{ 034 private static final long serialVersionUID = 34L; 035 /** 036 * @param metaObject 037 * @param context 038 */ 039 public FrontEndForwardLogicImpl( 040 Object metaObject, 041 String context) 042 { 043 super(metaObject, context); 044 } 045 046 /** 047 * @see org.andromda.metafacades.uml.FrontEndForward#isContainedInFrontEndUseCase() 048 */ 049 @Override 050 protected boolean handleIsContainedInFrontEndUseCase() 051 { 052 return this.getFrontEndActivityGraph() != null; 053 } 054 055 /** 056 * @see org.andromda.metafacades.uml.FrontEndForward#getFrontEndActivityGraph() 057 */ 058 @Override 059 protected FrontEndActivityGraph handleGetFrontEndActivityGraph() 060 { 061 final Object graph = this.getSource().getStateMachine(); 062 return (FrontEndActivityGraph)(graph instanceof FrontEndActivityGraph ? graph : null); 063 } 064 065 /** 066 * If this forward has a trigger this method returns that trigger's name, otherwise if this forward 067 * has a name this method returns that name, otherwise if this forward's target has a name this 068 * method returns that name, otherwise simply returns <code>"unknown"</code> 069 * 070 * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleGetName() 071 */ 072 protected final String handleGetName() 073 { 074 String forwardName = null; 075 076 // - trigger 077 final EventFacade trigger = getTrigger(); 078 if (trigger != null) 079 { 080 forwardName = trigger.getName(); 081 } 082 083 // - name 084 if (forwardName == null) 085 { 086 forwardName = super.handleGetName(); 087 } 088 089 // - target 090 if (forwardName == null) 091 { 092 forwardName = this.getTarget().getName(); 093 } 094 095 // - else 096 if (forwardName == null) 097 { 098 forwardName = "unknown"; 099 } 100 return forwardName; 101 } 102 103 /** 104 * @see org.andromda.metafacades.uml.FrontEndForward#getActionMethodName() 105 */ 106 @Override 107 protected String handleGetActionMethodName() 108 { 109 return StringUtilsHelper.lowerCamelCaseName(this.getName()); 110 } 111 112 /** 113 * @see org.andromda.metafacades.uml.FrontEndForward#isEnteringView() 114 */ 115 @Override 116 protected boolean handleIsEnteringView() 117 { 118 return this.getTarget() instanceof FrontEndView; 119 } 120 121 /** 122 * @see org.andromda.metafacades.uml.FrontEndForward#isExitingView() 123 */ 124 @Override 125 protected boolean handleIsExitingView() 126 { 127 return this.getSource() instanceof FrontEndView; 128 } 129 130 /** 131 * @see org.andromda.metafacades.uml.FrontEndForward#getUseCase() 132 */ 133 @Override 134 protected FrontEndUseCase handleGetUseCase() 135 { 136 FrontEndUseCase useCase = null; 137 final FrontEndActivityGraph graph = this.getFrontEndActivityGraph(); 138 if (graph != null) 139 { 140 final UseCaseFacade graphUseCase = graph.getUseCase(); 141 if (graphUseCase instanceof FrontEndUseCase) 142 { 143 useCase = (FrontEndUseCase)graphUseCase; 144 } 145 } 146 return useCase; 147 } 148 149 /** 150 * All action states that make up this action, this includes all possible action states traversed 151 * after a decision point too. 152 */ 153 private Collection<FrontEndActionState> actionStates = null; 154 155 /** 156 * @return new ArrayList(actionStates) 157 * @see org.andromda.metafacades.uml.FrontEndAction#getActionStates() 158 */ 159 //@Override 160 protected List<FrontEndActionState> handleGetActionStates() 161 { 162 if (actionStates == null) 163 { 164 this.initializeCollections(); 165 } 166 return new ArrayList<FrontEndActionState>(actionStates); 167 } 168 169 /** 170 * Initializes all action states, action forwards, decision transitions and transitions in one shot, so that they 171 * can be queried more efficiently later on. 172 */ 173 private void initializeCollections() 174 { 175 this.actionStates = new LinkedHashSet<FrontEndActionState>(); 176 this.collectTransitions( 177 this, 178 new LinkedHashSet<TransitionFacade>()); 179 } 180 181 /** 182 * Recursively collects all action states, action forwards, decision transitions and transitions. 183 * 184 * @param transition the current transition that is being processed 185 * @param processedTransitions the set of transitions already processed 186 */ 187 private void collectTransitions( 188 final TransitionFacade transition, 189 final Collection<TransitionFacade> processedTransitions) 190 { 191 if (processedTransitions.contains(transition)) 192 { 193 return; 194 } 195 processedTransitions.add(transition); 196 197 final StateVertexFacade target = transition.getTarget(); 198 if (target instanceof FrontEndActionState) 199 { 200 this.actionStates.add((FrontEndActionState)target); 201 final FrontEndForward forward = ((FrontEndActionState)target).getForward(); 202 if (forward != null) 203 { 204 collectTransitions( 205 forward, 206 processedTransitions); 207 } 208 } 209 } 210 211 /** 212 * @see org.andromda.metafacades.uml.FrontEndAction#getDecisionTrigger() 213 */ 214 @Override 215 protected EventFacade handleGetDecisionTrigger() 216 { 217 return (this.isEnteringDecisionPoint() ? getTrigger() : null); 218 } 219 220 /** 221 * @see org.andromda.metafacades.uml.FrontEndAction#getActions() 222 */ 223 @Override 224 protected List<FrontEndAction> handleGetActions() 225 { 226 final Set<FrontEndAction> actions = new LinkedHashSet<FrontEndAction>(); 227 this.findActions( 228 actions, 229 new LinkedHashSet<FrontEndForward>()); 230 return new ArrayList<FrontEndAction>(actions); 231 } 232 233 /** 234 * Recursively finds all actions for this forward, what this means depends on the context in which 235 * this forward is used: if the source is a page action state it will collect all actions going out 236 * of this page, if the source is a regular action state it will collect all actions that might traverse 237 * this action state, if the source is the initial state it will collect all actions forwarding to this 238 * forward's use-case (please not that those actions most likely are defined in other use-cases). 239 * 240 * @param actions the default set of actions, duplicates will not be recorded 241 * @param handledForwards the forwards already processed 242 */ 243 private void findActions( 244 final Set<FrontEndAction> actions, 245 final Set<FrontEndForward> handledForwards) 246 { 247 if (!handledForwards.contains(this.THIS())) 248 { 249 handledForwards.add(this); 250 251 if (this instanceof FrontEndAction) // TODO this is not so nice because FrontEndAction extends FrontEndForward, solution would be to override in FrontEndAction 252 { 253 actions.add((FrontEndAction)this.THIS()); 254 } 255 else 256 { 257 final StateVertexFacade vertex = getSource(); 258 if (vertex instanceof FrontEndView) 259 { 260 final FrontEndView view = (FrontEndView)vertex; 261 actions.addAll(view.getActions()); 262 } 263 else if (vertex instanceof FrontEndActionState) 264 { 265 final FrontEndActionState actionState = (FrontEndActionState)vertex; 266 actions.addAll(actionState.getContainerActions()); 267 } 268 else if (vertex instanceof PseudostateFacade) 269 { 270 final PseudostateFacade pseudostate = (PseudostateFacade)vertex; 271 if (!pseudostate.isInitialState()) 272 { 273 final Collection<TransitionFacade> incomingForwards = pseudostate.getIncomings(); 274 for (TransitionFacade incomingForward : incomingForwards) 275 { 276 final FrontEndForward forward = (FrontEndForward) incomingForward; 277 actions.addAll(forward.getActions()); 278 } 279 } 280 } 281 } 282 } 283 } 284 285 /** 286 * Overridden since a transition doesn't exist in a package. 287 * 288 * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleGetPackageName() 289 */ 290 protected String handleGetPackageName() 291 { 292 String packageName = null; 293 294 final UseCaseFacade useCase = this.getUseCase(); 295 if (useCase != null) 296 { 297 packageName = useCase.getPackageName(); 298 } 299 return packageName; 300 } 301 302 /** 303 * @see org.andromda.metafacades.uml.FrontEndAction#getForwardParameters() 304 */ 305 @Override 306 protected List<ParameterFacade> handleGetForwardParameters() 307 { 308 final EventFacade trigger = this.getTrigger(); 309 return trigger == null ? Collections.EMPTY_LIST : new ArrayList<ParameterFacade>(trigger.getParameters()); 310 } 311 312 /** 313 * @see org.andromda.metafacades.uml.FrontEndAction#getOperationCall() 314 */ 315 @Override 316 protected Object handleGetOperationCall() 317 { 318 FrontEndControllerOperation operation = null; 319 final EventFacade triggerEvent = this.getTrigger(); 320 if (triggerEvent instanceof FrontEndEvent) 321 { 322 final FrontEndEvent trigger = (FrontEndEvent)triggerEvent; 323 operation = trigger.getControllerCall(); 324 } 325 return operation; 326 } 327}