001package org.andromda.metafacades.uml14; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Iterator; 006import java.util.LinkedHashMap; 007import java.util.LinkedHashSet; 008import java.util.List; 009import java.util.Map; 010import java.util.Set; 011import org.andromda.metafacades.uml.ActionStateFacade; 012import org.andromda.metafacades.uml.ClassifierFacade; 013import org.andromda.metafacades.uml.EventFacade; 014import org.andromda.metafacades.uml.FrontEndAction; 015import org.andromda.metafacades.uml.FrontEndActionState; 016import org.andromda.metafacades.uml.FrontEndActivityGraph; 017import org.andromda.metafacades.uml.FrontEndController; 018import org.andromda.metafacades.uml.FrontEndControllerOperation; 019import org.andromda.metafacades.uml.FrontEndEvent; 020import org.andromda.metafacades.uml.FrontEndForward; 021import org.andromda.metafacades.uml.FrontEndParameter; 022import org.andromda.metafacades.uml.FrontEndPseudostate; 023import org.andromda.metafacades.uml.FrontEndUseCase; 024import org.andromda.metafacades.uml.ModelElementFacade; 025import org.andromda.metafacades.uml.OperationFacade; 026import org.andromda.metafacades.uml.ParameterFacade; 027import org.andromda.metafacades.uml.StateVertexFacade; 028import org.andromda.metafacades.uml.TransitionFacade; 029import org.apache.log4j.Logger; 030 031/** 032 * MetafacadeLogic implementation for org.andromda.metafacades.uml.FrontEndControllerOperation. 033 * 034 * @see org.andromda.metafacades.uml.FrontEndControllerOperation 035 * @author Bob Fields 036 */ 037public class FrontEndControllerOperationLogicImpl 038 extends FrontEndControllerOperationLogic 039{ 040 private static final long serialVersionUID = 6536778815148740646L; 041 042 /** 043 * @param metaObject 044 * @param context 045 */ 046 public FrontEndControllerOperationLogicImpl( 047 Object metaObject, 048 String context) 049 { 050 super(metaObject, context); 051 } 052 053 /** 054 * The logger instance. 055 */ 056 private static final Logger logger = Logger.getLogger(FrontEndControllerOperationLogicImpl.class); 057 058 /** 059 * Override to return the owner's package as the package name. 060 * 061 * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleGetPackageName() 062 */ 063 public String handleGetPackageName() 064 { 065 final ClassifierFacade owner = this.getOwner(); 066 return owner != null ? owner.getPackageName() : ""; 067 } 068 069 /** 070 * @see org.andromda.metafacades.uml.FrontEndControllerOperation#isOwnerIsController() 071 */ 072 @Override 073 protected boolean handleIsOwnerIsController() 074 { 075 return this.getOwner() instanceof FrontEndController; 076 } 077 078 /** 079 * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getFormFields() 080 */ 081 @Override 082 protected List<FrontEndParameter> handleGetFormFields() 083 { 084 final Map<String, FrontEndParameter> formFieldsMap = new LinkedHashMap<String, FrontEndParameter>(); 085 086 // for quick lookup we use a hashset for the argument names, we only consider parameters with a name 087 // which is also present in this set 088 final Set argumentNames = new LinkedHashSet(); 089 final Collection<ParameterFacade> arguments = this.getArguments(); 090 for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();) 091 { 092 final ModelElementFacade element = (ModelElementFacade)argumentIterator.next(); 093 argumentNames.add(element.getName()); 094 } 095 096 // - get all actions deferring to this operation 097 final List<FrontEndAction> deferringActions = this.getDeferringActions(); 098 for (final Iterator<FrontEndAction> iterator = deferringActions.iterator(); iterator.hasNext();) 099 { 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}