View Javadoc
1   package org.andromda.metafacades.emf.uml22;
2   
3   import org.andromda.metafacades.uml.ClassifierFacade;
4   import org.andromda.metafacades.uml.EntityAttribute;
5   import org.andromda.metafacades.uml.EnumerationFacade;
6   import org.andromda.metafacades.uml.NameMasker;
7   import org.andromda.metafacades.uml.TypeMappings;
8   import org.andromda.metafacades.uml.UMLMetafacadeProperties;
9   import org.andromda.metafacades.uml.UMLMetafacadeUtils;
10  import org.andromda.metafacades.uml.UMLProfile;
11  import org.andromda.utils.StringUtilsHelper;
12  import org.apache.commons.lang.BooleanUtils;
13  import org.apache.commons.lang.ObjectUtils;
14  import org.apache.commons.lang.StringUtils;
15  import org.eclipse.uml2.uml.Class;
16  import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
17  import org.eclipse.uml2.uml.Type;
18  
19  /**
20   * MetafacadeLogic implementation for
21   * org.andromda.metafacades.uml.AttributeFacade.
22   *
23   * @see org.andromda.metafacades.uml.AttributeFacade
24   * @author Bob Fields
25   */
26  public class AttributeFacadeLogicImpl
27      extends AttributeFacadeLogic
28  {
29      private static final long serialVersionUID = 34L;
30      /**
31       * @param metaObjectIn
32       * @param context
33       */
34      public AttributeFacadeLogicImpl(
35          final Attribute metaObjectIn,
36          final String context)
37      {
38          super(metaObjectIn, context);
39      }
40  
41      /**
42       * @see org.andromda.metafacades.uml.AttributeFacade#getGetterName()
43       */
44      @Override
45      protected String handleGetGetterName()
46      {
47          return UMLMetafacadeUtils.getGetterPrefix(this.getType(), this.getLower()) + StringUtils.capitalize(this.handleGetName());
48      }
49  
50      /**
51       * @see org.andromda.metafacades.uml.AttributeFacade#getSetterName()
52       */
53      @Override
54      protected String handleGetSetterName()
55      {
56          return "set" + StringUtils.capitalize(this.handleGetName());
57      }
58  
59      /**
60       * @see org.andromda.metafacades.uml.AttributeFacade#isReadOnly()
61       */
62      @Override
63      protected boolean handleIsReadOnly()
64      {
65          return this.metaObject.isReadOnly();
66      }
67  
68      /**
69       * @see org.andromda.metafacades.uml.AttributeFacade#getDefaultValue()
70       */
71      @Override
72      protected String handleGetDefaultValue()
73      {
74          String defaultValue = this.metaObject.getDefault();
75          // Put single or double quotes around default in case modeler forgot to do it. Most templates
76          // declare Type attribute = $attribute.defaultValue, requiring quotes around the value
77          if (StringUtils.isNotBlank(defaultValue) && !this.isMany())
78          {
79              final String typeName = this.metaObject.getType().getName();
80              final String fullyQualifiedName = this.handleGetFullyQualifiedName();
81              if ("String".equals(typeName) && defaultValue.indexOf('"')<0)
82              {
83                  defaultValue = '"' + defaultValue + '"';
84              }
85              else if (("char".equals(typeName) || "Character".equals(typeName))
86                  && defaultValue.indexOf('\'')<0)
87              {
88                  defaultValue = "'" + defaultValue.charAt(0) + '\'';
89              }
90              else if (fullyQualifiedName.startsWith("java.lang") && defaultValue.indexOf(".valueOf(")<0)
91              {
92                  defaultValue = fullyQualifiedName + ".valueOf(" + defaultValue + ')';
93              }
94          }
95          if (defaultValue==null) {defaultValue="";}
96          return defaultValue;
97      }
98  
99      /**
100      * @see org.andromda.metafacades.uml.AttributeFacade#isStatic()
101      */
102     @Override
103     protected boolean handleIsStatic()
104     {
105         return this.metaObject.isStatic();
106     }
107 
108     /**
109      * @return this.metaObject.isLeaf()
110      * @see org.andromda.metafacades.uml.AttributeFacade#isLeaf()
111      */
112     @Override
113     protected boolean handleIsLeaf()
114     {
115         return this.metaObject.isLeaf();
116     }
117 
118     /**
119      * @see org.andromda.metafacades.uml.AssociationEndFacade#isMany()
120      */
121     @Override
122     protected boolean handleIsMany()
123     {
124         // Because of MD11.5 (their multiplicity are String), we cannot use isMultiValued()
125         // Name or type may be null during the model validation process.
126         return this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED
127                || (null!=this.getType() && (this.getType().isArrayType() || this.getType().isCollectionType()));
128     }
129 
130     /**
131      * @see org.andromda.metafacades.uml.AssociationEndFacade#isRequired()
132      */
133     @Override
134     protected boolean handleIsRequired()
135     {
136         return this.getLower() > 0;
137     }
138 
139     /**
140      * @see org.andromda.metafacades.uml.AttributeFacade#isChangeable()
141      */
142     @Override
143     protected boolean handleIsChangeable()
144     {
145         return !this.metaObject.isReadOnly();
146     }
147 
148     /**
149      * @see org.andromda.metafacades.uml.AttributeFacade#isAddOnly()
150      */
151     @Override
152     protected boolean handleIsAddOnly()
153     {
154         // TODO: really nothing to do here ?
155         return false;
156     }
157 
158     /**
159      * @see org.andromda.metafacades.uml.AttributeFacade#isEnumerationLiteral()
160      */
161     @Override
162     protected boolean handleIsEnumerationLiteral()
163     {
164         final ClassifierFacade owner = this.getOwner();
165         return (owner != null) && owner.isEnumeration();
166     }
167 
168     /**
169      * @see org.andromda.metafacades.uml.AttributeFacade#getEnumerationValue()
170      */
171     @Override
172     protected String handleGetEnumerationValue()
173     {
174         String value = null;
175         if (this.isEnumerationLiteral())
176         {
177             value = this.getDefaultValue();
178             value = (StringUtils.isBlank(value)) ? this.handleGetName() : String.valueOf(value);
179         }
180         if (this.getType().isStringType() && value!=null && value.indexOf('"')<0)
181         {
182             value = '\"' + value + '\"';
183         }
184         return value;
185     }
186 
187     /**
188      * @see org.andromda.metafacades.uml.AttributeFacade#isEnumerationMember()
189      */
190     @Override
191     protected boolean handleIsEnumerationMember()
192     {
193         boolean isMemberVariable = false;
194         final String isMemberVariableAsString = (String)this.findTaggedValue(
195                 UMLProfile.TAGGEDVALUE_PERSISTENCE_ENUMERATION_MEMBER_VARIABLE);
196         if (StringUtils.isNotBlank(isMemberVariableAsString) && BooleanUtils.toBoolean(isMemberVariableAsString))
197         {
198             isMemberVariable = true;
199         }
200         return isMemberVariable;
201     }
202 
203     /**
204      * @see org.andromda.metafacades.uml.AttributeFacade#getEnumerationLiteralParameters()
205      */
206     @Override
207     protected String handleGetEnumerationLiteralParameters()
208     {
209         return (String)this.findTaggedValue(UMLProfile.TAGGEDVALUE_PERSISTENCE_ENUMERATION_LITERAL_PARAMETERS);
210     }
211 
212     /**
213      * @see org.andromda.metafacades.uml.AttributeFacade#isEnumerationLiteralParametersExist()
214      */
215     @Override
216     protected boolean handleIsEnumerationLiteralParametersExist()
217     {
218         boolean parametersExist = false;
219         if (StringUtils.isNotBlank(this.getEnumerationLiteralParameters()))
220         {
221             parametersExist = true;
222         }
223         return parametersExist;
224     }
225 
226     /**
227      * @see org.andromda.metafacades.uml.AttributeFacade#getGetterSetterTypeName()
228      */
229     @Override
230     protected String handleGetGetterSetterTypeName()
231     {
232         String name = null;
233         if (this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED)
234         {
235             final TypeMappings mappings = this.getLanguageMappings();
236             //TODO: Create Implementation types for declared types, with mappings from declaration -> implementation
237             // TODO: Fix Metafacade models to properly reflect Unique/Ordered in associations, and update Impl classes
238             /*if (this.handleIsUnique())
239             {
240                 name =
241                     this.isOrdered() ? mappings.getTo(UMLProfile.ORDERED_SET_TYPE_NAME)
242                                      : mappings.getTo(UMLProfile.SET_TYPE_NAME);
243             }
244             else
245             {*/
246                 name =
247                     this.isOrdered() ? mappings.getTo(UMLProfile.LIST_TYPE_NAME)
248                                      : mappings.getTo(UMLProfile.COLLECTION_TYPE_NAME);
249             /*}*/
250 
251             // set this attribute's type as a template parameter if required
252             if (BooleanUtils.toBoolean(
253                     ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING))))
254             {
255                 String type = this.getType().getFullyQualifiedName();
256                 if (this.getType().isPrimitive() || this.getLower() > 0)
257                 {
258                     // Can't template primitive values, Objects only. Convert to wrapped.
259                     type = this.getType().getWrapperName();
260                     if (type == null)
261                     {
262                         // No wrapper name configured
263                         type = this.getType().getFullyQualifiedName();
264                     }
265                 }
266                 // Allow List<Type[]> implementations.
267                 /*// Don't apply templating to modeled array types
268                 if (this.getType().isArrayType())
269                 {
270                     type = type.substring(0, type.length()-2);
271                 }*/
272                 /*Collection<GeneralizableElementFacade> specializations = this.getType().getAllSpecializations();
273                 if ((specializations != null && !specializations.isEmpty()))
274                 {
275                     name += "<? extends " + type + '>';
276                 }
277                 else
278                 {*/
279                     name += '<' + type + '>';
280                 /*}*/
281             }
282         }
283         if (name == null && this.handleGetType() != null)
284         {
285             name = this.getType().getFullyQualifiedName();
286             // Special case: lower bound overrides primitive/wrapped type declaration
287             // TODO Apply to all primitive types, not just booleans. This is a special case because of is/get Getters.
288             if (this.getType().isBooleanType())
289             {
290                 // Datatypes will be inconsistent with multiplicity but identifier attributes shouldn't be changed automatically
291                 if (this.getType().isPrimitive() && this.getLower() < 1 &&
292                     (!(this instanceof EntityAttribute) || !((EntityAttribute) this).isIdentifier()))
293                 {
294                     // Type is optional, should not be primitive
295                     name = this.getType().getWrapperName();
296                     if (name == null)
297                     {
298                         // No wrapper name configured
299                         name = this.getType().getFullyQualifiedName();
300                     }
301                 }
302                 /*else //if (this.getType().isPrimitive())
303                 {
304                     // Type is required, should not be wrapped
305                 }*/
306             }
307         }
308         return name;
309     }
310 
311     /**
312      * @see org.andromda.metafacades.uml.AttributeFacade#isOrdered()
313      */
314     @Override
315     protected boolean handleIsOrdered()
316     {
317         return this.metaObject.isOrdered();
318     }
319 
320     /**
321      * @see org.andromda.metafacades.uml.AttributeFacade#isUnique()
322      */
323     @Override
324     protected boolean handleIsUnique()
325     {
326         return this.metaObject.isUnique() || this.hasStereotype(UMLProfile.STEREOTYPE_UNIQUE);
327     }
328 
329     /**
330      * @see org.andromda.metafacades.uml.AttributeFacade#getOwner()
331      */
332     @Override
333     protected Class handleGetOwner()
334     {
335         // This is sure for attribute
336         return this.metaObject.getClass_();
337     }
338 
339     /**
340      * @see org.andromda.core.metafacade.MetafacadeBase#getValidationOwner()
341      */
342     @Override
343     public Object getValidationOwner()
344     {
345         return this.getOwner();
346     }
347 
348     /**
349      * @see org.andromda.metafacades.uml.AttributeFacade#getType()
350      */
351     @Override
352     protected Type handleGetType()
353     {
354         return this.metaObject.getType();
355     }
356 
357     /**
358      * @see org.andromda.metafacades.uml.AttributeFacade#getEnumeration()
359      */
360     @Override
361     protected EnumerationFacade handleGetEnumeration()
362     {
363         return (EnumerationFacade)(this.isEnumerationLiteral() ? this.getOwner() : null);
364     }
365 
366     /**
367      * @see org.andromda.metafacades.emf.uml22.AttributeFacadeLogic#handleIsDefaultValuePresent()
368      */
369     @Override
370     protected boolean handleIsDefaultValuePresent()
371     {
372         return StringUtils.isNotBlank(this.getDefaultValue());
373     }
374 
375     /**
376      * Overridden to provide different handling of the name if this attribute represents a literal.
377      *
378      * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
379      */
380     @Override
381     protected String handleGetName()
382     {
383         final String mask = String.valueOf(this.getConfiguredProperty(
384             // http://andromda.sourceforge.net/jira/browse/UMLMETA-88
385             this.getOwner() instanceof EnumerationFacade && !this.isEnumerationMember()
386                 ? UMLMetafacadeProperties.ENUMERATION_LITERAL_NAME_MASK
387                 : UMLMetafacadeProperties.CLASSIFIER_PROPERTY_NAME_MASK ));
388 
389         String name = NameMasker.mask(super.handleGetName(), mask);
390         if (this.isMany() && this.isPluralizeAttributeNames() && !this.isEnumerationMember())
391         {
392             name = StringUtilsHelper.pluralize(name);
393         }
394 
395         return name;
396     }
397 
398     /**
399      * Indicates whether or not we should pluralize association end names.
400      *
401      * @return true/false
402      */
403     private boolean isPluralizeAttributeNames()
404     {
405         final Object value = this.getConfiguredProperty(UMLMetafacadeProperties.PLURALIZE_ATTRIBUTE_NAMES);
406         return value != null && Boolean.valueOf(String.valueOf(value));
407     }
408 
409     /*  protected boolean handleIsBindingDependenciesPresent()
410       {
411           // TODO: Implement this with Templates.
412           // This method has been overridden. Why ?
413           return false;
414       }
415 
416       protected boolean handleIsTemplateParametersPresent()
417       {
418           // TODO: This method has been overridden. Why ?
419           return false;
420       }
421 
422       protected void handleCopyTaggedValues(final ModelElementFacade element)
423       {
424           // TODO: This method has been overridden. Why ?
425       }
426 
427       protected Object handleGetTemplateParameter(final String parameterName)
428       {
429           // TODO: This method has been overridden. Why ?
430           return null;
431       }
432 
433       protected Collection handleGetTemplateParameters()
434       {
435           // TODO: This method has been overridden. Why ?
436           return null;
437       } */
438 
439     /**
440      * Get the UML upper multiplicity Not implemented for UML1.4
441      * @return int upperMultiplicity, based UML multiplicity, default 1
442      */
443     @Override
444     protected int handleGetUpper()
445     {
446         // MD11.5 Exports multiplicity as String
447         return UmlUtilities.parseMultiplicity(this.metaObject.getUpperValue(), 1);
448     }
449 
450     /**
451      * Get the UML lower multiplicity Not implemented for UML1.4
452      * @return int lowerMultiplicity, based on primitive/wrapped type and UML multiplicity, default 1
453      */
454     @Override
455     protected int handleGetLower()
456     {
457         // MD11.5 Exports multiplicity as String
458         return UmlUtilities.parseLowerMultiplicity(this.metaObject.getLowerValue(),
459             this.getType(),
460             ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_MULTIPLICITY)));
461     }
462 
463     /**
464      * Override to change private to public, since we provide accessors in generated code
465      * Allows for protected, package level visibility of accessors/mutators in the model
466      * @return String visibility
467      */
468     @Override
469     protected String handleGetVisibility()
470     {
471         String visibility = super.handleGetVisibility();
472         if (visibility==null || visibility.equals("private"))
473         {
474             visibility = "public";
475         }
476         return visibility;
477     }
478 
479     /**
480      * @see org.andromda.metafacades.emf.uml22.AttributeFacadeLogic#handleFindTaggedValue(String, boolean)
481      */
482     @Override
483     protected Object handleFindTaggedValue(
484         String name,
485         final boolean follow)
486     {
487         name = StringUtils.trimToEmpty(name);
488         Object value = this.findTaggedValue(name);
489         if (follow)
490         {
491             ClassifierFacade type = this.getType();
492             while (value == null && type != null)
493             {
494                 value = type.findTaggedValue(name);
495                 type = (ClassifierFacade)type.getGeneralization();
496             }
497         }
498         return value;
499     }
500 
501     /**
502      * @see org.andromda.metafacades.uml.AttributeFacade#isDerived()
503      */
504     @Override
505     protected boolean handleIsDerived()
506     {
507         return this.metaObject.isDerived();
508     }
509 }