View Javadoc
1   package org.andromda.metafacades.emf.uml22;
2   
3   import java.io.Serializable;
4   import java.util.ArrayList;
5   import java.util.Collection;
6   import java.util.Comparator;
7   import java.util.Iterator;
8   import java.util.LinkedHashSet;
9   import java.util.List;
10  import java.util.Set;
11  import java.util.TreeSet;
12  import org.andromda.metafacades.uml.ActorFacade;
13  import org.andromda.metafacades.uml.AssociationEndFacade;
14  import org.andromda.metafacades.uml.AttributeFacade;
15  import org.andromda.metafacades.uml.ClassifierFacade;
16  import org.andromda.metafacades.uml.DependencyFacade;
17  import org.andromda.metafacades.uml.Entity;
18  import org.andromda.metafacades.uml.EntityAssociationEnd;
19  import org.andromda.metafacades.uml.EntityAttribute;
20  import org.andromda.metafacades.uml.GeneralizableElementFacade;
21  import org.andromda.metafacades.uml.ManageableEntity;
22  import org.andromda.metafacades.uml.ManageableEntityAssociationEnd;
23  import org.andromda.metafacades.uml.ManageableEntityAttribute;
24  import org.andromda.metafacades.uml.ModelElementFacade;
25  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
26  import org.andromda.metafacades.uml.UMLProfile;
27  import org.apache.commons.lang.ObjectUtils;
28  import org.apache.commons.lang.StringUtils;
29  
30  /**
31   * MetafacadeLogic implementation for
32   * org.andromda.metafacades.uml.ManageableEntity.
33   *
34   * @see org.andromda.metafacades.uml.ManageableEntity
35   */
36  public class ManageableEntityLogicImpl
37      extends ManageableEntityLogic
38  {
39      private static final long serialVersionUID = 3824640154861250348L;
40  
41      /**
42       * @param metaObject
43       * @param context
44       */
45      public ManageableEntityLogicImpl(
46          final Object metaObject,
47          final String context)
48      {
49          super(metaObject, context);
50      }
51  
52      /**
53       * The logger instance.
54       */
55      //private static final Logger LOGGER = Logger.getLogger(ManageableEntityLogicImpl.class);
56  
57      /**
58       * @return the configured property denoting the character sequence to use
59       *         for the separation of namespaces
60       */
61      private String getNamespaceSeparator()
62      {
63          return (String)this.getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR);
64      }
65  
66      /**
67       * @see org.andromda.metafacades.uml.ManageableEntity#getManageablePackageName()
68       */
69      @Override
70      protected String handleGetManageablePackageName()
71      {
72          String manageablePackageName = "";
73  
74          final String parentPackage = super.getPackageName();
75          if (StringUtils.isNotBlank(parentPackage))
76          {
77              manageablePackageName = parentPackage;
78          }
79  
80          final Object suffix = this.getConfiguredProperty(UMLMetafacadeProperties.MANAGEABLE_PACKAGE_NAME_SUFFIX);
81          if (suffix != null && StringUtils.isNotBlank(suffix.toString()))
82          {
83              manageablePackageName += this.getNamespaceSeparator() + suffix;
84          }
85  
86          return manageablePackageName;
87      }
88  
89      /**
90       * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageablePackagePath()
91       */
92      @Override
93      protected String handleGetManageablePackagePath()
94      {
95          return StringUtils.replace(
96              this.getManageablePackageName(),
97              this.getNamespaceSeparator(),
98              "/");
99      }
100 
101     /**
102      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableAssociationEnds()
103      */
104     @Override
105     protected List<AssociationEndFacade> handleGetManageableAssociationEnds()
106     {
107         final Set<AssociationEndFacade> manageableAssociationEnds = new LinkedHashSet<AssociationEndFacade>(); // linked
108 
109         // hashset
110         // to
111         // guarantee
112         // ordering
113         // wo/
114         // duplicates
115         collectAssociationEnds(
116             manageableAssociationEnds,
117             this);
118 
119         return new ArrayList<AssociationEndFacade>(manageableAssociationEnds);
120     }
121 
122     /**
123      * This method recursively collects all association ends to which a
124      * manageable entity would need to navigate, adds to manageableAssociationEnds
125      *
126      * @param manageableAssociationEnds
127      *            the collection in which to collect the association ends
128      * @param entity
129      *            the entity from which to recursively gather the association
130      *            ends
131      */
132     private static void collectAssociationEnds(
133         final Collection<AssociationEndFacade> manageableAssociationEnds,
134         final ManageableEntity entity)
135     {
136         final Collection<AssociationEndFacade> associationEnds = entity.getAssociationEnds();
137         for (final Iterator<AssociationEndFacade> associationEndIterator = associationEnds.iterator(); associationEndIterator.hasNext();)
138         {
139             final AssociationEndFacade associationEnd = associationEndIterator.next();
140             final AssociationEndFacade otherEnd = associationEnd.getOtherEnd();
141 
142             if (otherEnd.isNavigable() && otherEnd.getType() instanceof Entity)
143             {
144                 manageableAssociationEnds.add(otherEnd);
145             }
146         }
147 
148         // retrieve all association ends for all parents (recursively)
149         final Collection<GeneralizableElementFacade> parentEntities = entity.getAllGeneralizations();
150         for (final Iterator<GeneralizableElementFacade> parentEntityIterator = parentEntities.iterator(); parentEntityIterator.hasNext();)
151         {
152             final Object parentEntityObject = parentEntityIterator.next();
153             if (parentEntityObject instanceof ManageableEntity)
154             {
155                 collectAssociationEnds(
156                     manageableAssociationEnds,
157                     (ManageableEntity)parentEntityObject);
158             }
159         }
160     }
161 
162     /**
163      * @see org.andromda.metafacades.uml.ManageableEntity#isCreate()
164      */
165     @Override
166     protected boolean handleIsCreate()
167     {
168         return !this.isAbstract();
169     }
170 
171     /**
172      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableServiceName()
173      */
174     @Override
175     protected String handleGetManageableServiceName()
176     {
177         return this.handleGetName() + "ManageableService";
178     }
179 
180     /**
181      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableServiceFullPath()
182      */
183     @Override
184     protected String handleGetManageableServiceFullPath()
185     {
186         return '/' +
187         StringUtils.replace(
188             this.getFullyQualifiedManageableServiceName(),
189             this.getNamespaceSeparator(),
190             "/");
191     }
192 
193     /**
194      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetFullyQualifiedManageableServiceName()
195      */
196     @Override
197     protected String handleGetFullyQualifiedManageableServiceName()
198     {
199         return this.getManageablePackageName() + this.getNamespaceSeparator() + this.getManageableServiceName();
200     }
201 
202     /**
203      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableServiceAccessorCall()
204      */
205     @Override
206     protected String handleGetManageableServiceAccessorCall()
207     {
208         final String property = UMLMetafacadeProperties.MANAGEABLE_SERVICE_ACCESSOR_PATTERN;
209         final String accessorImplementation =
210             this.isConfiguredProperty(property) ? ObjectUtils.toString(this.getConfiguredProperty(property))
211                 : "${application.package}.ManageableServiceLocator.instance().get{1}()";
212         return accessorImplementation.replaceAll(
213             "\\{0\\}",
214             this.getManageablePackageName()).replaceAll(
215                 "\\{1\\}",
216                 this.getManageableServiceName());
217     }
218 
219     /**
220      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleIsRead()
221      */
222     @Override
223     protected boolean handleIsRead()
224     {
225         return true;
226     }
227 
228     /**
229      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleIsUpdate()
230      */
231     @Override
232     protected boolean handleIsUpdate()
233     {
234         return this.getManageableIdentifier() != null; // TODO implement isUpdate
235     }
236 
237     /**
238      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleIsDelete()
239      */
240     @Override
241     protected boolean handleIsDelete()
242     {
243         return this.getManageableIdentifier() != null; // TODO implement isDelete
244     }
245 
246     /**)
247      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableAttributes()
248      */
249     @Override
250     protected List<AttributeFacade> handleGetManageableAttributes()
251     {
252         return new ArrayList<AttributeFacade>(this.getAttributes(true));
253     }
254 
255     /**
256      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableIdentifier()
257      */
258     @Override
259     protected ModelElementFacade handleGetManageableIdentifier()
260     {
261         ModelElementFacade rtn = null;
262         Collection<ModelElementFacade> identifiers = this.getIdentifiers(true);
263         if (identifiers != null && !identifiers.isEmpty())
264         {
265             rtn = this.getIdentifiers(true).iterator().next();
266         }
267         return rtn;
268     }
269 
270     /**
271      * Contains both Attributes and AssociationEnds
272      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetManageableMembers()
273      */
274     @Override
275     protected List<ModelElementFacade> handleGetManageableMembers()
276     {
277         final List<ModelElementFacade> criteria = new ArrayList();
278         criteria.addAll(this.getManageableAttributes());
279         criteria.addAll(this.getManageableAssociationEnds());
280         return criteria;
281     }
282 
283     private enum ListType
284     {
285         PRIMITIVE,
286         WRAPPER
287     }
288 
289     private String createListWithManageableMembers(final ListType listType)
290     {
291         final StringBuilder buffer = new StringBuilder();
292 
293         for (ManageableEntityAttribute attribute : this.getManageableAttributes())
294         {
295             if (buffer.length() > 0)
296             {
297                 buffer.append(", ");
298             }
299 
300             final ClassifierFacade type = attribute.getType();
301             if (type != null)
302             {
303                 if(ListType.PRIMITIVE.equals(listType))
304                 {
305                     buffer.append(type.getFullyQualifiedName());
306                     buffer.append(' ');
307                 }
308                 else if(ListType.WRAPPER.equals(listType))
309                 {
310                     buffer.append(type.isPrimitive() ? type.getWrapperName() : type.getFullyQualifiedName());
311                     buffer.append(' ');
312                 }
313                 buffer.append(attribute.getName());
314             }
315         }
316 
317         for (ManageableEntityAssociationEnd associationEnd : this.getManageableAssociationEnds())
318         {
319             final Entity entity = (Entity)associationEnd.getType();
320             if(entity.isCompositeIdentifier())
321             {
322                 if (buffer.length() > 0)
323                 {
324                     buffer.append(", ");
325                 }
326                 if (listType != null)
327                 {
328                     buffer.append(entity.getFullyQualifiedIdentifierTypeName());
329                     if (associationEnd.isMany())
330                     {
331                         buffer.append("[]");
332                     }
333                     buffer.append(' ');
334                 }
335                 buffer.append(associationEnd.getName());
336             }
337             else
338             {
339                 for (ModelElementFacade identifier : entity.getIdentifiers())
340                 {
341                     if (identifier != null)
342                     {
343                         if (buffer.length() > 0)
344                         {
345                             buffer.append(", ");
346                         }
347 
348                         ClassifierFacade type = null;
349                         if (identifier instanceof EntityAttribute)
350                         {
351                             type = ((EntityAttribute)identifier).getType();
352                         }
353                         else if (identifier instanceof EntityAssociationEnd)
354                         {
355                             type = ((EntityAssociationEnd)identifier).getType();
356                         }
357                         if (type != null)
358                         {
359                             if (listType != null)
360                             {
361                                 buffer.append(type.getFullyQualifiedName());
362                                 if (associationEnd.isMany())
363                                 {
364                                     buffer.append("[]");
365                                 }
366                                 buffer.append(' ');
367                             }
368                             buffer.append(associationEnd.getName());
369                         }
370                     }
371                 }
372             }
373         }
374 
375         return buffer.toString();
376     }
377 
378     /**
379      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleListManageableMembersWithWrapperTypes()
380      */
381     @Override
382     protected String handleListManageableMembersWithWrapperTypes()
383     {
384         return createListWithManageableMembers(ListType.WRAPPER);
385     }
386 
387     /**
388      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleListManageableMembers(boolean)
389      */
390     @Override
391     protected String handleListManageableMembers(final boolean withTypes)
392     {
393         return createListWithManageableMembers(withTypes ? ListType.PRIMITIVE : null);
394     }
395 
396     /**
397      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleIsManageable()
398      */
399     @Override
400     protected boolean handleIsManageable()
401     {
402         return Boolean.valueOf((String) this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_MANAGEABLE_ENTITIES));
403     }
404 
405     /**
406      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetReferencingManageables()
407      */
408     @Override
409     protected List<ClassifierFacade> handleGetReferencingManageables()
410     {
411         final Set<ClassifierFacade> referencingManageables = new LinkedHashSet<ClassifierFacade>();
412         final Collection<AssociationEndFacade> associationEnds = this.getAssociationEnds();
413         for (final Iterator<AssociationEndFacade> associationEndIterator = associationEnds.iterator(); associationEndIterator.hasNext();)
414         {
415             final AssociationEndFacade associationEnd = associationEndIterator.next();
416 
417             if (associationEnd.isNavigable())
418             {
419                 if (associationEnd.isMany() || (associationEnd.isOne2One() && associationEnd.isChild()))
420                 {
421                     final Object otherEndType = associationEnd.getOtherEnd().getType();
422                     if (otherEndType instanceof Entity)
423                     {
424                         referencingManageables.add((ClassifierFacade) otherEndType);
425                     }
426                 }
427             }
428         }
429         return new ArrayList<ClassifierFacade>(referencingManageables);
430     }
431 
432     /**
433      * Returns the value of the 'andromda_manageable_table_displayname' or the first unique attribute, or the identifier column.
434      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetDisplayAttribute()
435      */
436     @Override
437     protected AttributeFacade handleGetDisplayAttribute()
438     {
439         AttributeFacade displayAttribute = null;
440 
441         final Object taggedValueObject = this.findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_DISPLAY_NAME);
442         if (taggedValueObject != null)
443         {
444             displayAttribute = this.findAttribute(StringUtils.trimToEmpty(taggedValueObject.toString()));
445         }
446 
447         final Collection<AttributeFacade> attributes = this.getAttributes(true);
448         for (final Iterator<AttributeFacade> attributeIterator = attributes.iterator();
449             attributeIterator.hasNext() && displayAttribute == null;)
450         {
451             // TODO: UML2 migrated models automatically mark all * attributes as unique. Different display attributes are selected from UML14 and UML2 migrated models.
452             // This selects the first attribute that is unique as the display value.
453             final Object attribute = attributeIterator.next();
454             if(attribute instanceof EntityAttribute)//can get attributes from ancestor classes
455             {
456                 final EntityAttribute entityAttribute = (EntityAttribute)attribute;
457                 if (entityAttribute.isUnique())
458                 {
459                     displayAttribute = entityAttribute;
460                 }
461             }
462         }
463 
464         if (displayAttribute == null)
465         {
466             final  Collection<ModelElementFacade> identifiers = this.getIdentifiers();
467             if (identifiers != null && !identifiers.isEmpty())
468             {
469                 ModelElementFacade facade = identifiers.iterator().next();
470                 if (facade instanceof EntityAttribute)
471                 {
472                     displayAttribute = ((EntityAttribute)facade);
473                 }
474                 else
475                 {
476                     displayAttribute = attributes.iterator().next();
477                 }
478             }
479             else if (!attributes.isEmpty())
480             {
481                 displayAttribute = attributes.iterator().next();
482             }
483         }
484 
485         return displayAttribute;
486     }
487 
488     /**
489      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetUsers()
490      */
491     @Override
492     protected List<ActorFacade> handleGetUsers()
493     {
494         final Set<ActorFacade> users = new LinkedHashSet<ActorFacade>();
495 
496         final Collection<DependencyFacade> dependencies = this.getTargetDependencies();
497         for (final Iterator<DependencyFacade> dependencyIterator = dependencies.iterator(); dependencyIterator.hasNext();)
498         {
499             final DependencyFacade dependency = dependencyIterator.next();
500             final Object dependencyObject = dependency.getSourceElement();
501 
502             if (!users.contains(dependencyObject) && dependencyObject instanceof ActorFacade)
503             {
504                 this.collectActors(
505                     (ActorFacade)dependencyObject,
506                     users);
507             }
508         }
509 
510         return new ArrayList<ActorFacade>(users);
511     }
512 
513     private void collectActors(
514         final ActorFacade actor,
515         final Collection<ActorFacade> actors)
516     {
517         if (!actors.contains(actor))
518         {
519             actors.add(actor);
520 
521             final Collection<ActorFacade> childActors = actor.getGeneralizedByActors();
522             for (final Iterator<ActorFacade> iterator = childActors.iterator(); iterator.hasNext();)
523             {
524                 final ActorFacade childActor = iterator.next();
525                 this.collectActors(
526                     childActor,
527                     actors);
528             }
529         }
530     }
531 
532     /**
533      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetMaximumListSize()
534      */
535     @Override
536     protected int handleGetMaximumListSize()
537     {
538         int maximumListSize;
539 
540         final Object taggedValueObject = this.findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_MAXIMUM_LIST_SIZE);
541         if (taggedValueObject == null)
542         {
543             maximumListSize = this.internalDefaultMaximumListSize();
544         }
545         else
546         {
547             try
548             {
549                 maximumListSize = Integer.parseInt(taggedValueObject.toString());
550             }
551             catch (NumberFormatException e)
552             {
553                 maximumListSize = this.internalDefaultMaximumListSize();
554             }
555         }
556 
557         return maximumListSize;
558     }
559 
560     private int internalDefaultMaximumListSize()
561     {
562         int maximumListSize;
563 
564         try
565         {
566             maximumListSize =
567                 Integer.parseInt(
568                     (String)this.getConfiguredProperty(UMLMetafacadeProperties.PROPERTY_DEFAULT_MAX_LIST_SIZE));
569         }
570         catch (NumberFormatException e1)
571         {
572             maximumListSize = -1;
573         }
574 
575         return maximumListSize;
576     }
577 
578     /**
579      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetPageSize()
580      */
581     @Override
582     protected int handleGetPageSize()
583     {
584         int pageSize;
585 
586         final Object taggedValueObject = this.findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_PAGE_SIZE);
587         if (taggedValueObject == null)
588         {
589             pageSize = this.internalDefaultPageSize();
590         }
591         else
592         {
593             try
594             {
595                 pageSize = Integer.parseInt(taggedValueObject.toString());
596             }
597             catch (NumberFormatException e)
598             {
599                 pageSize = this.internalDefaultPageSize();
600             }
601         }
602 
603         return pageSize;
604     }
605 
606     private int internalDefaultPageSize()
607     {
608         int pageSize;
609 
610         try
611         {
612             pageSize =
613                 Integer.parseInt(
614                     (String)this.getConfiguredProperty(UMLMetafacadeProperties.PROPERTY_DEFAULT_PAGE_SIZE));
615         }
616         catch (NumberFormatException e1)
617         {
618             pageSize = 20;
619         }
620 
621         return pageSize;
622     }
623 
624     /**
625      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleIsResolveable()
626      */
627     @Override
628     protected boolean handleIsResolveable()
629     {
630         boolean resolveable;
631 
632         final Object taggedValueObject = this.findTaggedValue(UMLProfile.TAGGEDVALUE_MANAGEABLE_RESOLVEABLE);
633         if (taggedValueObject == null)
634         {
635             resolveable = this.internalDefaultResolveable();
636         }
637         else
638         {
639             try
640             {
641                 resolveable = Boolean.valueOf(taggedValueObject.toString()).booleanValue();
642             }
643             catch (NumberFormatException e)
644             {
645                 resolveable = this.internalDefaultResolveable();
646             }
647         }
648 
649         return resolveable;
650     }
651 
652     private boolean internalDefaultResolveable()
653     {
654         boolean resolveable;
655 
656         try
657         {
658             resolveable =
659                Boolean.valueOf(
660                (String) this.getConfiguredProperty(UMLMetafacadeProperties.PROPERTY_DEFAULT_RESOLVEABLE)).booleanValue();
661         }
662         catch (NumberFormatException ex)
663         {
664             resolveable = true;
665         }
666 
667         return resolveable;
668     }
669 
670     /**
671      * @see org.andromda.metafacades.emf.uml22.ManageableEntityLogic#handleGetAllManageables()
672      */
673     @Override
674     protected List<ManageableEntity> handleGetAllManageables()
675     {
676         final Set<ManageableEntity> allManageableEntities = new TreeSet<ManageableEntity>(new ManageableComparator());
677 
678         final Collection<ClassifierFacade> allClasses = this.getModel().getAllClasses();
679         for (final Iterator<ClassifierFacade> classIterator = allClasses.iterator(); classIterator.hasNext();)
680         {
681             final Object classObject = classIterator.next();
682             if (classObject instanceof ManageableEntity)
683             {
684                 allManageableEntities.add((ManageableEntity)classObject);
685             }
686         }
687         return new ArrayList<ManageableEntity>(allManageableEntities);
688     }
689 
690     /**
691      */
692     static final class ManageableComparator
693         implements Serializable, Comparator
694     {
695         //@SuppressWarnings("unused")
696         private static final long serialVersionUID = 1L;
697         /**
698          * @see java.util.Comparator#compare(Object, Object)
699          */
700         public int compare(
701             final Object left,
702             final Object right)
703         {
704             final ModelElementFacade leftEntity = (ModelElementFacade)left;
705             final ModelElementFacade rightEntity = (ModelElementFacade)right;
706 
707             return leftEntity.getName().compareTo(rightEntity.getName());
708         }
709     }
710 }