001package org.andromda.metafacades.uml14; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Comparator; 006import java.util.Iterator; 007import java.util.LinkedHashSet; 008import java.util.List; 009import java.util.Set; 010import java.util.TreeSet; 011import org.andromda.metafacades.uml.ActorFacade; 012import org.andromda.metafacades.uml.AssociationEndFacade; 013import org.andromda.metafacades.uml.AttributeFacade; 014import org.andromda.metafacades.uml.ClassifierFacade; 015import org.andromda.metafacades.uml.DependencyFacade; 016import org.andromda.metafacades.uml.Entity; 017import org.andromda.metafacades.uml.EntityAttribute; 018import org.andromda.metafacades.uml.GeneralizableElementFacade; 019import org.andromda.metafacades.uml.ManageableEntity; 020import org.andromda.metafacades.uml.ModelElementFacade; 021import org.andromda.metafacades.uml.UMLMetafacadeProperties; 022import org.andromda.metafacades.uml.UMLProfile; 023import org.andromda.utils.StringUtilsHelper; 024import org.apache.commons.lang.ObjectUtils; 025import org.apache.commons.lang.StringUtils; 026 027/** 028 * MetafacadeLogic implementation for org.andromda.metafacades.uml.ManageableEntity. 029 * 030 * @see org.andromda.metafacades.uml.ManageableEntity 031 * @author Bob Fields 032 */ 033public class ManageableEntityLogicImpl 034 extends ManageableEntityLogic 035{ 036 private static final long serialVersionUID = -1239526138513293700L; 037 038 /** 039 * @param metaObject 040 * @param context 041 */ 042 public ManageableEntityLogicImpl(Object metaObject, String context) 043 { 044 super(metaObject, context); 045 } 046 047 /** 048 * @return the configured property denoting the character sequence to use for the separation of namespaces 049 */ 050 private String getNamespaceSeparator() 051 { 052 return (String)getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR); 053 } 054 055 /** 056 * @return manageablePackageName 057 * @see org.andromda.metafacades.uml.ManageableEntity#getManageablePackageName() 058 */ 059 protected String handleGetManageablePackageName() 060 { 061 String manageablePackageName = ""; 062 063 final String parentPackage = super.getPackageName(); 064 if (StringUtils.isNotBlank(parentPackage)) 065 { 066 manageablePackageName = parentPackage; 067 } 068 069 final Object suffix = getConfiguredProperty(UMLMetafacadeProperties.MANAGEABLE_PACKAGE_NAME_SUFFIX); 070 if (suffix != null && StringUtils.isNotBlank(suffix.toString())) 071 { 072 manageablePackageName += this.getNamespaceSeparator() + suffix; 073 } 074 075 return manageablePackageName; 076 } 077 078 /** 079 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageablePackagePath() 080 */ 081 protected String handleGetManageablePackagePath() 082 { 083 return StringUtils.replace(this.getManageablePackageName(), this.getNamespaceSeparator(), "/"); 084 } 085 086 /** 087 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableAssociationEnds() 088 */ 089 protected List handleGetManageableAssociationEnds() 090 { 091 final Set manageableAssociationEnds = new LinkedHashSet();// linked hashset to guarantee ordering wo/ duplicates 092 collectAssociationEnds(manageableAssociationEnds, this); 093 return new ArrayList(manageableAssociationEnds); 094 } 095 096 /** 097 * This method recursively collects all association ends to which a manageable entity would need to navigate 098 * 099 * @param manageableAssociationEnds the collection in which to collect the association ends 100 * @param entity the entity from which to recursively gather the association ends 101 */ 102 private static void collectAssociationEnds(Collection<AssociationEndFacade> manageableAssociationEnds, ManageableEntity entity) 103 { 104 final Collection<AssociationEndFacade> associationEnds = entity.getAssociationEnds(); 105 for (final Iterator<AssociationEndFacade> associationEndIterator = associationEnds.iterator(); associationEndIterator.hasNext();) 106 { 107 final AssociationEndFacade associationEnd = associationEndIterator.next(); 108 final AssociationEndFacade otherEnd = associationEnd.getOtherEnd(); 109 110 if (otherEnd.isNavigable() && otherEnd.getType() instanceof Entity) 111 { 112 manageableAssociationEnds.add(otherEnd); 113 } 114 } 115 116 // retrieve all association ends for all parents (recursively) 117 final Collection<GeneralizableElementFacade> parentEntities = entity.getAllGeneralizations(); 118 for (final Iterator<GeneralizableElementFacade> parentEntityIterator = parentEntities.iterator(); parentEntityIterator.hasNext();) 119 { 120 final Object parentEntityObject = parentEntityIterator.next(); 121 if (parentEntityObject instanceof ManageableEntity) 122 { 123 collectAssociationEnds(manageableAssociationEnds, (ManageableEntity)parentEntityObject); 124 } 125 } 126 } 127 128 /** 129 * @return !this.isAbstract() 130 * @see org.andromda.metafacades.uml.ManageableEntity#isCreate() 131 */ 132 protected boolean handleIsCreate() 133 { 134 return !this.isAbstract(); 135 } 136 137 /** 138 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableServiceName() 139 */ 140 protected String handleGetManageableServiceName() 141 { 142 return getName() + "ManageableService"; 143 } 144 145 /** 146 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableServiceFullPath() 147 */ 148 protected String handleGetManageableServiceFullPath() 149 { 150 return '/' + StringUtils.replace( 151 getFullyQualifiedManageableServiceName(), 152 getNamespaceSeparator(), 153 "/"); 154 } 155 156 /** 157 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetFullyQualifiedManageableServiceName() 158 */ 159 protected String handleGetFullyQualifiedManageableServiceName() 160 { 161 return this.getManageablePackageName() + this.getNamespaceSeparator() + getManageableServiceName(); 162 } 163 164 /** 165 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableServiceAccessorCall() 166 */ 167 protected String handleGetManageableServiceAccessorCall() 168 { 169 final String property = UMLMetafacadeProperties.MANAGEABLE_SERVICE_ACCESSOR_PATTERN; 170 final String accessorImplementation = 171 this.isConfiguredProperty(property) ? ObjectUtils.toString(this.getConfiguredProperty(property)) 172 : "${application.package}.ManageableServiceLocator.instance().get{1}()"; 173 return accessorImplementation.replaceAll( 174 "\\{0\\}", 175 getManageablePackageName()).replaceAll( 176 "\\{1\\}", 177 getManageableServiceName()); 178 } 179 180 /** 181 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleIsRead() 182 */ 183 protected boolean handleIsRead() 184 { 185 return true; 186 } 187 188 /** 189 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleIsUpdate() 190 */ 191 protected boolean handleIsUpdate() 192 { 193 return this.getManageableIdentifier() != null; // TODO Implement handleIsUpdate 194 } 195 196 /** 197 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleIsDelete() 198 */ 199 protected boolean handleIsDelete() 200 { 201 return this.getManageableIdentifier() != null; // TODO Implement handleIsDelete 202 } 203 204 /** 205 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableAttributes() 206 */ 207 protected List handleGetManageableAttributes() 208 { 209 return new ArrayList(this.getAttributes(true)); 210 } 211 212 /** 213 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableIdentifier() 214 */ 215 protected Object handleGetManageableIdentifier() 216 { 217 return this.getIdentifiers(true).iterator().next(); 218 } 219 220 /** 221 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableMembers() 222 */ 223 protected List handleGetManageableMembers() 224 { 225 final List criteria = new ArrayList(); 226 criteria.addAll(this.getManageableAttributes()); 227 criteria.addAll(this.getManageableAssociationEnds()); 228 return criteria; 229 } 230 231 private enum ListType 232 { 233 PRIMITIVE, 234 WRAPPER; 235 } 236 237 private String createListWithManageableMembers(ListType listType) 238 { 239 final StringBuilder buffer = new StringBuilder(); 240 241 final List attributes = this.getManageableAttributes(); 242 for (int i = 0; i < attributes.size(); i++) 243 { 244 if (buffer.length() > 0) 245 { 246 buffer.append(", "); 247 } 248 249 final AttributeFacade attribute = (AttributeFacade)attributes.get(i); 250 final ClassifierFacade type = attribute.getType(); 251 if (type != null) 252 { 253 if(ListType.PRIMITIVE.equals(listType)) 254 { 255 buffer.append(type.getFullyQualifiedName()); 256 buffer.append(' '); 257 } 258 else if(ListType.WRAPPER.equals(listType)) 259 { 260 buffer.append(type.isPrimitive()? type.getWrapperName(): type.getFullyQualifiedName()); 261 buffer.append(' '); 262 } 263 buffer.append(attribute.getName()); 264 } 265 } 266 267 final List associationEnds = this.getManageableAssociationEnds(); 268 for (int i = 0; i < associationEnds.size(); i++) 269 { 270 final AssociationEndFacade associationEnd = (AssociationEndFacade)associationEnds.get(i); 271 final Entity entity = (Entity)associationEnd.getType(); 272 273 if(entity.isCompositeIdentifier()) 274 { 275 if (buffer.length() > 0) 276 { 277 buffer.append(", "); 278 } 279 if (listType != null) 280 { 281 buffer.append("Object"); 282 if (associationEnd.isMany()) 283 { 284 buffer.append("[]"); 285 } 286 buffer.append(' '); 287 } 288 buffer.append(associationEnd.getName()); 289 } 290 else 291 { 292 final Iterator<ModelElementFacade> identifierIterator = entity.getIdentifiers().iterator(); 293 if (identifierIterator.hasNext()) 294 { 295 final ModelElementFacade identifier = identifierIterator.next(); 296 if (identifier != null) 297 { 298 if (buffer.length() > 0) 299 { 300 buffer.append(", "); 301 } 302 303 ClassifierFacade type = null; 304 if (identifier instanceof AttributeFacade) 305 { 306 type = ((AttributeFacade)identifier).getType(); 307 } 308 else if (identifier instanceof AssociationEndFacade) 309 { 310 type = ((AssociationEndFacade)identifier).getType(); 311 } 312 313 if (type != null) 314 { 315 if (listType != null) 316 { 317 buffer.append(type.getFullyQualifiedName()); 318 if (associationEnd.isMany()) 319 { 320 buffer.append("[]"); 321 } 322 buffer.append(' '); 323 } 324 buffer.append(associationEnd.getName()); 325 } 326 } 327 } 328 } 329 } 330 331 return buffer.toString(); 332 } 333 334 /** 335 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleListManageableMembersWithWrapperTypes() 336 */ 337 protected String handleListManageableMembersWithWrapperTypes() 338 { 339 return createListWithManageableMembers(ListType.WRAPPER); 340 } 341 342 /** 343 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleListManageableMembers(boolean) 344 */ 345 protected String handleListManageableMembers(boolean withTypes) 346 { 347 return createListWithManageableMembers(withTypes? ListType.PRIMITIVE: null); 348 } 349 350 /** 351 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleIsManageable() 352 */ 353 protected boolean handleIsManageable() 354 { 355 return Boolean.valueOf((String)this.getConfiguredProperty( 356 UMLMetafacadeProperties.ENABLE_MANAGEABLE_ENTITIES)).booleanValue(); 357 } 358 359 /** 360 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetReferencingManageables() 361 */ 362 protected List handleGetReferencingManageables() 363 { 364 final Set referencingManageables = new LinkedHashSet(); 365 final Collection associationEnds = getAssociationEnds(); 366 for (final Iterator associationEndIterator = associationEnds.iterator(); associationEndIterator.hasNext();) 367 { 368 final AssociationEndFacade associationEnd = (AssociationEndFacade)associationEndIterator.next(); 369 370 if (associationEnd.isNavigable()) 371 { 372 if (associationEnd.isMany() || (associationEnd.isOne2One() && associationEnd.isChild())) 373 { 374 final Object otherEndType = associationEnd.getOtherEnd().getType(); 375 if (otherEndType instanceof Entity) 376 { 377 referencingManageables.add(otherEndType); 378 } 379 } 380 } 381 } 382 return new ArrayList(referencingManageables); 383 } 384 385 /** 386 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetDisplayAttribute() 387 */ 388 protected Object handleGetDisplayAttribute() 389 { 390 Object displayAttribute = null; 391 392 final Object taggedValueObject = findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_DISPLAY_NAME); 393 if (taggedValueObject != null) 394 { 395 displayAttribute = findAttribute(StringUtilsHelper.trimToEmpty(taggedValueObject.toString())); 396 } 397 398 final Collection attributes = getAttributes(true); 399 for (final Iterator attributeIterator = attributes.iterator(); 400 attributeIterator.hasNext() && displayAttribute == null;) 401 { 402 // TODO: UML2 migrated models automatically mark all * attributes as unique. Different display attributes are selected from UML14 and UML2 migrated models. 403 // This selects the first attribute that is unique as the display value. 404 final Object attribute = attributeIterator.next(); 405 if(attribute instanceof EntityAttribute)//can get attributes from ancestor classes 406 { 407 final EntityAttribute entityAttribute = (EntityAttribute)attribute; 408 if (entityAttribute.isUnique()) 409 { 410 displayAttribute = entityAttribute; 411 } 412 } 413 } 414 415 if (displayAttribute == null) 416 { 417 if (!getIdentifiers().isEmpty()) 418 { 419 displayAttribute = getIdentifiers().iterator().next(); 420 } 421 else if (!attributes.isEmpty()) 422 { 423 displayAttribute = attributes.iterator().next(); 424 } 425 } 426 427 return displayAttribute; 428 } 429 430 /** 431 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetUsers() 432 */ 433 protected List handleGetUsers() 434 { 435 final Set users = new LinkedHashSet(); 436 437 final Collection<DependencyFacade> dependencies = getTargetDependencies(); 438 for (final Iterator<DependencyFacade> dependencyIterator = dependencies.iterator(); dependencyIterator.hasNext();) 439 { 440 final DependencyFacade dependency = dependencyIterator.next(); 441 final Object dependencyObject = dependency.getSourceElement(); 442 443 if (!users.contains(dependencyObject) && dependencyObject instanceof ActorFacade) 444 { 445 collectActors((ActorFacade)dependencyObject, users); 446 } 447 } 448 449 return new ArrayList(users); 450 } 451 452 private void collectActors(ActorFacade actor, Collection actors) 453 { 454 if (!actors.contains(actor)) 455 { 456 actors.add(actor); 457 458 final Collection<ActorFacade> childActors = actor.getGeneralizedByActors(); 459 for (final Iterator<ActorFacade> iterator = childActors.iterator(); iterator.hasNext();) 460 { 461 final ActorFacade childActor = iterator.next(); 462 collectActors(childActor, actors); 463 } 464 } 465 } 466 467 /** 468 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetMaximumListSize() 469 */ 470 protected int handleGetMaximumListSize() 471 { 472 int maximumListSize; 473 474 final Object taggedValueObject = findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_MAXIMUM_LIST_SIZE); 475 if (taggedValueObject != null) 476 { 477 try 478 { 479 maximumListSize = Integer.parseInt(taggedValueObject.toString()); 480 } 481 catch (NumberFormatException e) 482 { 483 maximumListSize = internalDefaultMaximumListSize(); 484 } 485 } 486 else 487 { 488 maximumListSize = internalDefaultMaximumListSize(); 489 } 490 491 return maximumListSize; 492 } 493 494 private int internalDefaultMaximumListSize() 495 { 496 int maximumListSize; 497 498 try 499 { 500 maximumListSize = 501 Integer.parseInt((String)getConfiguredProperty(UMLMetafacadeProperties.PROPERTY_DEFAULT_MAX_LIST_SIZE)); 502 } 503 catch (NumberFormatException e1) 504 { 505 maximumListSize = -1; 506 } 507 508 return maximumListSize; 509 } 510 511 /** 512 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetPageSize() 513 */ 514 protected int handleGetPageSize() 515 { 516 int pageSize; 517 518 final Object taggedValueObject = findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_PAGE_SIZE); 519 if (taggedValueObject != null) 520 { 521 try 522 { 523 pageSize = Integer.parseInt(taggedValueObject.toString()); 524 } 525 catch (NumberFormatException e) 526 { 527 pageSize = internalDefaultPageSize(); 528 } 529 } 530 else 531 { 532 pageSize = internalDefaultPageSize(); 533 } 534 535 return pageSize; 536 } 537 538 private int internalDefaultPageSize() 539 { 540 int pageSize; 541 542 try 543 { 544 pageSize = 545 Integer.parseInt((String)getConfiguredProperty(UMLMetafacadeProperties.PROPERTY_DEFAULT_PAGE_SIZE)); 546 } 547 catch (NumberFormatException e1) 548 { 549 pageSize = 20; 550 } 551 552 return pageSize; 553 } 554 555 /** 556 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleIsResolveable() 557 */ 558 protected boolean handleIsResolveable() 559 { 560 boolean resolveable; 561 562 final Object taggedValueObject = findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_RESOLVEABLE); 563 if (taggedValueObject != null) 564 { 565 try 566 { 567 resolveable = Boolean.valueOf(taggedValueObject.toString()).booleanValue(); 568 } 569 catch (NumberFormatException e) 570 { 571 resolveable = internalDefaultResolveable(); 572 } 573 } 574 else 575 { 576 resolveable = internalDefaultResolveable(); 577 } 578 579 return resolveable; 580 } 581 582 private boolean internalDefaultResolveable() 583 { 584 boolean resolveable; 585 586 try 587 { 588 resolveable = 589 Boolean.valueOf((String)getConfiguredProperty(UMLMetafacadeProperties.PROPERTY_DEFAULT_RESOLVEABLE)) 590 .booleanValue(); 591 } 592 catch (NumberFormatException ex) 593 { 594 resolveable = true; 595 } 596 597 return resolveable; 598 } 599 600 /** 601 * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetAllManageables() 602 */ 603 protected List<ClassifierFacade> handleGetAllManageables() 604 { 605 final Set<ClassifierFacade> allManageableEntities = new TreeSet(new ManageableComparator()); 606 607 final Collection<ClassifierFacade> allClasses = getModel().getAllClasses(); 608 for (final Iterator<ClassifierFacade> classIterator = allClasses.iterator(); classIterator.hasNext();) 609 { 610 final ClassifierFacade classObject = classIterator.next(); 611 if (classObject instanceof ManageableEntity) 612 { 613 allManageableEntities.add(classObject); 614 } 615 } 616 617 return new ArrayList<ClassifierFacade>(allManageableEntities); 618 } 619 620 /** 621 * 622 */ 623 static final class ManageableComparator 624 implements Comparator 625 { 626 /** 627 * @see java.util.Comparator#compare(Object, Object) 628 */ 629 public int compare(Object left, Object right) 630 { 631 final ModelElementFacade leftEntity = (ModelElementFacade)left; 632 final ModelElementFacade rightEntity = (ModelElementFacade)right; 633 634 return leftEntity.getName().compareTo(rightEntity.getName()); 635 } 636 } 637}