1 23 package org.mdarad.framework.util.struts; 24 25 import java.lang.reflect.InvocationTargetException ; 26 import java.lang.reflect.Method ; 27 import java.util.Collection ; 28 import java.util.Enumeration ; 29 import java.util.Iterator ; 30 31 import javax.servlet.http.HttpServletRequest ; 32 import javax.servlet.http.HttpServletResponse ; 33 34 import org.apache.commons.beanutils.ConvertUtils; 35 import org.apache.commons.lang.StringUtils; 36 import org.apache.struts.Globals; 37 import org.apache.struts.action.ActionForm; 38 import org.apache.struts.action.ActionForward; 39 import org.apache.struts.action.ActionMapping; 40 import org.apache.struts.action.ActionMessage; 41 import org.apache.struts.action.ActionMessages; 42 import org.apache.struts.tiles.actions.TilesAction; 43 import org.dataisland.primitives.bean.Entity; 44 import org.dataisland.primitives.bean.EntityPrimaryKey; 45 import org.mdarad.framework.delegates.BusinessDelegate; 46 import org.mdarad.framework.exception.ConcurrencyException; 47 import org.mdarad.framework.exception.ServiceLocatorException; 48 import org.mdarad.framework.exception.SystemException; 49 import org.mdarad.framework.util.GUIDGenerationException; 50 import org.mdarad.framework.util.struts.contextstack.ContextStack; 51 import org.mdarad.framework.util.struts.contextstack.ContextStackElement; 52 import org.mdarad.framework.util.struts.contextstack.ContextUpdateException; 53 import org.mdarad.framework.util.struts.contextstack.OrphanChildException; 54 55 public abstract class AbstractAction extends TilesAction { 56 public static final String WEB_CONTEXT_LOCALIZATION_CONTEXT_KEY = "org.mdarad.framework.util.struts.AbstractAction.webLocalizationContext"; 57 public static final String AGGREGATION_PARENT_FORWARD_PREFIX = "parent"; 58 public static final String AGGREGATION_PARENT_FORWARD_SEPARATOR = "-"; 59 public static final String SUCCESS_FORWARD_KEY = "success"; 60 public static final String CANCEL_FORWARD_KEY = "cancel"; 61 public static final String DISPLAY_FORWARD_KEY = "display"; 62 public static final String FAILURE_FORWARD_KEY = "failure"; 63 public static final String CHILD_AGGREGATION_FORWARD_PREFIX = "child"; 64 public static final String CHILD_AGGREGATION_FORWARD_SEPARATOR = "-"; 65 public final static String FORM_CHILD_ACTION_SUFFIX_PARAMETER_KEY = "form"; 66 public final static String DELETE_CHILD_ACTION_SUFFIX_PARAMETER_KEY = "delete"; 67 public final static String CONTEXT_STACK_USE_PARAMETER_KEY = "org.mdarad.framework.util.struts.AbstractAction.useContextStack"; 68 public final static String ID_IN_REQUEST_ATTRIBUTE_PARAMETER_KEY = "org.mdarad.framework.util.struts.AbstractAction.idInRequestAttributes"; 69 70 71 protected ActionForward forwardCancel(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { 72 ActionMessages actionMessages = new ActionMessages(); 73 actionMessages.add(Globals.MESSAGE_KEY, new ActionMessage("org.mdarad.framework.global.forward.cancel.message")); 74 saveMessages(httpServletRequest, actionMessages); 75 return actionMapping.findForward(CANCEL_FORWARD_KEY); 76 } 77 78 protected ActionForward forwardSuccess(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { 79 ActionMessages actionMessages = new ActionMessages(); 80 actionMessages.add(Globals.MESSAGE_KEY, new ActionMessage("org.mdarad.framework.global.forward.success.message")); 81 saveMessages(httpServletRequest, actionMessages); 82 return actionMapping.findForward(SUCCESS_FORWARD_KEY); 83 } 84 85 protected ActionForward forwardDisplay(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { 86 return actionMapping.findForward(DISPLAY_FORWARD_KEY); 87 } 88 89 protected ActionForward forwardFailure(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { 90 ActionMessages actionMessages = new ActionMessages(); 91 actionMessages.add(Globals.ERROR_KEY, new ActionMessage("org.mdarad.framework.global.forward.failure.message")); 92 saveMessages(httpServletRequest, actionMessages); 93 return actionMapping.findForward(FAILURE_FORWARD_KEY); 94 } 95 96 protected ActionForward forwardDisplay(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String forward) { 97 return actionMapping.findForward(forward); 98 } 99 100 protected ActionForward forwardChildAggregation(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String childAggregationName, String childAggregationActionName) { 101 return actionMapping.findForward(getForwardAggregationChildName(childAggregationName, childAggregationActionName)); 102 } 103 104 protected String getForwardAggregationChildName(String childAggregationName, String childAggregationActionName) { 105 StringBuffer forwardNameStringBuffer = new StringBuffer (CHILD_AGGREGATION_FORWARD_PREFIX); 106 forwardNameStringBuffer.append(CHILD_AGGREGATION_FORWARD_SEPARATOR); 107 forwardNameStringBuffer.append(childAggregationName); 108 forwardNameStringBuffer.append(CHILD_AGGREGATION_FORWARD_SEPARATOR); 109 forwardNameStringBuffer.append(childAggregationActionName); 110 return forwardNameStringBuffer.toString(); 111 } 112 113 protected ActionForward forwardAggregationParent(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, String aggregationParentName, String parentChildAggregationName, String aggregationParentForwardName) { 114 return actionMapping.findForward(getForwardAggregationParentName(aggregationParentName, parentChildAggregationName, aggregationParentForwardName)); 115 } 116 117 protected String getForwardAggregationParentName(String aggregationParentName, String parentChildAggregationName, String aggregationParentForwardName) { 118 StringBuffer forwardNameStringBuffer = new StringBuffer (AGGREGATION_PARENT_FORWARD_PREFIX); 119 forwardNameStringBuffer.append(AGGREGATION_PARENT_FORWARD_SEPARATOR); 120 forwardNameStringBuffer.append(aggregationParentName); 121 forwardNameStringBuffer.append(AGGREGATION_PARENT_FORWARD_SEPARATOR); 122 forwardNameStringBuffer.append(parentChildAggregationName); 123 forwardNameStringBuffer.append(AGGREGATION_PARENT_FORWARD_SEPARATOR); 124 forwardNameStringBuffer.append(aggregationParentForwardName); 125 126 return forwardNameStringBuffer.toString(); 127 } 128 129 public void deleteContextObject(String contextStackKey, Entity entityBean, HttpServletRequest httpServletRequest) throws OrphanChildException, SystemException, ConcurrencyException { 130 ContextStack contextStack = getContextStack(contextStackKey, httpServletRequest); 131 132 if (contextStack == null) { 133 throw new OrphanChildException("The child is being saved out of context. The context stack cannot be null."); 134 } 135 136 try { 137 if(contextStack.size() > 1) { 138 ContextStackElement currentContextStackElement = (ContextStackElement) contextStack.peek(); 140 141 ContextStackElement parentContextStackElement = (ContextStackElement) contextStack.get(contextStack.size() - 2); 143 Entity parentObject = (Entity) parentContextStackElement.getEntityBeanInstance(); 144 Class parentClass = parentContextStackElement.getEntityBeanInstance().getClass(); 145 146 if(currentContextStackElement.isParentMultipleAggregation()) { 148 EntityPrimaryKey entityPrimaryKey = entityBean.getPrimaryKey(); 150 151 String getAggregationCollectionMethodName = "get" + StringUtils.capitalise(currentContextStackElement.getParentAggregationName()); 153 Method getAggregationCollectionMethod = parentClass.getMethod(getAggregationCollectionMethodName, null); 154 Collection aggregationCollectionMethod = (Collection ) getAggregationCollectionMethod.invoke(parentObject, null); 155 156 Iterator aggregationCollectionIterator = aggregationCollectionMethod.iterator(); 158 while(aggregationCollectionIterator.hasNext()) { 159 Entity childAggregationEntity = (Entity) aggregationCollectionIterator.next(); 160 EntityPrimaryKey childAggregationentityPrimaryKey = childAggregationEntity.getPrimaryKey(); 161 if(entityPrimaryKey.equals(childAggregationentityPrimaryKey)) { 162 aggregationCollectionMethod.remove(childAggregationEntity); 163 break; 164 } 165 } 166 } else { 167 String setAggregation = "set" + StringUtils.capitalise(currentContextStackElement.getParentAggregationName()); 169 Class [] parameterTypes = new Class [] {entityBean.getClass()}; 170 Method setAggregationMethod = parentClass.getMethod(setAggregation, parameterTypes); 171 Object [] parameters = new Object [1]; 172 setAggregationMethod.invoke(parentObject, parameters); 173 } 174 175 BusinessDelegate delegateInstance = currentContextStackElement.getDelegate(); 178 Class facadeClass = delegateInstance.getClass(); 179 180 String fullyQualifiedName = entityBean.getClass().getName(); 182 Class [] parameterTypes = new Class []{entityBean.getClass()}; 183 String className = fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf('.') + 1, fullyQualifiedName.length()); 184 Method saveMethod = facadeClass.getMethod("save" + className, parameterTypes); 185 Object [] parameters = new Object []{entityBean}; 186 saveMethod.invoke(delegateInstance, parameters); 187 188 } 189 } catch (NoSuchMethodException e) { 190 throw new ContextUpdateException("The aggregated objects could not be saved", e); 191 } catch (IllegalAccessException e) { 192 throw new ContextUpdateException("The aggregated objects could not be saved", e); 193 } catch (InvocationTargetException e) { 194 Throwable nestedException = ((InvocationTargetException )e).getTargetException(); 195 196 if(nestedException instanceof SystemException) { 197 throw (SystemException) nestedException; 198 } else { 199 throw new ContextUpdateException("The aggregated objects could not be saved", e); 200 } 201 } 202 203 saveContextObjects(contextStack); 204 205 } 206 207 216 public void saveContextObjectsByParent(String contextStackKey, Entity entityBean, HttpServletRequest httpServletRequest, boolean isNewInstance) throws OrphanChildException, SystemException, ConcurrencyException { 217 ContextStack contextStack = getContextStack(contextStackKey, httpServletRequest); 218 219 ContextStackElement contextStackElement = (ContextStackElement) contextStack.peek(); 221 contextStackElement.setNewInstance(isNewInstance); 222 contextStackElement.setEntityBeanInstance(entityBean); 223 224 if (contextStack == null) { 225 throw new OrphanChildException("The child is being saved out of context. The context stack cannot be null."); 226 } 227 228 saveContextObjectsByParent(contextStack); 229 230 } 231 232 239 public void saveContextObjectsByParent(ContextStack contextStack) throws SystemException, ConcurrencyException { 240 updateContextObjects(contextStack); 241 saveContextObjects(contextStack); 242 } 243 244 252 protected void saveContextObjects(ContextStack contextStack) throws SystemException, ConcurrencyException { 253 try { 254 ContextStackElement parentContextStackElement = (ContextStackElement) contextStack.get(0); 256 257 Entity parentInstance = parentContextStackElement.getEntityBeanInstance(); 258 259 BusinessDelegate parentDelegateInstance = parentContextStackElement.getDelegate(); 261 Class parentFacadeClass = parentDelegateInstance.getClass(); 262 263 String parentFullyQualifiedEntityName = parentContextStackElement.getParentFullyQualifiedEntityName(); 265 Class [] parameterTypes = new Class []{Class.forName(parentContextStackElement.getParentFullyQualifiedEntityName())}; 266 String parentClassName = parentFullyQualifiedEntityName.substring(parentFullyQualifiedEntityName.lastIndexOf('.') + 1, parentFullyQualifiedEntityName.length()); 267 Method saveParentMethod = parentFacadeClass.getMethod("save" + parentClassName, parameterTypes); 268 Object [] parameters = new Object []{parentInstance}; 269 saveParentMethod.invoke(parentDelegateInstance, parameters); 270 } catch (NoSuchMethodException e) { 271 throw new ContextUpdateException("The aggregated objects could not be saved", e); 272 } catch (IllegalAccessException e) { 273 throw new ContextUpdateException("The aggregated objects could not be saved", e); 274 } catch (InvocationTargetException e) { 275 Throwable nestedException = ((InvocationTargetException )e).getTargetException(); 276 if(nestedException instanceof SystemException) { 277 throw (SystemException) nestedException; 278 } else if(nestedException instanceof ConcurrencyException) { 279 throw (ConcurrencyException) nestedException; 280 } else { 281 throw new ContextUpdateException("The aggregated objects could not be saved", e); 282 } 283 } catch (ClassNotFoundException e) { 284 throw new ContextUpdateException("The aggregated objects could not be saved", e); 285 } 286 } 287 288 295 static public ContextStack getContextStack(String contextStackKey, HttpServletRequest httpServletRequest) { 296 String contextStackIdString = httpServletRequest.getParameter(contextStackKey); 299 if(contextStackIdString == null ) { 300 contextStackIdString = (String ) httpServletRequest.getAttribute(contextStackKey); 301 } 302 303 String contextStackId = (String ) ConvertUtils.convert(contextStackIdString, String .class); 304 return (ContextStack) httpServletRequest.getSession().getAttribute(contextStackId); 305 } 306 static public void setContextStack(String contextStackKey, ContextStack contextStack, HttpServletRequest httpServletRequest) { 307 String contextStackId = contextStack.getId(); 309 httpServletRequest.getSession().setAttribute(contextStackId, contextStack); 310 httpServletRequest.setAttribute(contextStackKey, contextStackId); 311 } 312 static public void nullifyContextStack(String contextStackKey, ContextStack contextStack, HttpServletRequest httpServletRequest) { 313 String contextStackId = contextStack.getId(); 315 httpServletRequest.getSession().removeAttribute(contextStackId); 316 httpServletRequest.removeAttribute(contextStackKey); 317 } 318 static public ContextStack createNewContextStack(String contextStackKey, HttpServletRequest httpServletRequest) { 319 ContextStack contextStack = null; 320 try { 321 contextStack = new ContextStack(); 322 String contextStackId = contextStack.getId(); 324 httpServletRequest.getSession().setAttribute(contextStackId, contextStack); 325 httpServletRequest.setAttribute(contextStackKey, contextStackId); 326 } catch (GUIDGenerationException e) { 327 e.printStackTrace(); } 329 return contextStack; 330 } 331 332 public Entity getCurrentEntityFromContextStack(String contextStackKey, HttpServletRequest httpServletRequest) { 333 ContextStack contextStack = getContextStack(contextStackKey, httpServletRequest); 334 Entity output = null; 335 if(contextStack != null && contextStack.size() > 0) { 336 ContextStackElement contextStackElement = (ContextStackElement) contextStack.get(contextStack.size() - 1); 337 if(contextStackElement != null) { 338 output = contextStackElement.getEntityBeanInstance(); 339 } 340 } 341 return output; 342 } 343 344 350 public void setContextStackIDInRequest(String contextStackKey, HttpServletRequest httpServletRequest) { 351 String contextStackId = (String ) httpServletRequest.getAttribute(contextStackKey); 353 354 if (contextStackId == null) { 355 String contextStackIdString = httpServletRequest.getParameter(contextStackKey); 356 contextStackId = (String ) ConvertUtils.convert(contextStackIdString, String .class); 357 if(contextStackId != null) { 359 httpServletRequest.setAttribute(contextStackKey, contextStackId); 360 } 361 } 362 } 363 364 protected void updateContextObjects(ContextStack contextStack) throws SystemException, ConcurrencyException { 365 try { 366 if(contextStack.size() > 1) { 367 for(int i = contextStack.size()-1; i > 0; i--) { 368 ContextStackElement currentContextStackElement = (ContextStackElement) contextStack.get(i); 370 boolean isNewInstance = currentContextStackElement.isNewInstance(); 371 Entity entityBean = currentContextStackElement.getEntityBeanInstance(); 372 373 ContextStackElement parentContextStackElement = (ContextStackElement) contextStack.get(i-1); 375 Entity parentObject = (Entity) parentContextStackElement.getEntityBeanInstance(); 376 Class parentClass = parentContextStackElement.getEntityBeanInstance().getClass(); 377 378 if(currentContextStackElement.isParentMultipleAggregation()) { 380 if(!isNewInstance) { 381 EntityPrimaryKey entityPrimaryKey = entityBean.getPrimaryKey(); 383 384 String getAggregationCollectionMethodName = "get" + StringUtils.capitalise(currentContextStackElement.getParentAggregationName()); 386 Method getAggregationCollectionMethod = parentClass.getMethod(getAggregationCollectionMethodName, null); 387 Collection aggregationCollectionMethod = (Collection ) getAggregationCollectionMethod.invoke(parentObject, null); 388 389 Iterator aggregationCollectionIterator = aggregationCollectionMethod.iterator(); 391 while(aggregationCollectionIterator.hasNext()) { 392 Entity childAggregationEntity = (Entity) aggregationCollectionIterator.next(); 393 EntityPrimaryKey childAggregationentityPrimaryKey = childAggregationEntity.getPrimaryKey(); 394 if(entityPrimaryKey.equals(childAggregationentityPrimaryKey)) { 395 aggregationCollectionMethod.remove(childAggregationEntity); 396 break; 397 } 398 } 399 } 400 401 String addAggregation = "add" + StringUtils.capitalise(currentContextStackElement.getParentAggregationName()); 402 Class [] parameterTypes = new Class [] {Object .class}; 403 Method addAggregationMethod = parentClass.getMethod(addAggregation, parameterTypes); 404 Object [] parameters = new Object [] {entityBean}; 405 addAggregationMethod.invoke(parentObject, parameters); 406 } else { 407 String setAggregation = "set" + StringUtils.capitalise(currentContextStackElement.getParentAggregationName()); 408 Class [] parameterTypes = new Class [] {entityBean.getClass()}; 409 Method setAggregationMethod = parentClass.getMethod(setAggregation, parameterTypes); 410 Object [] parameters = new Object [1]; 411 if(!isNewInstance) { 412 setAggregationMethod.invoke(parentObject, parameters); 414 } 415 416 417 parameters[0] = entityBean; 419 setAggregationMethod.invoke(parentObject, parameters); 420 } 421 } 422 } 423 } catch (NoSuchMethodException e) { 424 throw new ContextUpdateException("The aggregated objects could not be saved", e); 425 } catch (IllegalAccessException e) { 426 throw new ContextUpdateException("The aggregated objects could not be saved", e); 427 } catch (InvocationTargetException e) { 428 Throwable nestedException = ((InvocationTargetException )e).getTargetException(); 429 430 if(nestedException instanceof SystemException) { 431 throw (SystemException) nestedException; 432 } else if(nestedException instanceof ConcurrencyException) { 433 throw (ConcurrencyException) nestedException; 434 } else { 435 throw new ContextUpdateException("The aggregated objects could not be saved", e); 436 } 437 } 438 } 439 440 public String getFirstParameterNameFromPrefix(HttpServletRequest httpServletRequest, String prefix) { 441 String output = null; 442 443 Enumeration enumeration = httpServletRequest.getParameterNames(); 444 445 while(enumeration.hasMoreElements()) { 446 String parameterName = (String ) enumeration.nextElement(); 447 if(parameterName != null && parameterName.startsWith(prefix)) { 448 output = parameterName; 449 break; 450 } 451 } 452 453 return output; 454 } 455 456 462 protected String getAggregationParentName(ContextStack contextStack) { 463 if((contextStack != null && contextStack.size() > 1)) { 465 ContextStackElement parentContextStackElement = (ContextStackElement) contextStack.get(contextStack.size() - 2); 466 return parentContextStackElement.getParentFullyQualifiedEntityName().substring(parentContextStackElement.getParentFullyQualifiedEntityName().lastIndexOf('.') + 1); 467 } 468 return null; 469 } 470 471 477 protected String getParentChildAggregationName(ContextStack contextStack) { 478 if(contextStack != null && contextStack.size() > 1) { 480 ContextStackElement currentContextStackElement = (ContextStackElement) contextStack.peek(); 481 return currentContextStackElement.getParentAggregationName(); 482 } 483 return null; 484 } 485 486 498 protected ActionForward determineForwardAggregation(String childAggregationActionName, String childAggregationName, ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws SystemException { 499 ActionForward output = null; 500 if(FORM_CHILD_ACTION_SUFFIX_PARAMETER_KEY.equals(childAggregationActionName)) { 502 output = forwardChildAggregation(actionMapping, actionForm, httpServletRequest, httpServletResponse, childAggregationName, childAggregationActionName); 504 505 } else if(DELETE_CHILD_ACTION_SUFFIX_PARAMETER_KEY.equals(childAggregationActionName)) { 506 output = forwardChildAggregation(actionMapping, actionForm, httpServletRequest, httpServletResponse, childAggregationName, childAggregationActionName); 508 } 509 510 if(output == null) throw new org.mdarad.framework.exception.SystemException("No forward of that name could be found: " + getForwardAggregationChildName(childAggregationName, childAggregationActionName)); 512 return output; 513 } 514 515 526 protected void updateContextStack( ContextStack contextStack, Entity entityBean, 527 Class entityClass, BusinessDelegate businessDelegate, 528 boolean isChildMultipleAggregation, boolean isNewInstance, 529 String childAggregationName) 530 throws ServiceLocatorException { 531 532 ContextStackElement currentContextStackElement; 533 if(contextStack.size() > 0) { 534 currentContextStackElement = (ContextStackElement) contextStack.peek(); 535 } else { 536 currentContextStackElement = new ContextStackElement(); 537 contextStack.add(currentContextStackElement); 538 } 539 540 currentContextStackElement.setDelegate(businessDelegate); 542 currentContextStackElement.setParentFullyQualifiedEntityName(entityClass.getName()); 543 currentContextStackElement.setEntityBeanInstance(entityBean); 544 545 ContextStackElement childContextStackElement = new ContextStackElement(); 547 childContextStackElement.setParentMultipleAggregation(isChildMultipleAggregation); 548 childContextStackElement.setNewInstance(isNewInstance); 549 childContextStackElement.setParentAggregationName(childAggregationName); 550 contextStack.push(childContextStackElement); 551 } 552 } | Popular Tags |