001package org.andromda.cartridges.bpm4struts.metafacades; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Collections; 006import java.util.HashMap; 007import java.util.Iterator; 008import java.util.LinkedHashMap; 009import java.util.LinkedHashSet; 010import java.util.List; 011import java.util.Map; 012import org.andromda.cartridges.bpm4struts.Bpm4StrutsGlobals; 013import org.andromda.cartridges.bpm4struts.Bpm4StrutsProfile; 014import org.andromda.cartridges.bpm4struts.Bpm4StrutsUtils; 015import org.andromda.metafacades.uml.EventFacade; 016import org.andromda.metafacades.uml.FilteredCollection; 017import org.andromda.metafacades.uml.FrontEndEvent; 018import org.andromda.metafacades.uml.FrontEndExceptionHandler; 019import org.andromda.metafacades.uml.FrontEndFinalState; 020import org.andromda.metafacades.uml.FrontEndForward; 021import org.andromda.metafacades.uml.FrontEndParameter; 022import org.andromda.metafacades.uml.FrontEndUseCase; 023import org.andromda.metafacades.uml.ModelElementFacade; 024import org.andromda.metafacades.uml.ParameterFacade; 025import org.andromda.metafacades.uml.PseudostateFacade; 026import org.andromda.metafacades.uml.Role; 027import org.andromda.metafacades.uml.StateVertexFacade; 028import org.andromda.metafacades.uml.TransitionFacade; 029import org.andromda.metafacades.uml.UMLProfile; 030import org.andromda.metafacades.uml.UseCaseFacade; 031import org.andromda.utils.StringUtilsHelper; 032import org.apache.commons.collections.CollectionUtils; 033import org.apache.commons.collections.Predicate; 034import org.apache.commons.lang.ObjectUtils; 035import org.apache.commons.lang.StringUtils; 036 037/** 038 * MetafacadeLogic implementation. 039 * 040 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction 041 */ 042public class StrutsActionLogicImpl 043 extends StrutsActionLogic 044{ 045 private static final long serialVersionUID = 34L; 046 /** 047 * All action states that make up this action, this includes all possible action states traversed 048 * after a decision point too. 049 */ 050 private Collection<StrutsActionState> actionStates = null; 051 052 /** 053 * All transitions leading into either a page or final state that originated from a call to this action. 054 */ 055 private Map<StateVertexFacade, TransitionFacade> actionForwards = null; 056 057 /** 058 * All transitions leading into a decision point that originated from a call to this action. 059 */ 060 private Collection<TransitionFacade> decisionTransitions = null; 061 062 /** 063 * All transitions that can be traversed when calling this action. 064 */ 065 private Collection<TransitionFacade> transitions = null; 066 067 /** 068 * @param metaObject 069 * @param context 070 */ 071 public StrutsActionLogicImpl(Object metaObject, 072 String context) 073 { 074 super(metaObject, context); 075 } 076 077 /** 078 * Initializes all action states, action forwards, decision transitions and transitions in one shot, so that they 079 * can be queried more efficiently later on. 080 */ 081 private void initializeCollections() 082 { 083 actionStates = new LinkedHashSet<StrutsActionState>(); 084 actionForwards = new HashMap<StateVertexFacade, TransitionFacade>(); 085 decisionTransitions = new LinkedHashSet<TransitionFacade>(); 086 transitions = new LinkedHashSet<TransitionFacade>(); 087 collectTransitions(this, transitions); 088 } 089 090 /** 091 * Recursively collects all action states, action forwards, decision transitions and transitions. 092 * 093 * @param transition the current transition that is being processed 094 * @param processedTransitions the set of transitions already processed 095 */ 096 private void collectTransitions(TransitionFacade transition, 097 Collection<TransitionFacade> processedTransitions) 098 { 099 if (processedTransitions.contains(transition)) 100 { 101 return; 102 } 103 processedTransitions.add(transition); 104 105 final StateVertexFacade target = transition.getTarget(); 106 if ((target instanceof StrutsJsp) || (target instanceof StrutsFinalState)) 107 { 108 if (!actionForwards.containsKey(transition.getTarget())) 109 { 110 actionForwards.put(transition.getTarget(), transition); 111 } 112 } 113 else if ((target instanceof PseudostateFacade) && ((PseudostateFacade) target).isDecisionPoint()) 114 { 115 decisionTransitions.add(transition); 116 for (final TransitionFacade outcome : target.getOutgoings()) 117 { 118 collectTransitions(outcome, processedTransitions); 119 } 120 } 121 else if (target instanceof StrutsActionState) 122 { 123 actionStates.add((StrutsActionState)target); 124 final FrontEndForward forward = ((StrutsActionState) target).getForward(); 125 if (forward != null) 126 { 127 collectTransitions(forward, processedTransitions); 128 } 129 } 130 else // all the rest is ignored but outgoing transitions are further processed 131 { 132 for (final TransitionFacade outcome : target.getOutgoings()) 133 { 134 collectTransitions(outcome, processedTransitions); 135 } 136 } 137 } 138 139 /** 140 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionName() 141 */ 142 protected String handleGetActionName() 143 { 144 return getFormBeanName(); 145 } 146 147 /** 148 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionInput() 149 */ 150 protected String handleGetActionInput() 151 { 152 final StateVertexFacade source = getSource(); 153 return (source instanceof StrutsJsp) ? ((StrutsJsp) source).getFullPath() : ""; 154 } 155 156 /** 157 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsMultipartFormData() 158 */ 159 protected boolean handleIsMultipartFormData() 160 { 161 boolean multipartFormPost = false; 162 163 for (StrutsParameter field : this.getActionFormFields()) 164 { 165 if (field.isFile()) 166 { 167 multipartFormPost = true; 168 break; 169 } 170 } 171 172 return multipartFormPost; 173 } 174 175 /** 176 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsFormPost() 177 */ 178 protected boolean handleIsFormPost() 179 { 180 final Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE); 181 return value == null || Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_FORM.equals(value); 182 } 183 184 /** 185 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsHyperlink() 186 */ 187 protected boolean handleIsHyperlink() 188 { 189 final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE); 190 return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_HYPERLINK 191 .equalsIgnoreCase(value == null ? null : value.toString()); 192 } 193 194 /** 195 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsImageLink() 196 */ 197 protected boolean handleIsImageLink() 198 { 199 final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE); 200 return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_IMAGE 201 .equalsIgnoreCase(value == null ? null : value.toString()); 202 } 203 204 /** 205 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsTableAction() 206 */ 207 protected boolean handleIsTableAction() 208 { 209 return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE_TABLE 210 .equals(this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TYPE)); 211 } 212 213 /** 214 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsTableRowAction() 215 */ 216 protected boolean handleIsTableRowAction() 217 { 218 return this.isTableLink() && !this.isTableAction(); 219 } 220 221 /** 222 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsTableLink() 223 */ 224 protected boolean handleIsTableLink() 225 { 226 return this.getTableLinkParameter() != null; 227 } 228 229 /** 230 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableLinkParameter() 231 */ 232 protected Object handleGetTableLinkParameter() 233 { 234 StrutsParameter tableLinkParameter = null; 235 236 final String tableLinkName = getTableLinkName(); 237 if (tableLinkName != null) 238 { 239 final StrutsJsp page = this.getInput(); 240 if (page != null) 241 { 242 for (FrontEndParameter table : page.getTables()) 243 { 244 if (tableLinkName.equals(table.getName())) 245 { 246 tableLinkParameter = (StrutsParameter)table; 247 } 248 } 249 } 250 } 251 252 return tableLinkParameter; 253 } 254 255 /** 256 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableNonColumnFormParameters() 257 */ 258 protected List<StrutsParameter> handleGetTableNonColumnFormParameters() 259 { 260 List<StrutsParameter> tableNonColumnActionParameters = null; 261 262 final StrutsParameter table = getTableLinkParameter(); 263 if (table != null) 264 { 265 final Map<String, StrutsParameter> tableNonColumnActionParametersMap = new LinkedHashMap<String, StrutsParameter>(4); 266 final Collection<String> columnNames = table.getTableColumnNames(); 267 final List<StrutsAction> formActions = table.getTableFormActions(); 268 int formSize = formActions.size(); 269 for (int i = 0; i < formSize; i++) 270 { 271 final StrutsAction action = formActions.get(i); 272 int size = action.getActionParameters().size(); 273 for (int j = 0; j < size; j++) 274 { 275 final StrutsParameter parameter = action.getActionParameters().get(j); 276 if (!columnNames.contains(parameter.getName())) 277 { 278 tableNonColumnActionParametersMap.put(parameter.getName(), parameter); 279 } 280 } 281 } 282 283 tableNonColumnActionParameters = new ArrayList<StrutsParameter>(tableNonColumnActionParametersMap.values()); 284 } 285 286 return tableNonColumnActionParameters; 287 } 288 289 /** 290 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableLinkName() 291 */ 292 protected String handleGetTableLinkName() 293 { 294 String tableLink = null; 295 296 final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TABLELINK); 297 if (value != null) 298 { 299 tableLink = StringUtils.trimToNull(value.toString()); 300 301 if (tableLink != null) 302 { 303 final int columnOffset = tableLink.indexOf('.'); 304 tableLink = (columnOffset == -1) ? tableLink : tableLink.substring(0, columnOffset); 305 } 306 } 307 308 return tableLink; 309 } 310 311 /** 312 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetTableLinkColumnName() 313 */ 314 protected String handleGetTableLinkColumnName() 315 { 316 String tableLink = null; 317 318 final Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_TABLELINK); 319 if (value != null) 320 { 321 tableLink = StringUtils.trimToNull(value.toString()); 322 323 if (tableLink != null) 324 { 325 final int columnOffset = tableLink.indexOf('.'); 326 tableLink = (columnOffset == -1 || columnOffset == tableLink.length() - 1) 327 ? null 328 : tableLink.substring(columnOffset + 1); 329 } 330 } 331 332 return tableLink; 333 } 334 335 /** 336 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetImagePath() 337 */ 338 protected String handleGetImagePath() 339 { 340 return getPackagePath() + '/' + Bpm4StrutsUtils.toWebFileName(getActionClassName()) + ".gif"; 341 } 342 343 /** 344 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionPath() 345 */ 346 protected String handleGetActionPath() 347 { 348 return getActionPathRoot() + '/' + getActionClassName(); 349 } 350 351 /** 352 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionPathRoot() 353 */ 354 protected String handleGetActionPathRoot() 355 { 356 String actionPathRoot = null; 357 358 final FrontEndUseCase useCase = this.getUseCase(); 359 if (useCase != null) 360 { 361 final StringBuilder buffer = new StringBuilder(); 362 363 final String actionPathPrefix = Bpm4StrutsGlobals.PROPERTY_ACTION_PATH_PREFIX; 364 String prefix = this.isConfiguredProperty(actionPathPrefix) ? ObjectUtils 365 .toString(this.getConfiguredProperty(actionPathPrefix)) : ""; 366 367 final ModelElementFacade useCasePackage = useCase.getPackage(); 368 if (useCasePackage != null) 369 { 370 prefix = prefix.replaceAll("\\{0\\}", useCasePackage.getPackagePath()); 371 } 372 373 buffer.append(prefix); 374 buffer.append('/'); 375 buffer.append(StringUtilsHelper.upperCamelCaseName(useCase.getName())); 376 377 actionPathRoot = buffer.toString(); 378 } 379 return actionPathRoot; 380 } 381 382 /** 383 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionScope() 384 */ 385 protected String handleGetActionScope() 386 { 387 return "request"; 388 } 389 390 /** 391 * @return getRoleUsers() 392 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getActionRoles() 393 */ 394 protected String handleGetActionRoles() 395 { 396 final Collection users = getRoleUsers(); 397 final StringBuilder roles = new StringBuilder(); 398 for (final Iterator userIterator = users.iterator(); userIterator.hasNext();) 399 { 400 roles.append(((ModelElementFacade) userIterator.next()).getName()); 401 if (userIterator.hasNext()) 402 { 403 roles.append(','); 404 } 405 } 406 return roles.toString(); 407 } 408 409 /** 410 * Returns a collection containing StrutsUser instances representing the roles 411 * authorized to call this action. If this action starts the use-case that use-case's users 412 * are returned, otherwise it will return the users associated to the use-cases targeted by this 413 * action (which may be none at all) 414 */ 415 private Collection<Role> getRoleUsers() 416 { 417 final Collection<Role> roleUsers = new ArrayList<Role>(); 418 419 if (this.isUseCaseStart()) 420 { 421 final FrontEndUseCase useCase = getUseCase(); 422 if (useCase != null) 423 { 424 roleUsers.addAll(useCase.getRoles()); 425 } 426 } 427 else 428 { 429 for (final StrutsForward forward : getActionForwards()) 430 { 431 if (forward.getTarget() instanceof StrutsFinalState) 432 { 433 final FrontEndUseCase useCase = ((StrutsFinalState) forward.getTarget()).getTargetUseCase(); 434 if (useCase != null) 435 { 436 roleUsers.addAll(useCase.getRoles()); 437 } 438 } 439 } 440 } 441 442 return roleUsers; 443 } 444 445 /** 446 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionClassName() 447 */ 448 protected String handleGetActionClassName() 449 { 450 String name = null; 451 452 if (this.isExitingInitialState()) 453 { 454 final UseCaseFacade useCase = this.getUseCase(); 455 if (useCase != null) 456 { 457 name = useCase.getName(); 458 } 459 } 460 else 461 { 462 final EventFacade trigger = getTrigger(); 463 final String suffix = (trigger == null) ? getTarget().getName() : trigger.getName(); 464 name = getSource().getName() + ' ' + suffix; 465 } 466 return StringUtilsHelper.upperCamelCaseName(name); 467 } 468 469 /** 470 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionType() 471 */ 472 protected String handleGetActionType() 473 { 474 return getPackageName() + '.' + getActionClassName(); 475 } 476 477 /** 478 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanClassName() 479 */ 480 protected String handleGetFormBeanClassName() 481 { 482 return getActionClassName() + Bpm4StrutsGlobals.FORM_IMPLEMENTATION_SUFFIX; 483 } 484 485 /** 486 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanName() 487 */ 488 protected String handleGetFormBeanName() 489 { 490 String formBeanName = null; 491 492 final UseCaseFacade useCase = this.getUseCase(); 493 if (useCase != null) 494 { 495 final String useCaseName = useCase.getName(); 496 formBeanName = StringUtilsHelper.lowerCamelCaseName(useCaseName) + getActionClassName() + Bpm4StrutsGlobals 497 .FORM_SUFFIX; 498 } 499 return formBeanName; 500 } 501 502 /** 503 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormValidationMethodName() 504 */ 505 protected String handleGetFormValidationMethodName() 506 { 507 return "validate" + this.getActionClassName() + Bpm4StrutsGlobals.FORM_SUFFIX; 508 } 509 510 /** 511 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetMessageKey() 512 */ 513 protected String handleGetMessageKey() 514 { 515 String messageKey = null; 516 517 final StrutsTrigger actionTrigger = getActionTrigger(); 518 if (actionTrigger != null) 519 { 520 messageKey = actionTrigger.getTriggerKey(); 521 } 522 523 return messageKey; 524 } 525 526 /** 527 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetImageMessageKey() 528 */ 529 protected String handleGetImageMessageKey() 530 { 531 return getMessageKey() + ".image"; 532 } 533 534 /** 535 * Overrides the method defined in the facade parent of StrutsAction, this is done because actions (transitions) are 536 * not directly contained in a UML namespace. 537 * @return useCase.getPackageName() 538 */ 539 public String getPackageName() 540 { 541 String packageName = null; 542 543 final UseCaseFacade useCase = this.getUseCase(); 544 if (useCase != null) 545 { 546 packageName = useCase.getPackageName(); 547 } 548 return packageName; 549 } 550 551 /** 552 * @return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_RESETTABLE 553 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isResettable() 554 */ 555 protected boolean handleIsResettable() 556 { 557 Object value = findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_RESETTABLE); 558 return isTrue(value == null ? null : value.toString()); 559 } 560 561 /** 562 * Convenient method to detect whether or not a String instance represents a boolean <code>true</code> value. 563 */ 564 private boolean isTrue(String string) 565 { 566 return "yes".equalsIgnoreCase(string) || 567 "true".equalsIgnoreCase(string) || 568 "on".equalsIgnoreCase(string) || 569 "1".equalsIgnoreCase(string); 570 } 571 572 /** 573 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsUseCaseStart() 574 */ 575 protected boolean handleIsUseCaseStart() 576 { 577 StateVertexFacade source = getSource(); 578 return source instanceof PseudostateFacade && ((PseudostateFacade) source).isInitialState(); 579 } 580 581 /** 582 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFullActionPath() 583 */ 584 protected String handleGetFullActionPath() 585 { 586 return getPackagePath() + '/' + getActionClassName(); 587 } 588 589 /** 590 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFullTilePath() 591 */ 592 protected String handleGetFullTilePath() 593 { 594 return isUseCaseStart() 595 ? "empty-file" 596 : getPackagePath() + '/' + Bpm4StrutsUtils.toWebFileName(getActionClassName()); 597 } 598 599 /** 600 * We override this method here to make sure the actions end-up in the same package as their use-case. A transition 601 * (this class' parent type) does not have a real package as we need it here. 602 * @return this.getUseCase() / useCase.getPackagePath() 603 */ 604 public String getPackagePath() 605 { 606 String packagePath = null; 607 608 final UseCaseFacade useCase = this.getUseCase(); 609 if (useCase != null) 610 { 611 packagePath = '/' + useCase.getPackagePath(); 612 } 613 return packagePath; 614 } 615 616 /** 617 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFullFormBeanPath() 618 */ 619 protected String handleGetFullFormBeanPath() 620 { 621 return '/' + (getPackageName() + '/' + getFormBeanClassName()).replace('.', '/'); 622 } 623 624 /** 625 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsValidationRequired() 626 */ 627 protected boolean handleIsValidationRequired() 628 { 629 for (final StrutsParameter parameter : getActionParameters()) 630 { 631 if (parameter.isValidationRequired()) 632 { 633 return true; 634 } 635 } 636 return false; 637 } 638 639 /** 640 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsDateFieldPresent() 641 */ 642 protected boolean handleIsDateFieldPresent() 643 { 644 for (final StrutsParameter parameter : getActionParameters()) 645 { 646 if (parameter.isDate()) 647 { 648 return true; 649 } 650 } 651 return false; 652 } 653 654 /** 655 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleIsCalendarRequired() 656 */ 657 protected boolean handleIsCalendarRequired() 658 { 659 for (final StrutsParameter parameter : getActionParameters()) 660 { 661 if (parameter.isCalendarRequired()) 662 { 663 return true; 664 } 665 } 666 return false; 667 } 668 669 /** 670 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanPackageName() 671 */ 672 protected String handleGetFormBeanPackageName() 673 { 674 return getPackageName(); 675 } 676 677 /** 678 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetFormBeanType() 679 */ 680 protected String handleGetFormBeanType() 681 { 682 return getFormBeanPackageName() + '.' + getFormBeanClassName(); 683 } 684 685 /** 686 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDocumentationKey() 687 */ 688 protected String handleGetDocumentationKey() 689 { 690 final StrutsTrigger trigger = getActionTrigger(); 691 return ((trigger == null) ? getMessageKey() + ".is.an.action.without.trigger" : trigger.getTriggerKey()) + 692 ".documentation"; 693 } 694 695 /** 696 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDocumentationValue() 697 */ 698 protected String handleGetDocumentationValue() 699 { 700 final String value = StringUtilsHelper.toResourceMessage(getDocumentation("", 64, false)); 701 return (value == null) ? "" : value; 702 } 703 704 /** 705 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetOnlineHelpKey() 706 */ 707 protected String handleGetOnlineHelpKey() 708 { 709 final StrutsTrigger trigger = getActionTrigger(); 710 return ((trigger == null) ? getMessageKey() + ".is.an.action.without.trigger" : trigger.getTriggerKey()) + 711 ".online.help"; 712 } 713 714 /** 715 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetOnlineHelpValue() 716 */ 717 protected String handleGetOnlineHelpValue() 718 { 719 final String crlf = "<br/>"; 720 final StringBuilder buffer = new StringBuilder(); 721 722 final String value = StringUtilsHelper.toResourceMessage(getDocumentation("", 64, false)); 723 buffer.append((value == null) ? "No action documentation has been specified" : value); 724 buffer.append(crlf); 725 726 return StringUtilsHelper.toResourceMessage(buffer.toString()); 727 } 728 729 /** 730 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionForwards() 731 */ 732 protected List<TransitionFacade> handleGetActionForwards() 733 { 734 if (actionForwards == null) initializeCollections(); 735 return new ArrayList<TransitionFacade>(actionForwards.values()); 736 } 737 738 /** 739 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDecisionTransitions() 740 */ 741 protected List<TransitionFacade> handleGetDecisionTransitions() 742 { 743 if (decisionTransitions == null) initializeCollections(); 744 return new ArrayList<TransitionFacade>(decisionTransitions); 745 } 746 747 /** 748 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionStates() 749 */ 750 protected List<StrutsActionState> handleGetActionStates() 751 { 752 if (actionStates == null) initializeCollections(); 753 return new ArrayList<StrutsActionState>(actionStates); 754 } 755 756 /** 757 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionExceptions() 758 */ 759 protected List<FrontEndExceptionHandler> handleGetActionExceptions() 760 { 761 final Collection<FrontEndExceptionHandler> exceptions = new LinkedHashSet<FrontEndExceptionHandler>(); 762 final Collection<StrutsActionState> actionStates = getActionStates(); 763 for (final Iterator<StrutsActionState> iterator = actionStates.iterator(); iterator.hasNext();) 764 { 765 StrutsActionState actionState = iterator.next(); 766 exceptions.addAll(actionState.getExceptions()); 767 } 768 769 return new ArrayList<FrontEndExceptionHandler>(exceptions); 770 } 771 772 /** 773 * @return PseudostateFacade or STEREOTYPE_FRONT_END_VIEW 774 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getInput() 775 */ 776 protected Object handleGetInput() 777 { 778 Object input = null; 779 final ModelElementFacade source = getSource(); 780 if (source instanceof PseudostateFacade) 781 { 782 final PseudostateFacade pseudostate = (PseudostateFacade) source; 783 if (pseudostate.isInitialState()) 784 { 785 input = source; 786 } 787 } 788 else 789 { 790 if (source.hasStereotype(UMLProfile.STEREOTYPE_FRONT_END_VIEW)) 791 { 792 input = source; 793 } 794 } 795 return input; 796 } 797 798 /** 799 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetController() 800 */ 801 protected Object handleGetController() 802 { 803 final StrutsActivityGraph graph = this.getStrutsActivityGraph(); 804 return graph == null ? null : graph.getController(); 805 } 806 807 /** 808 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionTrigger() 809 */ 810 protected Object handleGetActionTrigger() 811 { 812 return this.getTrigger(); 813 } 814 815 /** 816 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionFormFields() 817 */ 818 protected List<FrontEndParameter> handleGetActionFormFields() 819 { 820 final Map<String, FrontEndParameter> formFieldMap = new HashMap<String, FrontEndParameter>(); 821 822 /** 823 * for useCaseStart actions we need to detect all usecases forwarding to the one belonging to this action 824 * if there are any parameters in those requests we need to have them included in this action's form 825 */ 826 if (this.isUseCaseStart()) 827 { 828 final FrontEndUseCase useCase = this.getUseCase(); 829 if (useCase != null) 830 { 831 final Collection<FrontEndFinalState> finalStates = useCase.getReferencingFinalStates(); 832 for (final Iterator<FrontEndFinalState> finalStateIterator = finalStates.iterator(); finalStateIterator.hasNext();) 833 { 834 final Object finalStateObject = finalStateIterator.next(); 835 // we need to test for the type because a non struts-use-case final state might accidentally 836 // be linking to this use-case (for example: the user temporarily wants to disable code generation 837 // for a specific use-case and is not removing the final-state to use-case link(s)) 838 if (finalStateObject instanceof StrutsFinalState) 839 { 840 final StrutsFinalState finalState = (StrutsFinalState) finalStateObject; 841 for (final FrontEndParameter parameter : finalState.getInterUseCaseParameters()) 842 { 843 formFieldMap.put(parameter.getName(), parameter); 844 } 845 } 846 } 847 } 848 } 849 850 // if any action encountered by the execution of the complete action-graph path emits a forward 851 // containing one or more parameters they need to be included as a form field too 852 for (final StrutsActionState actionState : getActionStates()) 853 { 854 final StrutsForward forward = (StrutsForward) actionState.getForward(); 855 if (forward != null) 856 { 857 for (final FrontEndParameter forwardParameter : forward.getForwardParameters()) 858 { 859 formFieldMap.put(forwardParameter.getName(), forwardParameter); 860 } 861 } 862 } 863 864 // add page variables for all pages/final-states targeted 865 // also add the fields of the target page's actions (for preloading) 866 for (final StrutsForward forward : getActionForwards()) 867 { 868 final StateVertexFacade target = forward.getTarget(); 869 if (target instanceof StrutsJsp) 870 { 871 final StrutsJsp jsp = (StrutsJsp) target; 872 for (final StrutsParameter facade : jsp.getPageVariables()) 873 { 874 formFieldMap.put(facade.getName(), facade); 875 } 876 for (final FrontEndParameter facade : jsp.getAllActionParameters()) 877 { 878 formFieldMap.put(facade.getName(), facade); 879 } 880 } 881 else if (target instanceof StrutsFinalState) 882 { 883 // only add these if there is no parameter recorded yet with the same name 884 for (final FrontEndParameter facade : forward.getForwardParameters()) 885 { 886 if (!formFieldMap.containsKey(facade.getName())) 887 { 888 formFieldMap.put(facade.getName(), facade); 889 } 890 } 891 } 892 } 893 894 // we do the action parameters in the end because they are allowed to overwrite existing properties 895 for (final StrutsParameter facade : getActionParameters()) 896 { 897 formFieldMap.put(facade.getName(), facade); 898 } 899 900 return new ArrayList<FrontEndParameter>(formFieldMap.values()); 901 } 902 903 /** 904 * FrontEndControllerOperation does not extend OperationFacade 905 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetDeferredOperations() 906 */ 907 protected List handleGetDeferredOperations() 908 { 909 final Collection deferredOperations = new LinkedHashSet(); 910 911 final StrutsController controller = getController(); 912 if (controller != null) 913 { 914 final List<StrutsActionState> actionStates = getActionStates(); 915 int size = actionStates.size(); 916 for (int i = 0; i < size; i++) 917 { 918 final StrutsActionState actionState = actionStates.get(i); 919 deferredOperations.addAll(actionState.getControllerCalls()); 920 } 921 922 for (StrutsForward forward : this.getDecisionTransitions()) 923 { 924 final FrontEndEvent trigger = forward.getDecisionTrigger(); 925 if (trigger != null) 926 { 927 deferredOperations.add(trigger.getControllerCall()); 928 } 929 } 930 } 931 return new ArrayList(deferredOperations); 932 } 933 934 /** 935 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetActionParameters() 936 */ 937 protected List<ParameterFacade> handleGetActionParameters() 938 { 939 final StrutsTrigger trigger = getActionTrigger(); 940 return (trigger == null) ? Collections.emptyList() : new ArrayList(trigger.getParameters()); 941 } 942 943 /** 944 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetInterUseCaseParameters(org.andromda.cartridges.bpm4struts.metafacades.StrutsFinalState) 945 */ 946 protected List<FrontEndParameter> handleGetInterUseCaseParameters(StrutsFinalState finalState) 947 { 948 List<FrontEndParameter> parameters; 949 950 if (finalState == null) 951 { 952 parameters = Collections.emptyList(); 953 } 954 else 955 { 956 // we don't want to list parameters with the same name to we use a hash map 957 final Map<String, FrontEndParameter> parameterMap = new HashMap<String, FrontEndParameter>(); 958 959 for (final StrutsForward forward : this.getActionForwards()) 960 { 961 // only return those parameters that belong to both this action and the argument final state 962 if (finalState.equals(forward.getTarget())) 963 { 964 for (FrontEndParameter parameter : forward.getForwardParameters()) 965 { 966 parameterMap.put(parameter.getName(), parameter); 967 } 968 } 969 } 970 parameters = new ArrayList<FrontEndParameter>(parameterMap.values()); 971 } 972 973 return parameters; 974 } 975 976 /** 977 * @return getActionForwards().getTarget() 978 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getTargetPages() 979 */ 980 protected List<StateVertexFacade> handleGetTargetPages() 981 { 982 Collection<StateVertexFacade> targetPages = new LinkedHashSet<StateVertexFacade>(); 983 984 for (final StrutsForward forward : getActionForwards()) 985 { 986 if (forward.isEnteringPage()) 987 { 988 targetPages.add(forward.getTarget()); 989 } 990 } 991 992 return new ArrayList<StateVertexFacade>(targetPages); 993 } 994 995 /** 996 * @return new ArrayList(transitions) 997 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#getTransitions() 998 */ 999 protected List<TransitionFacade> handleGetTransitions() 1000 { 1001 if (transitions == null) 1002 { 1003 initializeCollections(); 1004 } 1005 return new ArrayList<TransitionFacade>(transitions); 1006 } 1007 1008 /** 1009 * @return getActionTrigger().getName() lowerCamelCaseName 1010 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getStyleId() 1011 */ 1012 protected String handleGetStyleId() 1013 { 1014 String styleId = null; 1015 1016 StrutsTrigger trigger = getActionTrigger(); 1017 if (trigger != null) 1018 { 1019 String triggerName = trigger.getName(); 1020 styleId = StringUtilsHelper.lowerCamelCaseName(triggerName); 1021 } 1022 return styleId; 1023 } 1024 1025 /** 1026 * @return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_REDIRECT 1027 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isRedirect() 1028 */ 1029 protected boolean handleIsRedirect() 1030 { 1031 String redirect = (String) this.getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_DEFAULT_ACTION_REDIRECT); 1032 Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_REDIRECT); 1033 if (value != null) 1034 { 1035 redirect = (String) value; 1036 } 1037 return Boolean.valueOf(StringUtils.trimToEmpty(redirect)); 1038 } 1039 1040 /** 1041 * @return getActionParameters().isShouldReset() 1042 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getResettableActionParameters() 1043 */ 1044 protected List<StrutsParameter> handleGetResettableActionParameters() 1045 { 1046 return new ArrayList<StrutsParameter>(new FilteredCollection(this.getActionParameters()) 1047 { 1048 private static final long serialVersionUID = 34L; 1049 public boolean evaluate(Object object) 1050 { 1051 return object != null && ((StrutsParameter)object).isShouldReset(); 1052 } 1053 }); 1054 } 1055 1056 /** 1057 * The "session" action form scope. 1058 */ 1059 private static final String FORM_SCOPE_SESSION = "session"; 1060 1061 /** 1062 * The "request" action form scope. 1063 */ 1064 private static final String FORM_SCOPE_REQUEST = "request"; 1065 1066 /** 1067 * The "none" action form scope. 1068 */ 1069 private static final String FORM_SCOPE_NONE = "none"; 1070 1071 /** 1072 * @return Bpm4StrutsProfile.TAGGEDVALUE_ACTION_FORM_SCOPE 1073 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#getFormScope() 1074 */ 1075 protected String handleGetFormScope() 1076 { 1077 String actionFormScope = String 1078 .valueOf(this.getConfiguredProperty(Bpm4StrutsGlobals.PROPERTY_ACTION_FORM_SCOPE)); 1079 Object value = this.findTaggedValue(Bpm4StrutsProfile.TAGGEDVALUE_ACTION_FORM_SCOPE); 1080 if (value != null) 1081 { 1082 actionFormScope = String.valueOf(value); 1083 } 1084 return StringUtils.trimToEmpty(actionFormScope); 1085 } 1086 1087 /** 1088 * @return getFormScope().equalsIgnoreCase(FORM_SCOPE_SESSION) 1089 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isFormScopeSession() 1090 */ 1091 protected boolean handleIsFormScopeSession() 1092 { 1093 return FORM_SCOPE_SESSION.equalsIgnoreCase(this.getFormScope()); 1094 } 1095 1096 /** 1097 * @return getFormScope().equalsIgnoreCase(FORM_SCOPE_REQUEST) 1098 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isFormScopeRequest() 1099 */ 1100 protected boolean handleIsFormScopeRequest() 1101 { 1102 return FORM_SCOPE_REQUEST.equalsIgnoreCase(this.getFormScope()); 1103 } 1104 1105 /** 1106 * @return getFormScope().equalsIgnoreCase(FORM_SCOPE_NONE) 1107 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsAction#isFormScopeNone() 1108 */ 1109 protected boolean handleIsFormScopeNone() 1110 { 1111 return this.getFormScope().equalsIgnoreCase(FORM_SCOPE_NONE); 1112 } 1113 1114 /** 1115 * @see org.andromda.cartridges.bpm4struts.metafacades.StrutsActionLogic#handleGetHiddenActionParameters() 1116 */ 1117 protected List<StrutsParameter> handleGetHiddenActionParameters() 1118 { 1119 final List<StrutsParameter> hiddenActionParameters = new ArrayList<StrutsParameter>(this.getActionParameters()); 1120 CollectionUtils.filter(hiddenActionParameters, new Predicate() 1121 { 1122 public boolean evaluate(final Object object) 1123 { 1124 return StrutsParameterLogicImpl.HIDDEN_INPUT_TYPE.equals(((StrutsParameter) object).getWidgetType()); 1125 } 1126 }); 1127 return hiddenActionParameters; 1128 } 1129}