View Javadoc
1   package org.andromda.metafacades.uml14;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Comparator;
6   import java.util.Iterator;
7   import java.util.LinkedHashSet;
8   import java.util.List;
9   import java.util.Set;
10  import java.util.TreeSet;
11  import org.andromda.metafacades.uml.ActorFacade;
12  import org.andromda.metafacades.uml.AssociationEndFacade;
13  import org.andromda.metafacades.uml.AttributeFacade;
14  import org.andromda.metafacades.uml.ClassifierFacade;
15  import org.andromda.metafacades.uml.DependencyFacade;
16  import org.andromda.metafacades.uml.Entity;
17  import org.andromda.metafacades.uml.EntityAttribute;
18  import org.andromda.metafacades.uml.GeneralizableElementFacade;
19  import org.andromda.metafacades.uml.ManageableEntity;
20  import org.andromda.metafacades.uml.ModelElementFacade;
21  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
22  import org.andromda.metafacades.uml.UMLProfile;
23  import org.andromda.utils.StringUtilsHelper;
24  import org.apache.commons.lang.ObjectUtils;
25  import org.apache.commons.lang.StringUtils;
26  
27  /**
28   * MetafacadeLogic implementation for org.andromda.metafacades.uml.ManageableEntity.
29   *
30   * @see org.andromda.metafacades.uml.ManageableEntity
31   * @author Bob Fields
32   */
33  public class ManageableEntityLogicImpl
34      extends ManageableEntityLogic
35  {
36      private static final long serialVersionUID = -1239526138513293700L;
37  
38      /**
39       * @param metaObject
40       * @param context
41       */
42      public ManageableEntityLogicImpl(Object metaObject, String context)
43      {
44          super(metaObject, context);
45      }
46  
47      /**
48       * @return the configured property denoting the character sequence to use for the separation of namespaces
49       */
50      private String getNamespaceSeparator()
51      {
52          return (String)getConfiguredProperty(UMLMetafacadeProperties.NAMESPACE_SEPARATOR);
53      }
54  
55      /**
56       * @return manageablePackageName
57       * @see org.andromda.metafacades.uml.ManageableEntity#getManageablePackageName()
58       */
59      protected String handleGetManageablePackageName()
60      {
61          String manageablePackageName = "";
62  
63          final String parentPackage = super.getPackageName();
64          if (StringUtils.isNotBlank(parentPackage))
65          {
66              manageablePackageName = parentPackage;
67          }
68  
69          final Object suffix = getConfiguredProperty(UMLMetafacadeProperties.MANAGEABLE_PACKAGE_NAME_SUFFIX);
70          if (suffix != null && StringUtils.isNotBlank(suffix.toString()))
71          {
72              manageablePackageName += this.getNamespaceSeparator() + suffix;
73          }
74  
75          return manageablePackageName;
76      }
77  
78      /**
79       * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageablePackagePath()
80       */
81      protected String handleGetManageablePackagePath()
82      {
83          return StringUtils.replace(this.getManageablePackageName(), this.getNamespaceSeparator(), "/");
84      }
85  
86      /**
87       * @see org.andromda.metafacades.uml14.ManageableEntityLogic#handleGetManageableAssociationEnds()
88       */
89      protected List handleGetManageableAssociationEnds()
90      {
91          final Set manageableAssociationEnds = new LinkedHashSet();// linked hashset to guarantee ordering wo/ duplicates
92          collectAssociationEnds(manageableAssociationEnds, this);
93          return new ArrayList(manageableAssociationEnds);
94      }
95  
96      /**
97       * This method recursively collects all association ends to which a manageable entity would need to navigate
98       *
99       * @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 }