001package org.andromda.cartridges.jsf.metafacades; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.HashMap; 006import java.util.HashSet; 007import java.util.Iterator; 008import java.util.LinkedHashMap; 009import java.util.LinkedHashSet; 010import java.util.List; 011import java.util.Map; 012import java.util.Set; 013import org.andromda.cartridges.jsf.JSFGlobals; 014import org.andromda.cartridges.jsf.JSFProfile; 015import org.andromda.cartridges.jsf.JSFUtils; 016import org.andromda.metafacades.uml.AssociationEndFacade; 017import org.andromda.metafacades.uml.AttributeFacade; 018import org.andromda.metafacades.uml.ClassifierFacade; 019import org.andromda.metafacades.uml.EventFacade; 020import org.andromda.metafacades.uml.FrontEndAction; 021import org.andromda.metafacades.uml.FrontEndActivityGraph; 022import org.andromda.metafacades.uml.FrontEndForward; 023import org.andromda.metafacades.uml.FrontEndParameter; 024import org.andromda.metafacades.uml.FrontEndView; 025import org.andromda.metafacades.uml.ModelElementFacade; 026import org.andromda.metafacades.uml.TransitionFacade; 027import org.andromda.metafacades.uml.UseCaseFacade; 028import org.andromda.utils.StringUtilsHelper; 029import org.apache.commons.lang.ObjectUtils; 030import org.apache.commons.lang.StringUtils; 031 032/** 033 * MetafacadeLogic implementation for org.andromda.cartridges.jsf.metafacades.JSFParameter. 034 * 035 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter 036 */ 037public class JSFParameterLogicImpl 038 extends JSFParameterLogic 039{ 040 private static final long serialVersionUID = 34L; 041 /** 042 * @param metaObject 043 * @param context 044 */ 045 public JSFParameterLogicImpl( 046 Object metaObject, 047 String context) 048 { 049 super(metaObject, context); 050 } 051 052 /** 053 * Overridden to make sure it's not an inputTable. 054 * 055 * @see org.andromda.metafacades.uml.FrontEndParameter#isTable() 056 */ 057 public boolean isTable() 058 { 059 return (super.isTable() || this.isPageableTable()) && !this.isSelectable() 060 && !this.isInputTable() && !this.isInputHidden(); 061 } 062 063 /** 064 * @return isPageableTable 065 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isPageableTable() 066 */ 067 protected boolean handleIsPageableTable() 068 { 069 final Object value = this.findTaggedValue(JSFProfile.TAGGEDVALUE_TABLE_PAGEABLE); 070 return Boolean.valueOf(ObjectUtils.toString(value)).booleanValue(); 071 } 072 073 /** 074 * @return messageKey 075 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMessageKey() 076 */ 077 protected String handleGetMessageKey() 078 { 079 final StringBuilder messageKey = new StringBuilder(); 080 081 if (!this.isNormalizeMessages()) 082 { 083 if (this.isActionParameter()) 084 { 085 final JSFAction action = (JSFAction)this.getAction(); 086 if (action != null) 087 { 088 messageKey.append(action.getMessageKey()); 089 messageKey.append('.'); 090 } 091 } 092 else 093 { 094 final JSFView view = (JSFView)this.getView(); 095 if (view != null) 096 { 097 messageKey.append(view.getMessageKey()); 098 messageKey.append('.'); 099 } 100 } 101 messageKey.append("param."); 102 } 103 104 messageKey.append(StringUtilsHelper.toResourceMessageKey(super.getName())); 105 return messageKey.toString(); 106 } 107 108 /** 109 * @return getMessageKey() + '.' + JSFGlobals.DOCUMENTATION_MESSAGE_KEY_SUFFIX 110 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDocumentationKey() 111 */ 112 protected String handleGetDocumentationKey() 113 { 114 return getMessageKey() + '.' + JSFGlobals.DOCUMENTATION_MESSAGE_KEY_SUFFIX; 115 } 116 117 /** 118 * @return documentationValue 119 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDocumentationValue() 120 */ 121 protected String handleGetDocumentationValue() 122 { 123 final String value = StringUtilsHelper.toResourceMessage(this.getDocumentation( 124 "", 125 64, 126 false)); 127 return value == null ? "" : value; 128 } 129 130 /** 131 * Indicates whether or not we should normalize messages. 132 * 133 * @return true/false 134 */ 135 private boolean isNormalizeMessages() 136 { 137 final String normalizeMessages = (String)getConfiguredProperty(JSFGlobals.NORMALIZE_MESSAGES); 138 return Boolean.valueOf(normalizeMessages).booleanValue(); 139 } 140 141 /** 142 * @return messageValue 143 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMessageValue() 144 */ 145 protected String handleGetMessageValue() 146 { 147 return StringUtilsHelper.toPhrase(super.getName()); // the actual name is used for displaying 148 } 149 150 /** 151 * @param columnName 152 * @return tableColumnMessageKey 153 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableColumnMessageKey(String) 154 */ 155 protected String handleGetTableColumnMessageKey(final String columnName) 156 { 157 StringBuilder messageKey = new StringBuilder(); 158 if (!this.isNormalizeMessages()) 159 { 160 final JSFView view = (JSFView)this.getView(); 161 if (view != null) 162 { 163 messageKey.append(this.getMessageKey()); 164 messageKey.append('.'); 165 } 166 } 167 messageKey.append(StringUtilsHelper.toResourceMessageKey(columnName)); 168 return messageKey.toString(); 169 } 170 171 /** 172 * @param columnName 173 * @return StringUtilsHelper.toPhrase(columnName) 174 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableColumnMessageValue(String) 175 */ 176 protected String handleGetTableColumnMessageValue(final String columnName) 177 { 178 return StringUtilsHelper.toPhrase(columnName); 179 } 180 181 /** 182 * @return getTableActions(true) 183 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableHyperlinkActions() 184 */ 185 protected List<JSFAction> handleGetTableHyperlinkActions() 186 { 187 return this.getTableActions(true); 188 } 189 190 /** 191 * If this is a table this method returns all those actions that are declared to work 192 * on this table. 193 * 194 * @param hyperlink denotes on which type of actions to filter 195 */ 196 private List<JSFAction> getTableActions(boolean hyperlink) 197 { 198 final Set<JSFAction> actions = new LinkedHashSet<JSFAction>(); 199 final String name = StringUtils.trimToNull(getName()); 200 if (name != null && isTable()) 201 { 202 final JSFView view = (JSFView)this.getView(); 203 204 final Collection<UseCaseFacade> allUseCases = getModel().getAllUseCases(); 205 for (final UseCaseFacade useCase : allUseCases) 206 { 207 if (useCase instanceof JSFUseCase) 208 { 209 final FrontEndActivityGraph graph = ((JSFUseCase)useCase).getActivityGraph(); 210 if (graph != null) 211 { 212 final Collection<TransitionFacade> transitions = graph.getTransitions(); 213 for (final TransitionFacade transition : transitions) 214 { 215 if (transition.getSource().equals(view) && transition instanceof JSFAction) 216 { 217 final JSFAction action = (JSFAction)transition; 218 if (action.isTableLink() && name.equals(action.getTableLinkName())) 219 { 220 if (hyperlink == action.isHyperlink()) 221 { 222 actions.add(action); 223 } 224 } 225 } 226 } 227 } 228 } 229 } 230 } 231 return new ArrayList<JSFAction>(actions); 232 } 233 234 /** 235 * @return getTableActions(false) 236 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableFormActions() 237 */ 238 protected List<JSFAction> handleGetTableFormActions() 239 { 240 return this.getTableActions(false); 241 } 242 243 /** 244 * @see org.andromda.metafacades.uml.FrontEndParameter#getTableColumns() 245 */ 246 // TODO tableColumns can be either String or JSFParameter. Should use a single return type in Collection. 247 public Collection getTableColumns() 248 { 249 final Collection tableColumns = super.getTableColumns(); 250 if (tableColumns.isEmpty()) 251 { 252 // try to preserve the order of the elements encountered 253 //final Map<String, JSFParameter> tableColumnsMap = new LinkedHashMap<String, JSFParameter>(); 254 final Map tableColumnsMap = new LinkedHashMap(); 255 256 // order is important 257 final List<JSFAction> actions = new ArrayList<JSFAction>(); 258 259 // all table actions need the exact same parameters, just not always all of them 260 actions.addAll(this.getTableFormActions()); 261 262 // if there are any actions that are hyperlinks then their parameters get priority 263 // the user should not have modeled it that way (constraints will warn him/her) 264 actions.addAll(this.getTableHyperlinkActions()); 265 266 for (final JSFAction action : actions) 267 { 268 for (final FrontEndParameter actionParameter : action.getParameters()) 269 { 270 if (actionParameter instanceof JSFParameter) 271 { 272 final JSFParameter parameter = (JSFParameter)actionParameter; 273 final String parameterName = parameter.getName(); 274 if (parameterName != null) 275 { 276 // never overwrite column specific table links 277 // the hyperlink table links working on a real column get priority 278 final Object existingObject = tableColumnsMap.get(parameterName); 279 if (existingObject instanceof JSFParameter) 280 { 281 if (action.isHyperlink() && parameterName.equals(action.getTableLinkColumnName())) 282 { 283 tableColumnsMap.put( 284 parameterName, 285 parameter); 286 } 287 } 288 } 289 } 290 } 291 } 292 293 // for any missing parameters we just add the name of the column 294 for (final String columnName : this.getTableColumnNames()) 295 { 296 if (!tableColumnsMap.containsKey(columnName)) 297 { 298 tableColumnsMap.put( 299 columnName, 300 columnName); 301 } 302 } 303 304 // return everything in the same order as it has been modeled (using the table tagged value) 305 for (final String columnObject : this.getTableColumnNames()) 306 { 307 tableColumns.add(tableColumnsMap.get(columnObject)); 308 } 309 } 310 return tableColumns; 311 } 312 313 /** 314 * @return the default date format pattern as defined using the configured property 315 */ 316 private String getDefaultDateFormat() 317 { 318 return (String)this.getConfiguredProperty(JSFGlobals.PROPERTY_DEFAULT_DATEFORMAT); 319 } 320 321 /** 322 * @return format 323 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getFormat() 324 */ 325 protected String handleGetFormat() 326 { 327 return JSFUtils.getFormat( 328 (ModelElementFacade)this.THIS(), 329 this.getType(), 330 this.getDefaultDateFormat(), 331 this.getDefaultTimeFormat()); 332 } 333 334 /** 335 * @return the default time format pattern as defined using the configured property 336 */ 337 private String getDefaultTimeFormat() 338 { 339 return (String)this.getConfiguredProperty(JSFGlobals.PROPERTY_DEFAULT_TIMEFORMAT); 340 } 341 342 /** 343 * @return JSFUtils.isStrictDateFormat((ModelElementFacade)this.THIS()) 344 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isStrictDateFormat() 345 */ 346 protected boolean handleIsStrictDateFormat() 347 { 348 return JSFUtils.isStrictDateFormat((ModelElementFacade)this.THIS()); 349 } 350 351 /** 352 * @return dateFormatter 353 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDateFormatter() 354 */ 355 protected String handleGetDateFormatter() 356 { 357 final ClassifierFacade type = this.getType(); 358 return type != null && type.isDateType() ? this.getName() + "DateFormatter" : null; 359 } 360 361 /** 362 * @return timeFormatter 363 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTimeFormatter() 364 */ 365 protected String handleGetTimeFormatter() 366 { 367 final ClassifierFacade type = this.getType(); 368 return type != null && type.isTimeType() ? this.getName() + "TimeFormatter" : null; 369 } 370 371 /** 372 * Gets the current value of the specified input type (or an empty string 373 * if one isn't specified). 374 * 375 * @return the input type name. 376 */ 377 private String getInputType() 378 { 379 return ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TYPE)).trim(); 380 } 381 382 /** 383 * Indicates whether or not this parameter is of the given input type. 384 * 385 * @param inputType the name of the input type to check for. 386 * @return true/false 387 */ 388 private boolean isInputType(final String inputType) 389 { 390 return inputType.equalsIgnoreCase(this.getInputType()); 391 } 392 393 /** 394 * @return isInputType(JSFGlobals.INPUT_TEXTAREA) 395 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputTextarea() 396 */ 397 protected boolean handleIsInputTextarea() 398 { 399 return this.isInputType(JSFGlobals.INPUT_TEXTAREA); 400 } 401 402 /** 403 * @return isInputType(JSFGlobals.INPUT_SELECT) 404 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputSelect() 405 */ 406 protected boolean handleIsInputSelect() 407 { 408 return this.isInputType(JSFGlobals.INPUT_SELECT); 409 } 410 411 /** 412 * @return isInputType(JSFGlobals.INPUT_PASSWORD) 413 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputSecret() 414 */ 415 protected boolean handleIsInputSecret() 416 { 417 return this.isInputType(JSFGlobals.INPUT_PASSWORD); 418 } 419 420 /** 421 * @return isInputType(JSFGlobals.INPUT_HIDDEN) 422 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputHidden() 423 */ 424 protected boolean handleIsInputHidden() 425 { 426 return this.isInputType(JSFGlobals.INPUT_HIDDEN); 427 } 428 429 /** 430 * @return isInputType(JSFGlobals.PLAIN_TEXT) 431 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isPlaintext() 432 */ 433 protected boolean handleIsPlaintext() 434 { 435 return this.isInputType(JSFGlobals.PLAIN_TEXT); 436 } 437 438 /** 439 * @return isInputTable 440 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputTable() 441 */ 442 protected boolean handleIsInputTable() 443 { 444 return this.getInputTableIdentifierColumns().length() > 0 || this.isInputType(JSFGlobals.INPUT_TABLE); 445 } 446 447 /** 448 * @return isInputType(JSFGlobals.INPUT_RADIO) 449 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputRadio() 450 */ 451 protected boolean handleIsInputRadio() 452 { 453 return this.isInputType(JSFGlobals.INPUT_RADIO); 454 } 455 456 /** 457 * @return isInputType(JSFGlobals.INPUT_TEXT) 458 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputText() 459 */ 460 protected boolean handleIsInputText() 461 { 462 return this.isInputType(JSFGlobals.INPUT_TEXT); 463 } 464 465 /** 466 * @return isInputType(JSFGlobals.INPUT_MULTIBOX) 467 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputMultibox() 468 */ 469 protected boolean handleIsInputMultibox() 470 { 471 return this.isInputType(JSFGlobals.INPUT_MULTIBOX); 472 } 473 474 /** 475 * @return isInputCheckbox 476 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputCheckbox() 477 */ 478 protected boolean handleIsInputCheckbox() 479 { 480 boolean checkbox = this.isInputType(JSFGlobals.INPUT_CHECKBOX); 481 if (!checkbox && this.getInputType().length() == 0) 482 { 483 final ClassifierFacade type = this.getType(); 484 checkbox = type != null ? type.isBooleanType() : false; 485 } 486 return checkbox; 487 } 488 489 /** 490 * @return isInputFile 491 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isInputFile() 492 */ 493 protected boolean handleIsInputFile() 494 { 495 boolean file = false; 496 ClassifierFacade type = getType(); 497 if (type != null) 498 { 499 file = type.isFileType(); 500 } 501 return file; 502 } 503 504 /** 505 * @return backingListName 506 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getBackingListName() 507 */ 508 protected String handleGetBackingListName() 509 { 510 return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.BACKING_LIST_PATTERN)).replaceAll( 511 "\\{0\\}", 512 this.getName()); 513 } 514 515 /** 516 * @return backingValueName 517 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getBackingValueName() 518 */ 519 protected String handleGetBackingValueName() 520 { 521 return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.BACKING_VALUE_PATTERN)).replaceAll( 522 "\\{0\\}", 523 this.getName()); 524 } 525 526 /** 527 * @return valueListName 528 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValueListName() 529 */ 530 protected String handleGetValueListName() 531 { 532 return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.VALUE_LIST_PATTERN)).replaceAll( 533 "\\{0\\}", 534 this.getName()); 535 } 536 537 /** 538 * @return labelListName 539 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getLabelListName() 540 */ 541 protected String handleGetLabelListName() 542 { 543 return ObjectUtils.toString(this.getConfiguredProperty(JSFGlobals.LABEL_LIST_PATTERN)).replaceAll( 544 "\\{0\\}", 545 this.getName()); 546 } 547 548 /** 549 * @return isSelectable 550 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isSelectable() 551 */ 552 protected boolean handleIsSelectable() 553 { 554 boolean selectable = false; 555 if (this.isActionParameter()) 556 { 557 selectable = this.isInputMultibox() || this.isInputSelect() || this.isInputRadio(); 558 final ClassifierFacade type = this.getType(); 559 560 if (!selectable && type != null) 561 { 562 final String name = this.getName(); 563 final String typeName = type.getFullyQualifiedName(); 564 565 // - if the parameter is not selectable but on a targeting page it IS selectable we must 566 // allow the user to set the backing list too 567 final Collection<FrontEndView> views = this.getAction().getTargetViews(); 568 for (final Iterator<FrontEndView> iterator = views.iterator(); iterator.hasNext() && !selectable;) 569 { 570 final Collection<FrontEndParameter> parameters = iterator.next().getAllActionParameters(); 571 for (final Iterator<FrontEndParameter> parameterIterator = parameters.iterator(); 572 parameterIterator.hasNext() && !selectable;) 573 { 574 final Object object = parameterIterator.next(); 575 if (object instanceof JSFParameter) 576 { 577 final JSFParameter parameter = (JSFParameter)object; 578 final String parameterName = parameter.getName(); 579 final ClassifierFacade parameterType = parameter.getType(); 580 if (parameterType != null) 581 { 582 final String parameterTypeName = parameterType.getFullyQualifiedName(); 583 if (name.equals(parameterName) && typeName.equals(parameterTypeName)) 584 { 585 selectable = 586 parameter.isInputMultibox() || parameter.isInputSelect() || 587 parameter.isInputRadio(); 588 } 589 } 590 } 591 } 592 } 593 } 594 } 595 else if (this.isControllerOperationArgument()) 596 { 597 final String name = this.getName(); 598 final Collection actions = this.getControllerOperation().getDeferringActions(); 599 for (final Iterator actionIterator = actions.iterator(); actionIterator.hasNext();) 600 { 601 final JSFAction action = (JSFAction)actionIterator.next(); 602 final Collection<FrontEndParameter> formFields = action.getFormFields(); 603 for (final Iterator<FrontEndParameter> fieldIterator = formFields.iterator(); 604 fieldIterator.hasNext() && !selectable;) 605 { 606 final Object object = fieldIterator.next(); 607 if (object instanceof JSFParameter) 608 { 609 final JSFParameter parameter = (JSFParameter)object; 610 if (!parameter.equals(this)) 611 { 612 if (name.equals(parameter.getName())) 613 { 614 selectable = parameter.isSelectable(); 615 } 616 } 617 } 618 } 619 } 620 } 621 return selectable; 622 } 623 624 /** 625 * Stores the initial value of each type. 626 */ 627 private final Map<String, String> initialValues = new HashMap<String, String>(); 628 629 /** 630 * @return constructDummyArray() 631 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValueListDummyValue() 632 */ 633 protected String handleGetValueListDummyValue() 634 { 635 return this.constructDummyArray(); 636 } 637 638 /** 639 * @return dummyValue 640 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getDummyValue() 641 */ 642 protected String handleGetDummyValue() 643 { 644 final ClassifierFacade type = this.getType(); 645 final String typeName = type != null ? type.getFullyQualifiedName() : ""; 646 String initialValue = null; 647 if (type != null) 648 { 649 if (type.isSetType()) 650 { 651 initialValue = 652 "new java.util.LinkedHashSet(java.util.Arrays.asList(" + this.constructDummyArray() + "))"; 653 } 654 else if (type.isCollectionType()) 655 { 656 initialValue = "java.util.Arrays.asList(" + this.constructDummyArray() + ")"; 657 } 658 else if (type.isArrayType()) 659 { 660 initialValue = this.constructDummyArray(); 661 } 662 final String name = this.getName() != null ? this.getName() : ""; 663 if (this.initialValues.isEmpty()) 664 { 665 initialValues.put( 666 boolean.class.getName(), 667 "false"); 668 initialValues.put( 669 int.class.getName(), 670 "(int)" + name.hashCode()); 671 initialValues.put( 672 long.class.getName(), 673 "(long)" + name.hashCode()); 674 initialValues.put( 675 short.class.getName(), 676 "(short)" + name.hashCode()); 677 initialValues.put( 678 byte.class.getName(), 679 "(byte)" + name.hashCode()); 680 initialValues.put( 681 float.class.getName(), 682 "(float)" + name.hashCode()); 683 initialValues.put( 684 double.class.getName(), 685 "(double)" + name.hashCode()); 686 initialValues.put( 687 char.class.getName(), 688 "(char)" + name.hashCode()); 689 690 initialValues.put( 691 String.class.getName(), 692 "\"" + name + "-test" + "\""); 693 initialValues.put( 694 java.util.Date.class.getName(), 695 "new java.util.Date()"); 696 initialValues.put( 697 java.sql.Date.class.getName(), 698 "new java.util.Date()"); 699 initialValues.put( 700 java.sql.Timestamp.class.getName(), 701 "new java.util.Date()"); 702 703 initialValues.put( 704 Integer.class.getName(), 705 "new Integer((int)" + name.hashCode() + ")"); 706 initialValues.put( 707 Boolean.class.getName(), 708 "Boolean.FALSE"); 709 initialValues.put( 710 Long.class.getName(), 711 "new Long((long)" + name.hashCode() + ")"); 712 initialValues.put( 713 Character.class.getName(), 714 "new Character(char)" + name.hashCode() + ")"); 715 initialValues.put( 716 Float.class.getName(), 717 "new Float((float)" + name.hashCode() / hashCode() + ")"); 718 initialValues.put( 719 Double.class.getName(), 720 "new Double((double)" + name.hashCode() / hashCode() + ")"); 721 initialValues.put( 722 Short.class.getName(), 723 "new Short((short)" + name.hashCode() + ")"); 724 initialValues.put( 725 Byte.class.getName(), 726 "new Byte((byte)" + name.hashCode() + ")"); 727 } 728 if (initialValue == null) 729 { 730 initialValue = this.initialValues.get(typeName); 731 } 732 } 733 if (initialValue == null) 734 { 735 initialValue = "null"; 736 } 737 return initialValue; 738 } 739 740 /** 741 * Constructs a string representing an array initialization in Java. 742 * 743 * @return A String representing Java code for the initialization of an array. 744 */ 745 private String constructDummyArray() 746 { 747 return JSFUtils.constructDummyArrayDeclaration( 748 this.getName(), 749 JSFGlobals.DUMMY_ARRAY_COUNT); 750 } 751 752 /** 753 * @return getName() + "SortColumn" 754 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableSortColumnProperty() 755 */ 756 protected String handleGetTableSortColumnProperty() 757 { 758 return this.getName() + "SortColumn"; 759 } 760 761 /** 762 * @return getName() + "SortAscending" 763 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableSortAscendingProperty() 764 */ 765 protected String handleGetTableSortAscendingProperty() 766 { 767 return this.getName() + "SortAscending"; 768 } 769 770 /** 771 * @return getName() + "Set" 772 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getFormAttributeSetProperty() 773 */ 774 protected String handleGetFormAttributeSetProperty() 775 { 776 return this.getName() + "Set"; 777 } 778 779 //TODO remove after 3.4 release 780 /** 781 * Hack to keep the compatibility with Andromda 3.4 782 */ 783 /** 784 * @see org.andromda.metafacades.uml.FrontEndParameter#getView() 785 */ 786 public FrontEndView getView() 787 { 788 Object view = null; 789 final EventFacade event = this.getEvent(); 790 if (event != null) 791 { 792 final TransitionFacade transition = event.getTransition(); 793 if (transition instanceof JSFActionLogicImpl) 794 { 795 final JSFActionLogicImpl action = (JSFActionLogicImpl)transition; 796 view = action.getInput(); 797 } 798 else if (transition instanceof FrontEndForward) 799 { 800 final FrontEndForward forward = (FrontEndForward)transition; 801 if (forward.isEnteringView()) 802 { 803 view = forward.getTarget(); 804 } 805 } 806 } 807 return (FrontEndView)view; 808 } 809 810 /** 811 * @return validationRequired 812 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isValidationRequired() 813 */ 814 protected boolean handleIsValidationRequired() 815 { 816 boolean required = !this.getValidatorTypes().isEmpty(); 817 if (!required) 818 { 819 // - look for any attributes 820 for (final Iterator<JSFAttribute> iterator = this.getAttributes().iterator(); iterator.hasNext();) 821 { 822 required = !iterator.next().getValidatorTypes().isEmpty(); 823 if (required) 824 { 825 break; 826 } 827 } 828 829 // - look for any table columns 830 if (!required) 831 { 832 for (final Iterator iterator = this.getTableColumns().iterator(); iterator.hasNext();) 833 { 834 final Object object = iterator.next(); 835 if (object instanceof JSFAttribute) 836 { 837 final JSFAttribute attribute = (JSFAttribute)object; 838 required = !attribute.getValidatorTypes().isEmpty(); 839 if (required) 840 { 841 break; 842 } 843 } 844 } 845 } 846 } 847 return required; 848 } 849 850 /** 851 * @return validatorTypes 852 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidatorTypes() 853 */ 854 protected Collection handleGetValidatorTypes() 855 { 856 return JSFUtils.getValidatorTypes( 857 (ModelElementFacade)this.THIS(), 858 this.getType()); 859 } 860 861 /** 862 * @return JSFUtils.getValidWhen(this) 863 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidWhen() 864 */ 865 protected String handleGetValidWhen() 866 { 867 return JSFUtils.getValidWhen(this); 868 } 869 870 /** 871 * Overridden to have the same behavior as bpm4struts. 872 * 873 * @see org.andromda.metafacades.uml.ParameterFacade#isRequired() 874 */ 875 public boolean isRequired() 876 { 877 if("org.omg.uml.foundation.core".equals(metaObject.getClass().getPackage().getName())) 878 { 879 //if uml 1.4, keep the old behavior (like bpm4struts) 880 final Object value = this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_REQUIRED); 881 return Boolean.valueOf(ObjectUtils.toString(value)).booleanValue(); 882 } 883 else 884 { 885 //if >= uml 2, default behavior 886 return super.isRequired(); 887 } 888 } 889 890 /** 891 * @return JSFUtils.isReadOnly(this) 892 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isReadOnly() 893 */ 894 protected boolean handleIsReadOnly() 895 { 896 return JSFUtils.isReadOnly(this); 897 } 898 899 /** 900 * @param validatorType 901 * @return validatorArgs 902 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidatorArgs(String) 903 */ 904 protected Collection handleGetValidatorArgs(final String validatorType) 905 { 906 return JSFUtils.getValidatorArgs( 907 (ModelElementFacade)this.THIS(), 908 validatorType); 909 } 910 911 /** 912 * @return validatorVars 913 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getValidatorVars() 914 */ 915 protected Collection handleGetValidatorVars() 916 { 917 return JSFUtils.getValidatorVars( 918 (ModelElementFacade)this.THIS(), 919 this.getType(), 920 null); 921 } 922 923 /** 924 * @return reset 925 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isReset() 926 */ 927 protected boolean handleIsReset() 928 { 929 boolean reset = 930 Boolean.valueOf(ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_RESET))) 931 .booleanValue(); 932 if (!reset) 933 { 934 final JSFAction action = (JSFAction)this.getAction(); 935 reset = action != null && action.isFormReset(); 936 } 937 return reset; 938 } 939 940 /** 941 * @return complex 942 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isComplex() 943 */ 944 protected boolean handleIsComplex() 945 { 946 boolean complex = false; 947 final ClassifierFacade type = this.getType(); 948 if (type != null) 949 { 950 complex = !type.getAttributes().isEmpty(); 951 if (!complex) 952 { 953 complex = !type.getAssociationEnds().isEmpty(); 954 } 955 } 956 return complex; 957 } 958 959 /** 960 * @return attributes 961 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getAttributes() 962 */ 963 protected Collection<AttributeFacade> handleGetAttributes() 964 { 965 Collection<AttributeFacade> attributes = null; 966 ClassifierFacade type = this.getType(); 967 if (type != null) 968 { 969 if (type.isArrayType()) 970 { 971 type = type.getNonArray(); 972 } 973 if (type != null) 974 { 975 attributes = type.getAttributes(true); 976 } 977 } 978 return attributes == null ? new ArrayList<AttributeFacade>() : attributes; 979 } 980 981 /** 982 * @return navigableAssociationEnds 983 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getNavigableAssociationEnds() 984 */ 985 protected Collection<AssociationEndFacade> handleGetNavigableAssociationEnds() 986 { 987 Collection<AssociationEndFacade> associationEnds = null; 988 ClassifierFacade type = this.getType(); 989 if (type != null) 990 { 991 if (type.isArrayType()) 992 { 993 type = type.getNonArray(); 994 } 995 if (type != null) 996 { 997 associationEnds = type.getNavigableConnectingEnds(); 998 } 999 } 1000 return associationEnds == null ? new ArrayList<AssociationEndFacade>() : associationEnds; 1001 } 1002 1003 /** 1004 * @return isEqualValidator 1005 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isEqualValidator() 1006 */ 1007 protected boolean handleIsEqualValidator() 1008 { 1009 final String equal = JSFUtils.getEqual((ModelElementFacade)this.THIS()); 1010 return equal != null && equal.trim().length() > 0; 1011 } 1012 1013 /** 1014 * @return isBackingValueRequired 1015 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#isEqualValidator() 1016 */ 1017 protected boolean handleIsBackingValueRequired() 1018 { 1019 boolean required = false; 1020 if (this.isActionParameter()) 1021 { 1022 required = this.isInputTable(); 1023 final ClassifierFacade type = this.getType(); 1024 1025 if (!required && type != null) 1026 { 1027 final String name = this.getName(); 1028 final String typeName = type.getFullyQualifiedName(); 1029 1030 // - if the backing value is not required for this parameter but on 1031 // a targeting page it IS selectable we must allow the user to set the backing value as well 1032 final Collection<FrontEndView> views = this.getAction().getTargetViews(); 1033 for (final Iterator<FrontEndView> iterator = views.iterator(); iterator.hasNext() && !required;) 1034 { 1035 final Collection<FrontEndParameter> parameters = iterator.next().getAllActionParameters(); 1036 for (final Iterator<FrontEndParameter> parameterIterator = parameters.iterator(); 1037 parameterIterator.hasNext() && !required;) 1038 { 1039 final FrontEndParameter object = parameterIterator.next(); 1040 if (object instanceof JSFParameter) 1041 { 1042 final JSFParameter parameter = (JSFParameter)object; 1043 final String parameterName = parameter.getName(); 1044 final ClassifierFacade parameterType = parameter.getType(); 1045 if (parameterType != null) 1046 { 1047 final String parameterTypeName = parameterType.getFullyQualifiedName(); 1048 if (name.equals(parameterName) && typeName.equals(parameterTypeName)) 1049 { 1050 required = parameter.isInputTable(); 1051 } 1052 } 1053 } 1054 } 1055 } 1056 } 1057 } 1058 else if (this.isControllerOperationArgument()) 1059 { 1060 final String name = this.getName(); 1061 final Collection<FrontEndAction> actions = this.getControllerOperation().getDeferringActions(); 1062 for (final Iterator<FrontEndAction> actionIterator = actions.iterator(); actionIterator.hasNext();) 1063 { 1064 final JSFAction action = (JSFAction)actionIterator.next(); 1065 final Collection<FrontEndParameter> formFields = action.getFormFields(); 1066 for (final Iterator<FrontEndParameter> fieldIterator = formFields.iterator(); 1067 fieldIterator.hasNext() && !required;) 1068 { 1069 final Object object = fieldIterator.next(); 1070 if (object instanceof JSFParameter) 1071 { 1072 final JSFParameter parameter = (JSFParameter)object; 1073 if (!parameter.equals(this)) 1074 { 1075 if (name.equals(parameter.getName())) 1076 { 1077 required = parameter.isBackingValueRequired(); 1078 } 1079 } 1080 } 1081 } 1082 } 1083 } 1084 return required; 1085 } 1086 1087 /** 1088 * @return findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TABLE_IDENTIFIER_COLUMNS) 1089 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getInputTableIdentifierColumns() 1090 */ 1091 protected String handleGetInputTableIdentifierColumns() 1092 { 1093 return ObjectUtils.toString(this.findTaggedValue(JSFProfile.TAGGEDVALUE_INPUT_TABLE_IDENTIFIER_COLUMNS)).trim(); 1094 } 1095 1096 /** 1097 * @param columnName 1098 * @return tableColumnActions 1099 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getTableColumnActions(String) 1100 */ 1101 protected List<JSFAction> handleGetTableColumnActions(final String columnName) 1102 { 1103 final List<JSFAction> columnActions = new ArrayList<JSFAction>(); 1104 1105 if (columnName != null) 1106 { 1107 final Set<JSFAction> actions = new LinkedHashSet<JSFAction>(this.getTableHyperlinkActions()); 1108 actions.addAll(this.getTableFormActions()); 1109 for (final JSFAction action : actions) 1110 { 1111 if (columnName.equals(action.getTableLinkColumnName())) 1112 { 1113 columnActions.add(action); 1114 } 1115 } 1116 } 1117 1118 return columnActions; 1119 } 1120 1121 /** 1122 * @return maxLength 1123 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMaxLength() 1124 */ 1125 protected String handleGetMaxLength() 1126 { 1127 final Collection<Collection> vars=getValidatorVars(); 1128 if(vars == null) 1129 { 1130 return null; 1131 } 1132 for(Iterator<Collection> it=vars.iterator(); it.hasNext();) 1133 { 1134 final Object[] values=(it.next()).toArray(); 1135 if("maxlength".equals(values[0])) 1136 { 1137 return values[1].toString(); 1138 } 1139 } 1140 return null; 1141 } 1142 1143 //to be used in the range validator: "range - 1000" or "range 20 -". 1144 /** - */ 1145 static final String UNDEFINED_BOUND="-"; 1146 /** javax.validation.constraints.NotNull */ 1147 static final String AN_REQUIRED = "@javax.validation.constraints.NotNull"; 1148 /** org.hibernate.validator.constraints.URL */ 1149 static final String AN_URL = "@org.hibernate.validator.constraints.URL"; 1150 /** org.apache.myfaces.extensions.validator.baseval.annotation.LongRange */ 1151 static final String AN_LONG_RANGE = "@org.apache.myfaces.extensions.validator.baseval.annotation.LongRange"; 1152 /** org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange */ 1153 static final String AN_DOUBLE_RANGE = "@org.apache.myfaces.extensions.validator.baseval.annotation.DoubleRange"; 1154 /** org.hibernate.validator.constraints.Email */ 1155 static final String AN_EMAIL = "@org.hibernate.validator.constraints.Email"; 1156 /** org.hibernate.validator.constraints.CreditCardNumber */ 1157 static final String AN_CREDIT_CARD = "@org.hibernate.validator.constraints.CreditCardNumber"; 1158 /** javax.validation.constraints.Size */ 1159 static final String AN_LENGTH = "@javax.validation.constraints.Size"; 1160 /** org.apache.myfaces.extensions.validator.baseval.annotation.Pattern */ 1161 static final String AN_PATTERN = "@org.apache.myfaces.extensions.validator.baseval.annotation.Pattern"; 1162 /** org.apache.myfaces.extensions.validator.crossval.annotation.Equals */ 1163 static final String AN_EQUALS = "@org.apache.myfaces.extensions.validator.crossval.annotation.Equals"; 1164 1165 /** 1166 * @return the annotations 1167 * @see org.andromda.cartridges.jsf.metafacades.JSFParameter#getMaxLength() 1168 */ 1169 @Override 1170 protected Collection<String> handleGetAnnotations() 1171 { 1172 final Collection<String> result=new HashSet<String>(); 1173 boolean requiredAdded=false; 1174 for(String vt: (Collection<String>)getValidatorTypes()) 1175 { 1176 if(vt.startsWith("@")) //add the annotation 1177 { 1178 result.add(vt); 1179 } 1180 if(JSFUtils.VT_REQUIRED.equals(vt)) 1181 { 1182 requiredAdded=true; 1183 result.add(AN_REQUIRED); 1184 } 1185 else if(JSFUtils.VT_URL.equals(vt)) 1186 { 1187 result.add(AN_URL); 1188 } 1189 else if(JSFUtils.VT_INT_RANGE.equals(vt)) 1190 { 1191 final StringBuilder sb=new StringBuilder(AN_LONG_RANGE+"("); 1192 final String format = JSFUtils.getInputFormat((ModelElementFacade)this.THIS()); 1193 final String rangeStart = JSFUtils.getRangeStart(format); 1194 boolean addComma=false; 1195 if(StringUtils.isNotBlank(rangeStart) && !rangeStart.equals(UNDEFINED_BOUND)) 1196 { 1197 sb.append("minimum="+rangeStart); 1198 addComma=true; 1199 } 1200 final String rangeEnd = JSFUtils.getRangeEnd(format); 1201 if(StringUtils.isNotBlank(rangeEnd) && !rangeEnd.equals(UNDEFINED_BOUND)) 1202 { 1203 if(addComma) 1204 { 1205 sb.append(","); 1206 } 1207 sb.append("maximum="+rangeEnd); 1208 } 1209 sb.append(")"); 1210 result.add(sb.toString()); 1211 } 1212 else if(JSFUtils.VT_FLOAT_RANGE.equals(vt) || JSFUtils.VT_DOUBLE_RANGE.equals(vt)) 1213 { 1214 final StringBuilder sb=new StringBuilder(AN_DOUBLE_RANGE+"("); 1215 final String format = JSFUtils.getInputFormat(((ModelElementFacade)this.THIS())); 1216 final String rangeStart = JSFUtils.getRangeStart(format); 1217 boolean addComma=false; 1218 if(StringUtils.isNotBlank(rangeStart) && !rangeStart.equals(UNDEFINED_BOUND)) 1219 { 1220 sb.append("minimum="+rangeStart); 1221 addComma=true; 1222 } 1223 final String rangeEnd = JSFUtils.getRangeEnd(format); 1224 if(StringUtils.isNotBlank(rangeEnd) && !rangeEnd.equals(UNDEFINED_BOUND)) 1225 { 1226 if(addComma) 1227 { 1228 sb.append(","); 1229 } 1230 sb.append("maximum="+rangeEnd); 1231 } 1232 sb.append(")"); 1233 result.add(sb.toString()); 1234 } 1235 else if(JSFUtils.VT_EMAIL.equals(vt)) 1236 { 1237 result.add(AN_EMAIL); 1238 } 1239 else if(JSFUtils.VT_CREDIT_CARD.equals(vt)) 1240 { 1241 result.add(AN_CREDIT_CARD); 1242 } 1243 else if(JSFUtils.VT_MIN_LENGTH.equals(vt) || JSFUtils.VT_MAX_LENGTH.equals(vt)) 1244 { 1245 final StringBuilder sb=new StringBuilder(AN_LENGTH+"("); 1246 final Collection formats = this.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_FORMAT); 1247 boolean addComma=false; 1248 for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();) 1249 { 1250 final String additionalFormat = String.valueOf(formatIterator.next()); 1251 if (JSFUtils.isMinLengthFormat(additionalFormat)) 1252 { 1253 if(addComma) 1254 { 1255 sb.append(","); 1256 } 1257 sb.append("min="); 1258 sb.append(JSFUtils.getMinLengthValue(additionalFormat)); 1259 addComma=true; 1260 } 1261 else if (JSFUtils.isMaxLengthFormat(additionalFormat)) 1262 { 1263 if(addComma) 1264 { 1265 sb.append(","); 1266 } 1267 sb.append("max="); 1268 sb.append(JSFUtils.getMinLengthValue(additionalFormat)); 1269 addComma=true; 1270 } 1271 } 1272 sb.append(")"); 1273 result.add(sb.toString()); 1274 } 1275 else if(JSFUtils.VT_MASK.equals(vt)) 1276 { 1277 final Collection formats = this.findTaggedValues(JSFProfile.TAGGEDVALUE_INPUT_FORMAT); 1278 for (final Iterator formatIterator = formats.iterator(); formatIterator.hasNext();) 1279 { 1280 final String additionalFormat = String.valueOf(formatIterator.next()); 1281 if (JSFUtils.isPatternFormat(additionalFormat)) 1282 { 1283 result.add(AN_PATTERN+"(\""+JSFUtils.getPatternValue(additionalFormat)+"\")"); 1284 } 1285 } 1286 } 1287 else if(JSFUtils.VT_VALID_WHEN.equals(vt)) 1288 { 1289 result.add(""); 1290 } 1291 else if(JSFUtils.VT_EQUAL.equals(vt)) 1292 { 1293 result.add(AN_EQUALS+"(\""+JSFUtils.getEqual((ModelElementFacade)this.THIS())+"\")"); 1294 } 1295 } 1296 if(!requiredAdded && getLower() > 0) 1297 { 1298 result.add(AN_REQUIRED); 1299 } 1300 return result; 1301 } 1302}