001package org.andromda.metafacades.uml14; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Collections; 006import java.util.HashMap; 007import java.util.Iterator; 008import java.util.Map; 009import java.util.regex.Pattern; 010import org.andromda.core.metafacade.MetafacadeBase; 011import org.andromda.core.metafacade.MetafacadeConstants; 012import org.andromda.core.metafacade.MetafacadeFactory; 013import org.andromda.metafacades.uml.BindingFacade; 014import org.andromda.metafacades.uml.ConstraintFacade; 015import org.andromda.metafacades.uml.DependencyFacade; 016import org.andromda.metafacades.uml.EnumerationLiteralFacade; 017import org.andromda.metafacades.uml.MetafacadeUtils; 018import org.andromda.metafacades.uml.ModelElementFacade; 019import org.andromda.metafacades.uml.NameMasker; 020import org.andromda.metafacades.uml.ParameterFacade; 021import org.andromda.metafacades.uml.RedefinableTemplateSignatureFacade; 022import org.andromda.metafacades.uml.StereotypeFacade; 023import org.andromda.metafacades.uml.TaggedValueFacade; 024import org.andromda.metafacades.uml.TemplateArgumentFacade; 025import org.andromda.metafacades.uml.TemplateParameterFacade; 026import org.andromda.metafacades.uml.TypeMappings; 027import org.andromda.metafacades.uml.UMLMetafacadeProperties; 028import org.andromda.metafacades.uml.UMLMetafacadeUtils; 029import org.andromda.metafacades.uml.UMLProfile; 030import org.andromda.translation.ocl.ExpressionKinds; 031import org.andromda.utils.StringUtilsHelper; 032import org.apache.commons.collections.CollectionUtils; 033import org.apache.commons.collections.Predicate; 034import org.apache.commons.lang.BooleanUtils; 035import org.apache.commons.lang.ObjectUtils; 036import org.apache.commons.lang.StringUtils; 037import org.apache.commons.lang.SystemUtils; 038import org.apache.log4j.Logger; 039import org.omg.uml.behavioralelements.statemachines.StateMachine; 040import org.omg.uml.foundation.core.Abstraction; 041import org.omg.uml.foundation.core.Classifier; 042import org.omg.uml.foundation.core.Comment; 043import org.omg.uml.foundation.core.Dependency; 044import org.omg.uml.foundation.core.Feature; 045import org.omg.uml.foundation.core.ModelElement; 046import org.omg.uml.foundation.core.Namespace; 047import org.omg.uml.foundation.datatypes.VisibilityKind; 048import org.omg.uml.foundation.datatypes.VisibilityKindEnum; 049import org.omg.uml.modelmanagement.UmlPackage; 050 051/** 052 * Metaclass facade implementation. 053 * @author Bob Fields 054 */ 055public class ModelElementFacadeLogicImpl 056 extends ModelElementFacadeLogic 057{ 058 private static final long serialVersionUID = 34L; 059 /** 060 * @param metaObject 061 * @param context 062 */ 063 public ModelElementFacadeLogicImpl( 064 org.omg.uml.foundation.core.ModelElement metaObject, 065 String context) 066 { 067 super(metaObject, context); 068 } 069 070 /** 071 * The logger instance. 072 */ 073 private static final Logger logger = Logger.getLogger(ModelElementFacadeLogicImpl.class); 074 075 /** 076 * @see org.andromda.metafacades.uml.ModelElementFacade#getTaggedValues() 077 */ 078 @Override 079 protected Collection handleGetTaggedValues() 080 { 081 return metaObject.getTaggedValue(); 082 } 083 084 /** 085 * @see org.andromda.metafacades.uml.ModelElementFacade#getPackageName() 086 */ 087 @Override 088 protected String handleGetPackageName() 089 { 090 final boolean modelName = false; 091 String packageName = UML14MetafacadeUtils.getPackageName( 092 this.metaObject, 093 this.getNamespaceScope(modelName), 094 modelName); 095 096 //package names are treated differently so we have to apply the name mask here 097 //since there isn't a packageNameMask, we're using the modelElementNameMask 098 String nameMask = null; 099 try 100 { 101 nameMask = String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.MODEL_ELEMENT_NAME_MASK)); 102 } 103 catch (Exception ignore) 104 { 105 logger.warn("modelElementNameMask not found in " + this.toString() + " (getPackageName)"); 106 nameMask = "none"; 107 } 108 109 return NameMasker.mask(packageName, nameMask); 110 111 } 112 113 /** 114 * @see org.andromda.metafacades.uml.ModelElementFacade#getPackageName(boolean) 115 */ 116 @Override 117 protected String handleGetPackageName(boolean modelName) 118 { 119 String packageName = this.handleGetPackageName(); 120 if (modelName) 121 { 122 packageName = 123 StringUtils.replace( 124 packageName, 125 ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR)), 126 MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR); 127 } 128 return packageName; 129 } 130 131 /** 132 * @see org.andromda.metafacades.uml.ModelElementFacade#getFullyQualifiedName(boolean) 133 */ 134 @Override 135 protected String handleGetFullyQualifiedName(boolean modelName) 136 { 137 return handleGetBindedFullyQualifiedName(modelName, Collections.<BindingFacade>emptyList()); 138 } 139 140 /** 141 * Gets the appropriate namespace property for retrieving the namespace scope operation (depending on the given 142 * <code>modelName</code> flag. 143 * 144 * @param modelName whether or not the scope operation for the model should be retrieved as opposed to the mapped 145 * scope operator. 146 * @return the scope operator. 147 */ 148 private String getNamespaceScope(boolean modelName) 149 { 150 String namespaceScope = MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR; 151 if (!modelName) 152 { 153 namespaceScope = 154 ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR)); 155 } 156 return namespaceScope; 157 } 158 159 /** 160 * @see org.andromda.metafacades.uml.ModelElementFacade#getFullyQualifiedName() 161 */ 162 @Override 163 protected String handleGetFullyQualifiedName() 164 { 165 return this.handleGetFullyQualifiedName(false); 166 } 167 168 /** 169 * @see org.andromda.metafacades.uml.ModelElementFacade#findTaggedValues(String) 170 */ 171 @Override 172 protected Collection<Object> handleFindTaggedValues(String name) 173 { 174 final Collection<Object> values = new ArrayList<Object>(); 175 176 // only search a tagged value when it actually has a name 177 if (StringUtils.isNotBlank(name)) 178 { 179 // trim the name, we don't want leading/trailing spaces 180 name = StringUtils.trimToEmpty(name); 181 182 for (final TaggedValueFacade taggedValue: this.getTaggedValues()) 183 { 184 // does this name match the argument tagged value name ? 185 // Check both the UML14 format name @andromda.value and EMF Format andromda_whatever 186 String tagName = taggedValue.getName(); 187 if (name.equals(tagName) || MetafacadeUtils.getEmfTaggedValue(name).equals(tagName) 188 || MetafacadeUtils.getUml14TaggedValue(name).equals(tagName)) 189 { 190 for (final Object value : taggedValue.getValues()) 191 { 192 // only process tagged values when they actually have a non-empty value 193 if (value != null) 194 { 195 // if an enumeration literal is referenced we assume its name 196 if (value instanceof EnumerationLiteralFacade) 197 { 198 values.add(((EnumerationLiteralFacade)value).getValue(true)); 199 } 200 else if (value instanceof String) 201 { 202 // only add String when they are not blank 203 String valueString = (String)value; 204 if (StringUtils.isNotBlank(valueString)) 205 { 206 values.add(value); 207 } 208 } 209 else 210 { 211 values.add(value); 212 } 213 } 214 } 215 } 216 } 217 } 218 return values; 219 } 220 221 /** 222 * @see org.andromda.metafacades.uml.ModelElementFacade#findTaggedValue(String) 223 */ 224 @Override 225 protected Object handleFindTaggedValue(String name) 226 { 227 Collection taggedValues = findTaggedValues(name); 228 return taggedValues.isEmpty() ? null : taggedValues.iterator().next(); 229 } 230 231 /** 232 * @see org.andromda.metafacades.uml.ModelElementFacade#hasStereotype(String) 233 */ 234 @Override 235 protected boolean handleHasStereotype(final String stereotypeName) 236 { 237 Collection<StereotypeFacade> stereotypes = this.getStereotypes(); 238 239 boolean hasStereotype = StringUtils.isNotBlank(stereotypeName) && stereotypes != null && 240 !stereotypes.isEmpty(); 241 242 if (hasStereotype) 243 { 244 class StereotypeFilter 245 implements Predicate 246 { 247 public boolean evaluate(Object object) 248 { 249 boolean valid; 250 StereotypeFacade facade = (StereotypeFacade)object; 251 String name = StringUtils.trimToEmpty(facade.getName()); 252 valid = stereotypeName.equals(name); 253 while (!valid && facade != null) 254 { 255 facade = (StereotypeFacade)facade.getGeneralization(); 256 valid = facade != null && StringUtils.trimToEmpty(facade.getName()).equals(stereotypeName); 257 } 258 return valid; 259 } 260 } 261 hasStereotype = CollectionUtils.find( 262 this.getStereotypes(), 263 new StereotypeFilter()) != null; 264 } 265 return hasStereotype; 266 } 267 268 /** 269 * @see org.andromda.metafacades.uml.ModelElementFacade#getId() 270 */ 271 @Override 272 protected String handleGetId() 273 { 274 return this.metaObject.refMofId(); 275 } 276 277 /** 278 * @see org.andromda.metafacades.uml.ModelElementFacade#hasExactStereotype(String) 279 */ 280 @Override 281 protected boolean handleHasExactStereotype(String stereotypeName) 282 { 283 return this.handleGetStereotypeNames().contains(StringUtils.trimToEmpty(stereotypeName)); 284 } 285 286 /** 287 * @see org.andromda.metafacades.uml.ModelElementFacade#getVisibility() 288 */ 289 @Override 290 protected String handleGetVisibility() 291 { 292 String visibility; 293 294 final VisibilityKind visibilityKind = metaObject.getVisibility(); 295 if (visibilityKind == null || VisibilityKindEnum.VK_PRIVATE.equals(visibilityKind)) 296 { 297 visibility = "private"; 298 } 299 else if (VisibilityKindEnum.VK_PROTECTED.equals(visibilityKind)) 300 { 301 visibility = "protected"; 302 } 303 else if (VisibilityKindEnum.VK_PUBLIC.equals(visibilityKind)) 304 { 305 visibility = "public"; 306 } 307 else // VisibilityKindEnum.VK_PACKAGE 308 { 309 visibility = "package"; 310 } 311 312 final TypeMappings languageMappings = this.getLanguageMappings(); 313 if (languageMappings != null) 314 { 315 visibility = languageMappings.getTo(visibility); 316 } 317 318 return visibility; 319 } 320 321 /** 322 * @see org.andromda.metafacades.uml.ModelElementFacade#getStereotypeNames() 323 */ 324 @Override 325 protected Collection<String> handleGetStereotypeNames() 326 { 327 Collection<String> stereotypeNames = new ArrayList<String>(); 328 329 Collection<ModelElement> stereotypes = metaObject.getStereotype(); 330 for (final ModelElement stereotype : stereotypes) 331 { 332 if (stereotype != null) 333 { 334 stereotypeNames.add(StringUtils.trimToEmpty(stereotype.getName())); 335 } 336 } 337 return stereotypeNames; 338 } 339 340 /** 341 * @see org.andromda.metafacades.uml.ModelElementFacade#getFullyQualifiedNamePath() 342 */ 343 @Override 344 protected String handleGetFullyQualifiedNamePath() 345 { 346 return StringUtils.replace( 347 this.handleGetFullyQualifiedName(), 348 String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR)), 349 "/"); 350 } 351 352 /** 353 * @see org.andromda.metafacades.uml.ModelElementFacade#getPackagePath() 354 */ 355 @Override 356 protected String handleGetPackagePath() 357 { 358 return StringUtils.replace( 359 this.handleGetPackageName(), 360 String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR)), 361 "/"); 362 } 363 364 /** 365 * @see org.andromda.metafacades.uml.ModelElementFacade#getDocumentation(String) 366 */ 367 @Override 368 protected String handleGetDocumentation(String indent) 369 { 370 return getDocumentation( 371 indent, 372 100 - indent.length()); 373 } 374 375 /** 376 * @see org.andromda.metafacades.uml.ModelElementFacade#getDocumentation(String, int) 377 */ 378 @Override 379 protected String handleGetDocumentation( 380 String indent, 381 int lineLength) 382 { 383 return getDocumentation( 384 indent, 385 lineLength, 386 true); 387 } 388 389 /** 390 * @see org.andromda.metafacades.uml.ModelElementFacade#getDocumentation(String, int, boolean) 391 */ 392 @Override 393 protected String handleGetDocumentation( 394 String indent, 395 int lineLength, 396 boolean htmlStyle) 397 { 398 final StringBuilder documentation = new StringBuilder(); 399 400 if (lineLength < 1) 401 { 402 lineLength = Integer.MAX_VALUE; 403 } 404 405 final Collection<Comment> comments = this.metaObject.getComment(); 406 if (comments != null && !comments.isEmpty()) 407 { 408 for (Comment comment : comments) 409 { 410 String commentString = StringUtils.trimToEmpty(comment.getBody()); 411 412 // if there isn't anything in the body, try the name 413 if (StringUtils.isBlank(commentString)) 414 { 415 commentString = StringUtils.trimToEmpty(comment.getName()); 416 } 417 documentation.append(StringUtils.trimToEmpty(commentString)); 418 documentation.append(SystemUtils.LINE_SEPARATOR); 419 } 420 } 421 422 // if there still isn't anything, try a tagged value 423 if (StringUtils.isBlank(documentation.toString())) 424 { 425 documentation.append( 426 StringUtils.trimToEmpty((String)this.findTaggedValue(UMLProfile.TAGGEDVALUE_DOCUMENTATION))); 427 } 428 // Add toDoTag if doc is empty: make modelers do the documentation. 429 if (StringUtils.isEmpty(documentation.toString())) 430 { 431 if (Boolean.valueOf((String)this.getConfiguredProperty(UMLMetafacadeProperties.TODO_FOR_MISSING_DOCUMENTATION))) 432 { 433 String todoTag = (String)this.getConfiguredProperty(UMLMetafacadeProperties.TODO_TAG); 434 documentation.append(todoTag).append(": Model Documentation for " + this.handleGetFullyQualifiedName()); 435 } 436 } 437 438 // Only add paragraph tags if doc is not empty 439 String rtn = StringUtilsHelper.format( 440 StringUtils.trimToEmpty(documentation.toString()), 441 indent, 442 lineLength, 443 htmlStyle); 444 445 return rtn; 446 } 447 448 /** 449 * If documentation is present, i.e. to add toDoTag or skip a line if not 450 * @return true is documentation comment or Documentation stereotype is present 451 * @see org.andromda.metafacades.uml.ModelElementFacade#isDocumentationPresent() 452 */ 453 @Override 454 protected boolean handleIsDocumentationPresent() 455 { 456 boolean rtn = false; 457 final Collection<Comment> comments = this.metaObject.getComment(); 458 if (comments != null && !comments.isEmpty()) 459 { 460 for (Comment comment : comments) 461 { 462 // if there isn't anything in the body, try the name 463 if (StringUtils.isNotBlank(comment.getBody())|| StringUtils.isNotBlank(comment.getName())) 464 { 465 rtn = true; 466 break; 467 } 468 } 469 } 470 471 if (!rtn && StringUtils.isNotBlank((String)this.findTaggedValue(UMLProfile.TAGGEDVALUE_DOCUMENTATION))) 472 { 473 rtn = true; 474 } 475 476 return rtn; 477 } 478 479 /** 480 * @return NOT IMPLEMENTED: UML2 only 481 * @see org.andromda.metafacades.uml.ModelElementFacade#getLabel() 482 */ 483 protected String handleGetLabel() 484 { 485 return null; 486 } 487 488 /** 489 * @return NOT IMPLEMENTED: UML2 only 490 * @see org.andromda.metafacades.uml.ModelElementFacade#getKeywords() 491 */ 492 protected Collection<String> handleGetKeywords() 493 { 494 return new ArrayList<String>(); 495 } 496 497 /* 498 * @return NOT IMPLEMENTED: UML2 only 499 * @see org.andromda.metafacades.uml.ModelElementFacade#getModelNamespace() 500 protected ModelElementFacade handleGetModelNamespace() 501 { 502 return null; 503 } 504 */ 505 506 /* 507 * @return NOT IMPLEMENTED: UML2 only 508 * @see org.andromda.metafacades.uml.ModelElementFacade#getModelNamespace() 509 protected ClassifierFacade handleGetOwner() 510 { 511 return null; 512 } 513 */ 514 515 /** 516 * @return NOT IMPLEMENTED: UML2 only 517 * @see org.andromda.metafacades.uml.ModelElementFacade#getQualifiedName() 518 */ 519 protected String handleGetQualifiedName() 520 { 521 return null; 522 } 523 524 /** 525 * @param keyword hasExactStereotype(keyword) 526 * @return hasExactStereotype(keyword) 527 * @see org.andromda.metafacades.uml.ModelElementFacade#getQualifiedName() 528 */ 529 protected boolean handleHasKeyword(String keyword) 530 { 531 return this.handleHasExactStereotype(keyword); 532 } 533 534 /** 535 * @see org.andromda.metafacades.uml.ModelElementFacade#getName() 536 */ 537 @Override 538 protected String handleGetName() 539 { 540 String name=metaObject.getName(); 541 542 if(name != null) 543 { 544 String nameMask = null; 545 try 546 { 547 nameMask = String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.MODEL_ELEMENT_NAME_MASK)); 548 } 549 catch (Exception ignore) 550 { 551 logger.warn("modelElementNameMask not found in " + this.toString()); 552 nameMask = "none"; 553 } 554 name = NameMasker.mask(name, nameMask); 555 } 556 557 return name; 558 } 559 560 /** 561 * Gets the array suffix from the configured metafacade properties. 562 * 563 * @return the array suffix. 564 */ 565 protected String getArraySuffix() 566 { 567 return String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.ARRAY_NAME_SUFFIX)); 568 } 569 570 /** 571 * @see org.andromda.metafacades.uml.ModelElementFacade#getLanguageMappings() 572 */ 573 @Override 574 protected TypeMappings handleGetLanguageMappings() 575 { 576 final String propertyName = UMLMetafacadeProperties.LANGUAGE_MAPPINGS_URI; 577 Object property = this.getConfiguredProperty(propertyName); 578 TypeMappings mappings = null; 579 String uri; 580 if (property instanceof String) 581 { 582 uri = (String)property; 583 try 584 { 585 mappings = TypeMappings.getInstance(uri); 586 mappings.setArraySuffix(this.getArraySuffix()); 587 this.setProperty( 588 propertyName, 589 mappings); 590 } 591 catch (Throwable throwable) 592 { 593 final String message = "Error getting '" + propertyName + "' --> '" + uri + '\''; 594 logger.error( 595 message, 596 throwable); 597 598 // don't throw the exception 599 } 600 } 601 else 602 { 603 mappings = (TypeMappings)property; 604 } 605 return mappings; 606 } 607 608 /* 609 * UML2 Only 610 * @see org.andromda.metafacades.uml.ModelElementFacade#getOwnedMembers() 611 protected Collection<ModelElementFacade> handleGetOwnedElements() 612 { 613 return new ArrayList<ModelElementFacade>(); 614 } 615 */ 616 617 /** 618 * @return Feature owner, or namespace 619 * @see org.andromda.metafacades.uml.ModelElementFacade#getPackage() 620 */ 621 //@Override 622 protected Object handleGetOwner() 623 { 624 if (this.metaObject instanceof Feature) 625 { 626 Feature feature = (Feature)this.metaObject; 627 return feature.getOwner(); 628 } 629 return metaObject.getNamespace(); 630 } 631 632 /** 633 * @return Collection of Features or Namespace elements 634 * @see org.andromda.metafacades.uml.ModelElementFacade#getPackage() 635 */ 636 //@Override 637 protected Collection handleGetOwnedElements() 638 { 639 if (this.metaObject instanceof Classifier) 640 { 641 Classifier classifier = (Classifier)this.metaObject; 642 return classifier.getFeature(); 643 } 644 if (this.metaObject instanceof Namespace) 645 { 646 Namespace namespace = (Namespace)this.metaObject; 647 return namespace.getOwnedElement(); 648 } 649 return null; 650 } 651 652 /** 653 * @see org.andromda.metafacades.uml.ModelElementFacade#getPackage() 654 */ 655 @Override 656 protected Namespace handleGetPackage() 657 { 658 return metaObject.getNamespace(); 659 } 660 661 /** 662 * @see org.andromda.metafacades.uml.ModelElementFacade#getRootPackage() 663 */ 664 @Override 665 protected UmlPackage handleGetRootPackage() 666 { 667 return UML14MetafacadeUtils.getRootPackage(); 668 } 669 670 /** 671 * @see org.andromda.metafacades.uml.ModelElementFacade#getSourceDependencies() 672 */ 673 @Override 674 protected Collection<DependencyFacade> handleGetSourceDependencies() 675 { 676 Collection<DependencyFacade> dependencies = new ArrayList(); 677 Collection<DependencyFacade> clientDependencies = 678 UML14MetafacadeUtils.getCorePackage().getAClientClientDependency().getClientDependency(this.metaObject); 679 if (clientDependencies != null) 680 { 681 dependencies.addAll(clientDependencies); 682 } 683 CollectionUtils.filter( 684 dependencies, 685 new Predicate() 686 { 687 public boolean evaluate(Object object) 688 { 689 return (object instanceof Dependency) && !(object instanceof Abstraction); 690 } 691 }); 692 return dependencies; 693 } 694 695 /** 696 * @see org.andromda.metafacades.uml.ModelElementFacade#getTargetDependencies() 697 */ 698 @Override 699 protected Collection<DependencyFacade> handleGetTargetDependencies() 700 { 701 Collection<DependencyFacade> dependencies = new ArrayList(); 702 Collection<DependencyFacade> supplierDependencies = 703 UML14MetafacadeUtils.getCorePackage().getASupplierSupplierDependency().getSupplierDependency( 704 this.metaObject); 705 if (supplierDependencies != null) 706 { 707 dependencies.addAll(supplierDependencies); 708 } 709 CollectionUtils.filter( 710 dependencies, 711 new Predicate() 712 { 713 public boolean evaluate(Object object) 714 { 715 return (object instanceof Dependency) && !(object instanceof Abstraction); 716 } 717 }); 718 return dependencies; 719 } 720 721 /** 722 * @see org.andromda.metafacades.uml.ModelElementFacade#getStereotypes() 723 */ 724 @Override 725 protected Collection<StereotypeFacade> handleGetStereotypes() 726 { 727 return this.metaObject.getStereotype(); 728 } 729 730 /** 731 * @see org.andromda.metafacades.uml.ModelElementFacade#getModel() 732 */ 733 @Override 734 protected Object handleGetModel() 735 { 736 return MetafacadeFactory.getInstance().getModel().getModel(); 737 } 738 739 /** 740 * @see org.andromda.metafacades.uml.ModelElementFacade#getConstraints() 741 */ 742 @Override 743 protected Collection<ConstraintFacade> handleGetConstraints() 744 { 745 return this.metaObject.getConstraint(); 746 } 747 748 /** 749 * @see org.andromda.metafacades.uml.ModelElementFacade#getConstraints(String) 750 */ 751 @Override 752 protected Collection<ConstraintFacade> handleGetConstraints(final String kind) 753 { 754 return CollectionUtils.select( 755 getConstraints(), 756 new Predicate() 757 { 758 public boolean evaluate(Object object) 759 { 760 if (object instanceof ConstraintFacade) 761 { 762 ConstraintFacade constraint = (ConstraintFacade)object; 763 return ((ExpressionKinds.BODY.equals(kind) && constraint.isBodyExpression()) || 764 (ExpressionKinds.DEF.equals(kind) && constraint.isDefinition()) || 765 (ExpressionKinds.INV.equals(kind) && constraint.isInvariant()) || 766 (ExpressionKinds.PRE.equals(kind) && constraint.isPreCondition()) || 767 (ExpressionKinds.POST.equals(kind) && constraint.isPostCondition())); 768 } 769 return false; 770 } 771 }); 772 } 773 774 /** 775 * @see org.andromda.metafacades.uml.ModelElementFacade#translateConstraint(String, String) 776 */ 777 @Override 778 protected String handleTranslateConstraint( 779 final String name, 780 String translation) 781 { 782 String translatedExpression = ""; 783 ConstraintFacade constraint = 784 (ConstraintFacade)CollectionUtils.find( 785 this.getConstraints(), 786 new Predicate() 787 { 788 public boolean evaluate(Object object) 789 { 790 ConstraintFacade constraint = (ConstraintFacade)object; 791 return StringUtils.trimToEmpty(constraint.getName()).equals(StringUtils.trimToEmpty(name)); 792 } 793 }); 794 795 if (constraint != null) 796 { 797 translatedExpression = constraint.getTranslation(translation); 798 } 799 return translatedExpression; 800 } 801 802 /** 803 * @see org.andromda.metafacades.uml.ModelElementFacade#translateConstraints(String) 804 */ 805 @Override 806 protected String[] handleTranslateConstraints(String translation) 807 { 808 return this.translateConstraints( 809 this.getConstraints(), 810 translation); 811 } 812 813 /** 814 * Private helper that translates all the expressions contained in the <code>constraints</code>, and returns an 815 * array of the translated expressions. 816 * 817 * @param constraints the constraints to translate 818 * @param translation the translation to translate <code>to</code>. 819 * @return String[] the translated expressions, or null if no constraints were found 820 */ 821 private String[] translateConstraints( 822 Collection<ConstraintFacade> constraints, 823 String translation) 824 { 825 String[] translatedExpressions = null; 826 if (constraints != null && !constraints.isEmpty()) 827 { 828 translatedExpressions = new String[constraints.size()]; 829 Iterator<ConstraintFacade> constraintIt = constraints.iterator(); 830 for (int ctr = 0; constraintIt.hasNext(); ctr++) 831 { 832 ConstraintFacade constraint = constraintIt.next(); 833 translatedExpressions[ctr] = constraint.getTranslation(translation); 834 } 835 } 836 return translatedExpressions; 837 } 838 839 /** 840 * @see org.andromda.metafacades.uml.ModelElementFacade#translateConstraints(String, String) 841 */ 842 @Override 843 protected String[] handleTranslateConstraints( 844 final String kind, 845 String translation) 846 { 847 Collection<ConstraintFacade> constraints = this.getConstraints(); 848 CollectionUtils.filter( 849 constraints, 850 new Predicate() 851 { 852 public boolean evaluate(Object object) 853 { 854 ConstraintFacade constraint = (ConstraintFacade)object; 855 return UMLMetafacadeUtils.isConstraintKind( 856 constraint.getBody(), 857 kind); 858 } 859 }); 860 return this.translateConstraints( 861 constraints, 862 translation); 863 } 864 865 /** 866 * @see org.andromda.metafacades.uml.ModelElementFacade#getStateMachineContext() 867 */ 868 @Override 869 protected StateMachine handleGetStateMachineContext() 870 { 871 StateMachine machineContext = null; 872 873 final Collection<StateMachine> machines = UML14MetafacadeUtils.getModel().getStateMachines().getStateMachine().refAllOfType(); 874 for (final StateMachine machine : machines) 875 { 876 final ModelElement contextElement = machine.getContext(); 877 if (metaObject.equals(contextElement)) 878 { 879 machineContext = machine; 880 } 881 } 882 883 return machineContext; 884 } 885 886 /** 887 * @see org.andromda.metafacades.uml.ModelElementFacade#getTemplateParameters() 888 */ 889 @Override 890 protected Collection handleGetTemplateParameters() 891 { 892 return metaObject.getTemplateParameter(); 893 } 894 895 /** 896 * @see org.andromda.core.metafacade.MetafacadeBase#getValidationName() 897 */ 898 public String getValidationName() 899 { 900 final StringBuilder validationName = new StringBuilder(); 901 final String seperator = MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR; 902 for (ModelElement namespace = metaObject.getNamespace(); namespace != null; 903 namespace = namespace.getNamespace()) 904 { 905 if (validationName.length() == 0) 906 { 907 validationName.append(namespace.getName()); 908 } 909 else 910 { 911 validationName.insert( 912 0, 913 seperator); 914 validationName.insert( 915 0, 916 namespace.getName()); 917 } 918 } 919 if (validationName.length() > 0) 920 { 921 validationName.append(seperator); 922 } 923 if (StringUtils.isNotBlank(this.handleGetName())) 924 { 925 validationName.append(this.handleGetName()); 926 } 927 else 928 { 929 validationName.append(this.getConfiguredProperty(UMLMetafacadeProperties.UNDEFINED_NAME)); 930 } 931 return validationName.toString(); 932 } 933 934 /** 935 * @see org.andromda.metafacades.uml.ModelElementFacade#isConstraintsPresent() 936 */ 937 @Override 938 protected boolean handleIsConstraintsPresent() 939 { 940 return this.getConstraints() != null && !this.getConstraints().isEmpty(); 941 } 942 943 /** 944 * @see org.andromda.metafacades.uml.ModelElementFacade#isBindingDependenciesPresent() 945 */ 946 @Override 947 protected boolean handleIsBindingDependenciesPresent() 948 { 949 Collection<DependencyFacade> dependencies = this.getSourceDependencies(); 950 CollectionUtils.filter( 951 dependencies, 952 new Predicate() 953 { 954 public boolean evaluate(Object object) 955 { 956 return object instanceof BindingFacade; 957 } 958 }); 959 return !dependencies.isEmpty(); 960 } 961 962 /** 963 * @see org.andromda.metafacades.uml.ModelElementFacade#isReservedWord() 964 */ 965 @Override 966 protected boolean handleIsReservedWord() 967 { 968 return UMLMetafacadeUtils.isReservedWord(metaObject.getName()); 969 } 970 971 /** 972 * @see org.andromda.metafacades.uml.ModelElementFacade#isTemplateParametersPresent() 973 */ 974 @Override 975 protected boolean handleIsTemplateParametersPresent() 976 { 977 final Collection<TemplateParameterFacade> params = this.getTemplateParameters(); 978 return params != null && !params.isEmpty(); 979 } 980 981 /** 982 * @see org.andromda.metafacades.uml.ModelElementFacade#copyTaggedValues(org.andromda.metafacades.uml.ModelElementFacade) 983 */ 984 @Override 985 protected void handleCopyTaggedValues(ModelElementFacade element) 986 { 987 org.omg.uml.foundation.core.ModelElement elementMetaObject; 988 if (element instanceof MetafacadeBase) 989 { 990 final MetafacadeBase metafacade = (MetafacadeBase)element; 991 final Object metaObject = metafacade.getMetaObject(); 992 if (metaObject instanceof ModelElement) 993 { 994 elementMetaObject = (ModelElement)metaObject; 995 this.metaObject.getTaggedValue().addAll(elementMetaObject.getTaggedValue()); 996 } 997 } 998 } 999 1000 /** 1001 * @see org.andromda.metafacades.uml.ModelElementFacade#getTemplateParameter(String) 1002 */ 1003 @Override 1004 protected TemplateParameterFacade handleGetTemplateParameter(String parameterName) 1005 { 1006 TemplateParameterFacade templateParameter = null; 1007 if (StringUtils.isNotBlank(parameterName)) 1008 { 1009 parameterName = StringUtils.trimToEmpty(parameterName); 1010 final Collection<TemplateParameterFacade> parameters = this.getTemplateParameters(); 1011 if (parameters != null && !parameters.isEmpty()) 1012 { 1013 for (final TemplateParameterFacade currentTemplateParameter : parameters) 1014 { 1015 if (currentTemplateParameter.getParameter() != null) 1016 { 1017 final ModelElementFacade parameter = currentTemplateParameter.getParameter(); 1018 1019 // there should not be two template parameters with the same parameter name, but nothing 1020 // prevents the model from allowing that. So return the first instance if found. 1021 if (parameterName.equals(parameter.getName())) 1022 { 1023 templateParameter = currentTemplateParameter; 1024 break; 1025 } 1026 } 1027 } 1028 } 1029 } 1030 1031 return templateParameter; 1032 } 1033 1034 /** 1035 * {@inheritDoc} 1036 */ 1037 @Override 1038 protected String handleGetBindedFullyQualifiedName(ModelElementFacade bindedElement) 1039 { 1040 // This cast is not safe yet, but will be as soon as the filtering will be done 1041 @SuppressWarnings("unchecked") 1042 final Collection<BindingFacade> bindingFacades = new ArrayList(bindedElement.getSourceDependencies()); 1043 CollectionUtils.filter( 1044 bindingFacades, 1045 new Predicate() 1046 { 1047 public boolean evaluate(Object object) 1048 { 1049 return object instanceof BindingFacade; 1050 } 1051 }); 1052 return handleGetBindedFullyQualifiedName(false, bindingFacades); 1053 } 1054 1055 /** 1056 * <p> 1057 * Returns the fully qualified name of the model element. The fully 1058 * qualified name includes complete package qualified name of the 1059 * underlying model element. If modelName is true, then the 1060 * original name of the model element (the name contained within 1061 * the model) will be the name returned, otherwise a name from a 1062 * language mapping will be returned. Moreover use the given collection 1063 * of {@link BindingFacade} to bind templates parameters to their actual 1064 * type. 1065 * </p> 1066 * @param modelName boolean 1067 * @param bindingFacades Collection 1068 * @return String 1069 */ 1070 private String handleGetBindedFullyQualifiedName(boolean modelName, Collection<BindingFacade> bindingFacades) 1071 { 1072 String fullName = StringUtils.trimToEmpty(this.handleGetName()); 1073 final String packageName = this.handleGetPackageName(true); 1074 final String metafacadeNamespaceScopeOperator = MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR; 1075 if (StringUtils.isNotBlank(packageName)) 1076 { 1077 fullName = packageName + metafacadeNamespaceScopeOperator + fullName; 1078 } 1079 if (!modelName) 1080 { 1081 final TypeMappings languageMappings = this.getLanguageMappings(); 1082 if (languageMappings != null) 1083 { 1084 fullName = StringUtils.trimToEmpty(languageMappings.getTo(fullName)); 1085 1086 // now replace the metafacade scope operators 1087 // with the mapped scope operators 1088 final String namespaceScopeOperator = 1089 String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR)); 1090 fullName = StringUtils.replace( 1091 fullName, 1092 metafacadeNamespaceScopeOperator, 1093 namespaceScopeOperator); 1094 } 1095 } 1096 1097 if (this.isTemplateParametersPresent() && 1098 BooleanUtils.toBoolean( 1099 ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING)))) 1100 { 1101 // Retrieve all template parameters 1102 final Collection<TemplateParameterFacade> templateParameters = this.getTemplateParameters(); 1103 1104 // Construct a map of the TemplateParameterFacade to replace 1105 Map<TemplateParameterFacade, ModelElementFacade> bindedParameters = new HashMap<TemplateParameterFacade, ModelElementFacade>(); 1106 for(BindingFacade bindingFacade : bindingFacades) 1107 { 1108 ModelElementFacade targetElement = bindingFacade.getTargetElement(); 1109 if(targetElement instanceof RedefinableTemplateSignatureFacade) 1110 { 1111 targetElement = ((RedefinableTemplateSignatureFacade) targetElement).getClassifier(); 1112 } 1113 if(this.equals(targetElement)) 1114 { 1115 final Collection<TemplateArgumentFacade> arguments = bindingFacade.getArguments(); 1116 if(arguments.size() != getTemplateParameters().size()) 1117 { 1118 throw new IllegalStateException("The size of the arguments of the BindingFacace must be equals to the size of the TemplateParameter collection of this element."); 1119 } 1120 1121 Iterator<TemplateParameterFacade> templateParametersIterator = templateParameters.iterator(); 1122 Iterator<TemplateArgumentFacade> templateArgumentsIterator = arguments.iterator(); 1123 1124 while(templateParametersIterator.hasNext()) 1125 { 1126 final TemplateParameterFacade templateParameter = templateParametersIterator.next(); 1127 final TemplateArgumentFacade templateArgument = templateArgumentsIterator.next(); 1128 bindedParameters.put(templateParameter, templateArgument.getElement()); 1129 } 1130 } 1131 } 1132 if(bindedParameters.isEmpty()) 1133 { 1134 for(TemplateParameterFacade templateParameterFacade : templateParameters) 1135 { 1136 bindedParameters.put(templateParameterFacade, templateParameterFacade.getParameter()); 1137 } 1138 } 1139 1140 // we'll be constructing the parameter list in this buffer 1141 // add the name we've constructed so far 1142 final StringBuilder buffer = new StringBuilder(fullName + '<'); 1143 1144 // loop over the parameters, we are so to have at least one (see 1145 // outer condition) 1146 for (final Iterator<TemplateParameterFacade> parameterIterator = templateParameters.iterator(); parameterIterator.hasNext();) 1147 { 1148 final ModelElementFacade modelElement = bindedParameters.get(parameterIterator.next()); 1149 1150 // TODO: UML14 returns ParameterFacade, UML2 returns ModelElementFacade, so types are wrong from fullyQualifiedName 1151 // Mapping from UML2 should return ParameterFacade, with a getType method. 1152 // Add TemplateParameterFacade.getType method - need to access this in vsl templates. 1153 if (modelElement instanceof ParameterFacade) 1154 { 1155 buffer.append(((ParameterFacade)modelElement).getType().getFullyQualifiedName()); 1156 } 1157 else 1158 { 1159 buffer.append(modelElement.getFullyQualifiedName()); 1160 } 1161 1162 if (parameterIterator.hasNext()) 1163 { 1164 buffer.append(", "); 1165 } 1166 } 1167 1168 // we're finished listing the parameters 1169 buffer.append('>'); 1170 1171 // we have constructed the full name in the buffer 1172 fullName = buffer.toString(); 1173 } 1174 1175 return fullName; 1176 } 1177 1178 // Valid identifier starts with alphanum or _$ and contains only alphanum or _$ or digits 1179 private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("[a-zA-Z_$][a-zA-Z\\d_$]*"); 1180 /** 1181 * Return true if name matches the pattern [a-zA-Z_$][a-zA-Z\\d_$]* 1182 * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleIsValidIdentifierName() 1183 */ 1184 @Override 1185 protected boolean handleIsValidIdentifierName() 1186 { 1187 final String name = this.handleGetName(); 1188 return IDENTIFIER_PATTERN.matcher(name).matches(); 1189 } 1190}