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