001package org.andromda.cartridges.bpm4struts.metafacades; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.HashMap; 006import java.util.Iterator; 007import java.util.LinkedHashMap; 008import java.util.LinkedHashSet; 009import java.util.List; 010import java.util.Map; 011import java.util.Set; 012import org.andromda.cartridges.bpm4struts.Bpm4StrutsGlobals; 013import org.andromda.metafacades.uml.ClassifierFacade; 014import org.andromda.metafacades.uml.DependencyFacade; 015import org.andromda.metafacades.uml.EventFacade; 016import org.andromda.metafacades.uml.FrontEndActivityGraph; 017import org.andromda.metafacades.uml.FrontEndControllerOperation; 018import org.andromda.metafacades.uml.ModelElementFacade; 019import org.andromda.metafacades.uml.OperationFacade; 020import org.andromda.metafacades.uml.ParameterFacade; 021import org.andromda.metafacades.uml.ServiceOperation; 022import org.andromda.metafacades.uml.StateVertexFacade; 023import org.andromda.utils.StringUtilsHelper; 024 025/** 026 * MetafacadeLogic implementation for org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperation. 027 * 028 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperation 029 */ 030public class StrutsControllerOperationLogicImpl 031 extends StrutsControllerOperationLogic 032{ 033 private static final long serialVersionUID = 34L; 034 /** 035 * @param metaObject 036 * @param context 037 */ 038 public StrutsControllerOperationLogicImpl( 039 Object metaObject, 040 String context) 041 { 042 super(metaObject, context); 043 } 044 045 /** 046 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfaceName() 047 */ 048 protected String handleGetInterfaceName() 049 { 050 return StringUtilsHelper.upperCamelCaseName(getName()) + Bpm4StrutsGlobals.FORM_SUFFIX; 051 } 052 053 /** 054 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfacePackageName() 055 */ 056 protected String handleGetInterfacePackageName() 057 { 058 return getOwner().getPackageName(); 059 } 060 061 /** 062 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfaceType() 063 */ 064 protected String handleGetInterfaceType() 065 { 066 return getInterfacePackageName() + '.' + getInterfaceName(); 067 } 068 069 /** 070 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetInterfaceFullPath() 071 */ 072 protected String handleGetInterfaceFullPath() 073 { 074 return '/' + getInterfaceType().replace('.', '/'); 075 } 076 077 /** 078 * Overridden because StrutsAction does not extend FrontEndAction. 079 * 080 * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getDeferringActions() 081 */ 082 public java.util.List getDeferringActions() 083 { 084 final Collection deferringActions = new LinkedHashSet(); 085 086 final FrontEndActivityGraph graph = getActivityGraph(); 087 if (graph != null) 088 { 089 final Collection actionStates = graph.getActionStates(); 090 for (final Iterator actionStateIterator = actionStates.iterator(); actionStateIterator.hasNext();) 091 { 092 final Object actionStateObject = actionStateIterator.next(); 093 if (actionStateObject instanceof StrutsActionState) 094 { 095 final StrutsActionState actionState = (StrutsActionState)actionStateObject; 096 final Collection controllerCalls = actionState.getControllerCalls(); 097 for (final Iterator controllerCallIterator = controllerCalls.iterator(); 098 controllerCallIterator.hasNext();) 099 { 100 final OperationFacade operation = (OperationFacade)controllerCallIterator.next(); 101 if (this.equals(operation)) 102 { 103 deferringActions.addAll(actionState.getContainerActions()); 104 } 105 } 106 } 107 } 108 109 final Collection transitions = graph.getTransitions(); 110 for (final Iterator transitionIterator = transitions.iterator(); transitionIterator.hasNext();) 111 { 112 final StrutsForward transition = (StrutsForward)transitionIterator.next(); 113 final EventFacade event = transition.getTrigger(); 114 if (event instanceof StrutsTrigger) 115 { 116 final StrutsTrigger trigger = (StrutsTrigger)event; 117 final FrontEndControllerOperation operation = trigger.getControllerCall(); 118 if (this.equals(operation)) 119 { 120 // we have two types of controller calls: the ones in action states and the ones for decisions 121 final StateVertexFacade source = transition.getSource(); 122 if (source instanceof StrutsActionState) 123 { 124 final StrutsActionState sourceActionState = (StrutsActionState)source; 125 deferringActions.addAll(sourceActionState.getContainerActions()); 126 } 127 128 // test for decision 129 final StateVertexFacade target = transition.getTarget(); 130 if (target instanceof StrutsPseudostate) 131 { 132 final StrutsPseudostate targetPseudoState = (StrutsPseudostate)target; 133 if (targetPseudoState.isDecisionPoint()) 134 { 135 deferringActions.addAll(targetPseudoState.getContainerActions()); 136 } 137 } 138 } 139 } 140 } 141 } 142 return new ArrayList(deferringActions); 143 } 144 145 /** 146 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetController() 147 */ 148 protected Object handleGetController() 149 { 150 final Object owner = getOwner(); 151 return (owner instanceof StrutsController) ? owner : null; 152 } 153 154 /** 155 * Overridden since StrutsAction does not extend FrontEndAction. 156 * 157 * @see org.andromda.metafacades.uml.FrontEndControllerOperation#getFormFields() 158 */ 159 public List getFormFields() 160 { 161 final Map formFieldsMap = new LinkedHashMap(); 162 163 // for quick lookup we use a hashset for the argument names, we only consider parameters with a name 164 // which is also present in this set 165 final Set argumentNames = new LinkedHashSet(); 166 final Collection arguments = this.getArguments(); 167 for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();) 168 { 169 final ModelElementFacade element = (ModelElementFacade)argumentIterator.next(); 170 argumentNames.add(element.getName()); 171 } 172 173 // get all actions deferring to this operation 174 final List deferringActions = this.getDeferringActions(); 175 for (int i = 0; i < deferringActions.size(); i++) 176 { 177 final StrutsAction action = (StrutsAction)deferringActions.get(i); 178 // store the action parameters 179 final List actionFormFields = action.getActionFormFields(); 180 for (int j = 0; j < actionFormFields.size(); j++) 181 { 182 final ModelElementFacade parameter = (ModelElementFacade)actionFormFields.get(j); 183 if (argumentNames.contains(parameter.getName())) 184 { 185 formFieldsMap.put(parameter.getName(), parameter); 186 } 187 } 188 // get all forwards and overwrite when we find a table (or add when not yet present) 189 final List forwards = action.getActionForwards(); 190 for (int j = 0; j < forwards.size(); j++) 191 { 192 final StrutsForward forward = (StrutsForward)forwards.get(j); 193 // only consider forwards directly entering a page 194 if (forward.isEnteringPage()) 195 { 196 final List pageVariables = forward.getForwardParameters(); 197 for (int k = 0; k < pageVariables.size(); k++) 198 { 199 final StrutsParameter pageVariable = (StrutsParameter)pageVariables.get(k); 200 if (argumentNames.contains(pageVariable.getName())) 201 { 202 if (!formFieldsMap.containsKey(pageVariable.getName()) || pageVariable.isTable()) 203 { 204 formFieldsMap.put(pageVariable.getName(), pageVariable); 205 } 206 } 207 } 208 } 209 } 210 } 211 212 // since all arguments need to be present we add those that haven't yet been stored in the map 213 for (final Iterator argumentIterator = arguments.iterator(); argumentIterator.hasNext();) 214 { 215 final StrutsParameter argument = (StrutsParameter)argumentIterator.next(); 216 if (!formFieldsMap.containsKey(argument.getName())) 217 { 218 formFieldsMap.put(argument.getName(), argument); 219 } 220 } 221 222 return new ArrayList(formFieldsMap.values()); 223 } 224 225 /** 226 * Overridden because StrutsAction does not extend FrontEndAction 227 * 228 * @see org.andromda.metafacades.uml.FrontEndControllerOperation#isAllArgumentsHaveFormFields() 229 */ 230 public boolean isAllArgumentsHaveFormFields() 231 { 232 final Collection<ParameterFacade> arguments = this.getArguments(); 233 final Collection deferringActions = this.getDeferringActions(); 234 235 boolean allArgumentsHaveFormFields = true; 236 for (final Iterator iterator = arguments.iterator(); iterator.hasNext() && allArgumentsHaveFormFields;) 237 { 238 final ParameterFacade parameter = (ParameterFacade)iterator.next(); 239 final String parameterName = parameter.getName(); 240 final ClassifierFacade parameterType = parameter.getType(); 241 final String parameterTypeName = parameterType != null ? parameterType.getFullyQualifiedName() : ""; 242 243 boolean actionMissingField = false; 244 for (final Iterator actionIterator = deferringActions.iterator(); 245 actionIterator.hasNext() && !actionMissingField;) 246 { 247 final StrutsAction action = (StrutsAction)actionIterator.next(); 248 final Collection<StrutsParameter> actionFormFields = action.getActionFormFields(); 249 250 boolean fieldPresent = false; 251 for (final Iterator fieldIterator = actionFormFields.iterator(); 252 fieldIterator.hasNext() && !fieldPresent;) 253 { 254 final ParameterFacade field = (ParameterFacade)fieldIterator.next(); 255 final ClassifierFacade fieldType = field.getType(); 256 final String fieldTypeName = fieldType != null ? fieldType.getFullyQualifiedName() : ""; 257 if (parameterName.equals(field.getName()) && parameterTypeName.equals(fieldTypeName)) 258 { 259 fieldPresent = true; 260 } 261 } 262 actionMissingField = !fieldPresent; 263 } 264 allArgumentsHaveFormFields = !actionMissingField; 265 } 266 return allArgumentsHaveFormFields; 267 } 268 269 /** 270 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleIsBackEndServiceOperationMatchingParameters() 271 */ 272 protected boolean handleIsBackEndServiceOperationMatchingParameters() 273 { 274 boolean matches = true; 275 276 final ServiceOperation serviceOperation = getBackEndServiceOperation(); 277 278 // cache this operation's parameters for easy lookup 279 final Map parameterMap = new HashMap(); 280 final Collection<ParameterFacade> controllerParameters = getParameters(); 281 for (final Iterator iterator = controllerParameters.iterator(); iterator.hasNext();) 282 { 283 final ParameterFacade parameter = (ParameterFacade)iterator.next(); 284 parameterMap.put(parameter.getName(), parameter.getType()); 285 } 286 287 // make sure that any service parameter exists here too 288 final Collection<ParameterFacade> serviceParameters = serviceOperation.getParameters(); 289 for (final Iterator iterator = serviceParameters.iterator(); iterator.hasNext() && matches;) 290 { 291 final ParameterFacade serviceParameter = (ParameterFacade)iterator.next(); 292 final ClassifierFacade controllerParameterType = (ClassifierFacade)parameterMap.get( 293 serviceParameter.getName()); 294 matches = (controllerParameterType != null) && controllerParameterType.equals(serviceParameter.getType()); 295 } 296 297 return matches; 298 } 299 300 /** 301 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleGetBackEndServiceOperation() 302 */ 303 protected Object handleGetBackEndServiceOperation() 304 { 305 Object operation = null; 306 307 final Collection<DependencyFacade> dependencies = getSourceDependencies(); 308 for (final Iterator dependencyIterator = dependencies.iterator(); 309 dependencyIterator.hasNext() && operation == null;) 310 { 311 final DependencyFacade dependency = (DependencyFacade)dependencyIterator.next(); 312 final Object target = dependency.getTargetElement(); 313 if (target instanceof ServiceOperation) 314 { 315 operation = target; 316 } 317 } 318 319 return operation; 320 } 321 322 /** 323 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsControllerOperationLogic#handleIsCallingBackEnd() 324 */ 325 protected boolean handleIsCallingBackEnd() 326 { 327 return getBackEndServiceOperation() != null; 328 } 329}