View Javadoc
1   package org.andromda.metafacades.uml14;
2   
3   import java.util.Collection;
4   import org.andromda.metafacades.uml.ClassifierFacade;
5   import org.andromda.metafacades.uml.NameMasker;
6   import org.andromda.metafacades.uml.TypeMappings;
7   import org.andromda.metafacades.uml.UMLMetafacadeProperties;
8   import org.andromda.metafacades.uml.UMLMetafacadeUtils;
9   import org.andromda.metafacades.uml.UMLProfile;
10  import org.andromda.utils.StringUtilsHelper;
11  import org.apache.commons.lang.BooleanUtils;
12  import org.apache.commons.lang.ObjectUtils;
13  import org.apache.commons.lang.StringUtils;
14  import org.omg.uml.foundation.core.AssociationEnd;
15  import org.omg.uml.foundation.core.Classifier;
16  import org.omg.uml.foundation.core.UmlAssociation;
17  import org.omg.uml.foundation.datatypes.AggregationKindEnum;
18  import org.omg.uml.foundation.datatypes.ChangeableKindEnum;
19  import org.omg.uml.foundation.datatypes.Multiplicity;
20  import org.omg.uml.foundation.datatypes.MultiplicityRange;
21  import org.omg.uml.foundation.datatypes.OrderingKind;
22  import org.omg.uml.foundation.datatypes.OrderingKindEnum;
23  
24  /**
25   * Metaclass facade implementation.
26   * @author Bob Fields
27   */
28  public class AssociationEndFacadeLogicImpl
29      extends AssociationEndFacadeLogic
30  {
31      private static final long serialVersionUID = 34L;
32      /**
33       * @param metaObject
34       * @param context
35       */
36      public AssociationEndFacadeLogicImpl(
37          org.omg.uml.foundation.core.AssociationEnd metaObject,
38          String context)
39      {
40          super(metaObject, context);
41      }
42  
43      /**
44       * @see org.andromda.core.metafacade.MetafacadeBase#getValidationOwner()
45       */
46      public ClassifierFacade getValidationOwner()
47      {
48          return this.getType();
49      }
50  
51      /**
52       * @see org.andromda.metafacades.uml.AssociationEndFacade#getOtherEnd()
53       */
54      @Override
55      protected AssociationEnd handleGetOtherEnd()
56      {
57          final Collection<AssociationEnd> ends = metaObject.getAssociation().getConnection();
58          for (final AssociationEnd end : ends)
59          {
60              if (!metaObject.equals(end))
61              {
62                  return end;
63              }
64          }
65          return null;
66      }
67  
68      /**
69       * @see org.andromda.metafacades.uml14.ModelElementFacadeLogic#handleGetName()
70       */
71      protected String handleGetName()
72      {
73          String name = super.handleGetName();
74  
75          // if name is empty, then get the name from the type
76          if (StringUtils.isEmpty(name))
77          {
78              final ClassifierFacade type = this.getType();
79              if (type != null)
80              {
81                  name = StringUtils.uncapitalize(StringUtils.trimToEmpty(type.getName()));
82              }
83          }
84          if (this.isMany() && this.isPluralizeAssociationEndNames())
85          {
86              name = StringUtilsHelper.pluralize(name);
87          }
88          final String nameMask =
89              String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.CLASSIFIER_PROPERTY_NAME_MASK));
90          return NameMasker.mask(
91              name,
92              nameMask);
93      }
94  
95      /**
96       * Indicates whether or not we should pluralize association end names.
97       *
98       * @return true/false
99       */
100     private boolean isPluralizeAssociationEndNames()
101     {
102         final Object value = this.getConfiguredProperty(UMLMetafacadeProperties.PLURALIZE_ASSOCIATION_END_NAMES);
103         return value != null && Boolean.valueOf(String.valueOf(value));
104     }
105 
106     /**
107      * @return metaObject.getAggregation().toString()
108      * @see org.andromda.metafacades.uml.AssociationEndFacade#getAggregationKind()
109      */
110     protected String handleGetAggregationKind()
111     {
112         return metaObject.getAggregation().toString();
113     }
114 
115     /**
116      * NOT IMPLEMENTED - UML2 only
117      * @return "" always
118      * @see org.andromda.metafacades.uml.AssociationEndFacade#getDefault()
119      */
120     protected String handleGetDefault()
121     {
122         return "";
123     }
124 
125     /**
126      * @see org.andromda.metafacades.uml.AssociationEndFacade#getType()
127      */
128     @Override
129     protected Classifier handleGetType()
130     {
131         return metaObject.getParticipant();
132     }
133 
134     /**
135      * @see org.andromda.metafacades.uml.AssociationEndFacade#isOne2Many()
136      */
137     @Override
138     protected boolean handleIsOne2Many()
139     {
140         return !this.isMany() && this.getOtherEnd().isMany();
141     }
142 
143     /**
144      * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany2Many()
145      */
146     @Override
147     protected boolean handleIsMany2Many()
148     {
149         return this.isMany() && this.getOtherEnd().isMany();
150     }
151 
152     /**
153      * @see org.andromda.metafacades.uml.AssociationEndFacade#isOne2One()
154      */
155     @Override
156     protected boolean handleIsOne2One()
157     {
158         return !this.isMany() && !this.getOtherEnd().isMany();
159     }
160 
161     /**
162      * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany2One()
163      */
164     @Override
165     protected boolean handleIsMany2One()
166     {
167         return this.isMany() && !this.getOtherEnd().isMany();
168     }
169 
170     /**
171      * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany()
172      */
173     @Override
174     protected boolean handleIsMany()
175     {
176         boolean isMany = false;
177         final Multiplicity multiplicity = this.metaObject.getMultiplicity();
178 
179         // we'll say a null multiplicity is 1
180         if (multiplicity != null)
181         {
182             final Collection<MultiplicityRange> ranges = multiplicity.getRange();
183             if (ranges != null && !ranges.isEmpty())
184             {
185                 for (MultiplicityRange multiplicityRange : ranges)
186                 {
187                     final int upper = multiplicityRange.getUpper();
188                     isMany = upper > 1 || upper < 0;
189                 }
190             }
191         }
192         if (null!=this.getType() && !isMany)
193         {
194             // isCollectionType causes too many problems with the metafacades
195             isMany = this.getType().isArrayType();
196         }
197         return isMany;
198     }
199 
200     /**
201      * UML2 Only: Returns false always.
202      * @return false
203      * @see org.andromda.metafacades.uml.AssociationEndFacade#isLeaf()
204      */
205     @Override
206     public boolean handleIsLeaf()
207     {
208         return false;
209     }
210 
211     /**
212      * @see org.andromda.metafacades.uml.AssociationEndFacade#isOrdered()
213      */
214     @Override
215     protected boolean handleIsOrdered()
216     {
217         boolean ordered = false;
218 
219         final OrderingKind ordering = metaObject.getOrdering();
220 
221         // no ordering is 'unordered'
222         if (ordering != null)
223         {
224             ordered = ordering.equals(OrderingKindEnum.OK_ORDERED);
225         }
226 
227         return ordered;
228     }
229 
230     /**
231      * UML2 Only: Returns false always.
232      * @return hasStereotype(UMLProfile.STEREOTYPE_UNIQUE)
233      * @see org.andromda.metafacades.uml.AssociationEndFacade#isUnique()
234      */
235     @Override
236     public boolean handleIsUnique()
237     {
238         return this.hasStereotype(UMLProfile.STEREOTYPE_UNIQUE);
239     }
240 
241     /**
242      * @see org.andromda.metafacades.uml.AssociationEndFacade#isAggregation()
243      */
244     @Override
245     protected boolean handleIsAggregation()
246     {
247         return AggregationKindEnum.AK_AGGREGATE.equals(metaObject.getAggregation());
248     }
249 
250     /**
251      * @see org.andromda.metafacades.uml.AssociationEndFacade#isComposition()
252      */
253     @Override
254     protected boolean handleIsComposition()
255     {
256         return AggregationKindEnum.AK_COMPOSITE.equals(metaObject.getAggregation());
257     }
258 
259     /**
260      * @see org.andromda.metafacades.uml.AssociationEndFacade#isReadOnly()
261      */
262     @Override
263     protected boolean handleIsReadOnly()
264     {
265         return ChangeableKindEnum.CK_FROZEN.equals(metaObject.getChangeability());
266     }
267 
268     /**
269      * @see org.andromda.metafacades.uml.AssociationEndFacade#isNavigable()
270      */
271     @Override
272     protected boolean handleIsNavigable()
273     {
274         return metaObject.isNavigable();
275     }
276 
277     /**
278      * @see org.andromda.metafacades.uml.AssociationEndFacade#getGetterName()
279      */
280     @Override
281     protected String handleGetGetterName()
282     {
283         return UMLMetafacadeUtils.getGetterPrefix(this.getType()) + StringUtilsHelper.capitalize(this.getName());
284     }
285 
286     /**
287      * @see org.andromda.metafacades.uml.AssociationEndFacade#getSetterName()
288      */
289     @Override
290     protected String handleGetSetterName()
291     {
292         return "set" + StringUtils.capitalize(this.getName());
293     }
294 
295     /**
296      * @see org.andromda.metafacades.uml.AssociationEndFacade#getAdderName()
297      */
298     @Override
299     protected String handleGetAdderName()
300     {
301         return "add" + StringUtils.capitalize(this.getName());
302     }
303 
304     /**
305      * @see org.andromda.metafacades.uml.AssociationEndFacade#getRemoverName()
306      */
307     @Override
308     protected String handleGetRemoverName()
309     {
310         return "remove" + StringUtils.capitalize(this.getName());
311     }
312 
313     /**
314      * @see org.andromda.metafacades.uml.AssociationEndFacade#isBindingDependenciesPresent()
315      */
316     @Override
317     protected boolean handleIsBidirectional()
318     {
319         return isNavigable() && getOtherEnd().isNavigable();
320     }
321 
322     /**
323      * @see org.andromda.metafacades.uml.AssociationEndFacade#getAssociation()
324      */
325     @Override
326     protected UmlAssociation handleGetAssociation()
327     {
328         return metaObject.getAssociation();
329     }
330 
331     /**
332      * @see org.andromda.metafacades.uml.AssociationEndFacade#getGetterSetterTypeName()
333      */
334     @Override
335     protected String handleGetGetterSetterTypeName()
336     {
337         String name = null;
338         if (this.isMany() && this.getType()!=null && !this.getType().isArrayType() && !this.getType().isCollectionType())
339         {
340             final TypeMappings mappings = this.getLanguageMappings();
341             if (mappings != null)
342             {
343                 name =
344                     this.isOrdered() ? mappings.getTo(UMLProfile.LIST_TYPE_NAME)
345                                      : mappings.getTo(UMLProfile.COLLECTION_TYPE_NAME);
346             }
347 
348             // set this association end's type as a template parameter if required
349             if (BooleanUtils.toBoolean(
350                     ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING)))
351                     && this.getType() != null)
352             {
353                 String type = this.getType().getFullyQualifiedName();
354                 /*Collection<GeneralizableElementFacade> specializations = this.getType().getAllSpecializations();
355                 if ((specializations != null && !specializations.isEmpty()))
356                 {
357                     name += "<? extends " + type + '>';
358                 }
359                 else
360                 {*/
361                     name += '<' + type + '>';
362                 //}
363             }
364         }
365         if (name == null && this.getType() != null)
366         {
367             name = this.getType().getFullyQualifiedName();
368         }
369         return name;
370     }
371 
372     /**
373      * @see org.andromda.metafacades.uml.AssociationEndFacade#isRequired()
374      */
375     @Override
376     protected boolean handleIsRequired()
377     {
378         final int lower = this.getMultiplicityRangeLower();
379         return lower >= 1;
380     }
381 
382     /**
383      * @see org.andromda.metafacades.uml.AssociationEndFacade#isChild()
384      */
385     @Override
386     protected boolean handleIsChild()
387     {
388         return this.getOtherEnd() != null && this.getOtherEnd().isComposition();
389     }
390 
391     /**
392      * Returns the upper range of the multiplicity for the passed in attribute
393      *
394      * @return int the upper range of the multiplicity or 1 if it isn't defined.
395      */
396     private int getMultiplicityRangeUpper()
397     {
398         Integer upper = null;
399         final Multiplicity multiplicity = metaObject.getMultiplicity();
400         if (multiplicity != null)
401         {
402             final Collection<MultiplicityRange> ranges = multiplicity.getRange();
403             if (ranges != null)
404             {
405                 for (MultiplicityRange multiplicityRange  : ranges)
406                 {
407                     upper = Integer.valueOf(multiplicityRange.getUpper());
408                 }
409             }
410         }
411         if (upper == null)
412         {
413             upper = Integer.valueOf(1);
414         }
415         return upper.intValue();
416     }
417 
418     /**
419      * Returns the lower range of the multiplicity for the passed in associationEnd
420      *
421      * @return int the lower range of the multiplicity or 1 if it isn't defined.
422      */
423     private int getMultiplicityRangeLower()
424     {
425         Integer lower = null;
426         final Multiplicity multiplicity = this.metaObject.getMultiplicity();
427         if (multiplicity != null)
428         {
429             final Collection<MultiplicityRange> ranges = multiplicity.getRange();
430             if (ranges != null)
431             {
432                 for (MultiplicityRange multiplicityRange : ranges)
433                 {
434                     lower = Integer.valueOf(multiplicityRange.getLower());
435                 }
436             }
437         }
438         if (lower == null)
439         {
440             final String defaultMultiplicity = this.getDefaultMultiplicity();
441             if (defaultMultiplicity.startsWith("0"))
442             {
443                 lower = Integer.valueOf(0);
444             }
445             else
446             {
447                 lower = Integer.valueOf(1);
448             }
449         }
450         return lower.intValue();
451     }
452 
453     /**
454      * Gets the default multiplicity for this attribute (the
455      * multiplicity if none is defined).
456      *
457      * @return the default multiplicity as a String.
458      */
459     private String getDefaultMultiplicity()
460     {
461         return ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_MULTIPLICITY));
462     }
463 
464     /**
465      * Get the UML upper multiplicity
466      * Not implemented for UML1.4
467      */
468     @Override
469     protected int handleGetUpper()
470     {
471         return this.getMultiplicityRangeUpper();
472      }
473 
474     /**
475      * Get the UML lower multiplicity
476      */
477     @Override
478     protected int handleGetLower()
479     {
480         return this.getMultiplicityRangeLower();
481     }
482 
483     /**
484      * @see org.andromda.metafacades.uml14.AssociationEndFacadeLogic#handleIsDerived()
485      */
486     @Override
487     protected boolean handleIsDerived()
488     {
489         // UML 1.4 does not have derived association ends.
490         return false;
491     }
492 
493     /**
494      * UML2 only. Can't determine association scope in UML14.
495      * @see org.andromda.metafacades.uml.AttributeFacade#isStatic()
496      */
497     @Override
498     public boolean handleIsStatic()
499     {
500         return false;
501     }
502 }