View Javadoc
1   package org.andromda.metafacades.emf.uml22;
2   
3   import org.andromda.metafacades.uml.NameMasker;
4   import org.andromda.metafacades.uml.TypeMappings;
5   import org.andromda.metafacades.uml.UMLMetafacadeProperties;
6   import org.andromda.metafacades.uml.UMLMetafacadeUtils;
7   import org.andromda.metafacades.uml.UMLProfile;
8   import org.andromda.utils.StringUtilsHelper;
9   import org.apache.commons.lang.BooleanUtils;
10  import org.apache.commons.lang.ObjectUtils;
11  import org.apache.commons.lang.StringUtils;
12  import org.eclipse.uml2.uml.Activity;
13  import org.eclipse.uml2.uml.Element;
14  import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
15  import org.eclipse.uml2.uml.Operation;
16  import org.eclipse.uml2.uml.Parameter;
17  import org.eclipse.uml2.uml.ParameterDirectionKind;
18  import org.eclipse.uml2.uml.ParameterEffectKind;
19  import org.eclipse.uml2.uml.Type;
20  
21  /**
22   * MetafacadeLogic implementation for
23   * org.andromda.metafacades.uml.ParameterFacade.
24   *
25   * @see org.andromda.metafacades.uml.ParameterFacade
26   * @author Bob Fields
27   */
28  public class ParameterFacadeLogicImpl
29      extends ParameterFacadeLogic
30  {
31      private static final long serialVersionUID = 34L;
32      /**
33       * @param metaObjectIn
34       * @param context
35       */
36      public ParameterFacadeLogicImpl(
37          final Parameter metaObjectIn,
38          final String context)
39      {
40          super(metaObjectIn, context);
41      }
42  
43      /**
44       * @see org.andromda.metafacades.uml.ParameterFacade#getDefaultValue()
45       */
46      @Override
47      protected String handleGetDefaultValue()
48      {
49          String defaultValue = this.metaObject.getDefault();
50          // Put single or double quotes around default in case modeler forgot to do it. Most templates
51          // declare Type parameter = $parameter.defaultValue, requiring quotes around the value
52          if (StringUtils.isNotBlank(defaultValue) && !this.handleIsMany())
53          {
54              final String typeName = this.metaObject.getType().getName();
55              if ("String".equals(typeName) && defaultValue.indexOf('"')<0)
56              {
57                  defaultValue = '"' + defaultValue + '"';
58              }
59              else if (("char".equals(typeName) || "Character".equals(typeName))
60                  && defaultValue.indexOf('\'')<0)
61              {
62                  defaultValue = "'" + defaultValue.charAt(0) + '\'';
63              }
64          }
65          if (defaultValue==null) {defaultValue="";}
66          return defaultValue;
67      }
68  
69      /**
70       * Overridden to provide name masking.
71       *
72       * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
73       */
74      @Override
75      protected String handleGetName()
76      {
77          final String nameMask = String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.PARAMETER_NAME_MASK));
78          String name = NameMasker.mask(
79              super.handleGetName(),
80              nameMask);
81          if (this.handleIsMany() && this.isPluralizeParameterNames())
82          {
83              name = StringUtilsHelper.pluralize(name);
84          }
85  
86          return name;
87      }
88  
89      /**
90       * Indicates whether or not we should pluralize parameter names if parameter[*].
91       *
92       * @return true/false
93       */
94      private boolean isPluralizeParameterNames()
95      {
96          final Object value = this.getConfiguredProperty(UMLMetafacadeProperties.PLURALIZE_PARAMETER_NAMES);
97          return value != null && Boolean.valueOf(String.valueOf(value));
98      }
99  
100     /**
101      * @return this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED
102      * @see org.andromda.metafacades.uml.ParameterFacade#isMany()
103      */
104     protected boolean handleIsMany()
105     {
106         // Because of MD11.5 (their multiplicity are String), we cannot use
107         // isMultiValued()
108         return this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED
109         || (this.getType() != null && (this.getType().isArrayType() || this.getType().isCollectionType()));
110     }
111 
112     /**
113      * UML2 Only: Returns "NONE" if no effect specified.
114      * @see org.andromda.metafacades.uml.ParameterFacade#isException()
115      */
116     @Override
117     public String handleGetEffect()
118     {
119         final ParameterEffectKind effect = this.metaObject.getEffect();
120         if (effect==null)
121         {
122             return "NONE";
123         }
124         return effect.getLiteral();
125         //return effect.getName();
126     }
127 
128     /**
129      * UML2 Only: Returns false always.
130      * @see org.andromda.metafacades.uml.ParameterFacade#isException()
131      */
132     @Override
133     public boolean handleIsException()
134     {
135         return this.metaObject.isException();
136     }
137 
138     /**
139      * @see org.andromda.metafacades.uml.ParameterFacade#isOrdered()
140      */
141     @Override
142     protected boolean handleIsOrdered()
143     {
144         return this.metaObject.isOrdered();
145     }
146 
147     /**
148      * @see org.andromda.metafacades.uml.ParameterFacade#isUnique()
149      */
150     @Override
151     protected boolean handleIsUnique()
152     {
153         return this.metaObject.isUnique();
154     }
155 
156     /**
157      * @see org.andromda.metafacades.uml.ParameterFacade#isReturn()
158      */
159     @Override
160     protected boolean handleIsReturn()
161     {
162         return this.metaObject.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL);
163     }
164 
165     /**
166      * @see org.andromda.metafacades.uml.ParameterFacade#isRequired()
167      */
168     @Override
169     protected boolean handleIsRequired()
170     {
171         return !this.hasStereotype(UMLProfile.STEREOTYPE_NULLABLE) && this.getLower() >= 1;
172     }
173 
174     /**
175      * @see org.andromda.metafacades.uml.ParameterFacade#getGetterName()
176      */
177     @Override
178     protected String handleGetGetterName()
179     {
180         return UMLMetafacadeUtils.getGetterPrefix(this.getType(), this.getLower()) + StringUtils.capitalize(this.handleGetName());
181     }
182 
183     /**
184      * @see org.andromda.metafacades.uml.ParameterFacade#getSetterName()
185      */
186     @Override
187     protected String handleGetSetterName()
188     {
189         return "set" + StringUtils.capitalize(this.handleGetName());
190     }
191 
192     /**
193      * @see org.andromda.metafacades.uml.ParameterFacade#isReadable()
194      */
195     @Override
196     protected boolean handleIsReadable()
197     {
198         return this.isInParameter() || this.isInoutParameter();
199     }
200 
201     /**
202      * @see org.andromda.metafacades.uml.ParameterFacade#isWritable()
203      */
204     @Override
205     protected boolean handleIsWritable()
206     {
207         return this.isOutParameter() || this.isInoutParameter();
208     }
209 
210     /**
211      * @see org.andromda.metafacades.uml.ParameterFacade#isDefaultValuePresent()
212      */
213     @Override
214     protected boolean handleIsDefaultValuePresent()
215     {
216         return StringUtils.isNotBlank(this.getDefaultValue());
217     }
218 
219     /**
220      * @see org.andromda.metafacades.uml.ParameterFacade#isInParameter()
221      */
222     @Override
223     protected boolean handleIsInParameter()
224     {
225         return this.metaObject.getDirection().equals(ParameterDirectionKind.IN_LITERAL);
226     }
227 
228     /**
229      * @see org.andromda.metafacades.uml.ParameterFacade#isOutParameter()
230      */
231     @Override
232     protected boolean handleIsOutParameter()
233     {
234         return this.metaObject.getDirection().equals(ParameterDirectionKind.OUT_LITERAL);
235     }
236 
237     /**
238      * @see org.andromda.metafacades.uml.ParameterFacade#isInoutParameter()
239      */
240     @Override
241     protected boolean handleIsInoutParameter()
242     {
243         return this.metaObject.getDirection().equals(ParameterDirectionKind.INOUT_LITERAL);
244     }
245 
246     /**
247      * @see org.andromda.metafacades.uml.ParameterFacade#getOperation()
248      */
249     @Override
250     protected Operation handleGetOperation()
251     {
252         final Object owner = this.metaObject.getOwner();
253         if (owner instanceof Operation)
254         {
255             return (Operation) owner;
256         }
257         return null;
258     }
259 
260     /**
261      * @see org.andromda.metafacades.uml.ParameterFacade#getEvent()
262      */
263     @Override
264     protected Activity handleGetEvent()
265     {
266         final Element owner = this.metaObject.getOwner();
267         if (owner instanceof Activity)
268         {
269             return (Activity)owner;
270         }
271         return null;
272     }
273 
274     /**
275      * @see org.andromda.metafacades.uml.ParameterFacade#getType()
276      */
277     @Override
278     protected Type handleGetType()
279     {
280         return this.metaObject.getType();
281     }
282 
283     private String getTemplatingType()
284     {
285         String type = null;
286         if (BooleanUtils.toBoolean(
287                 ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING)))
288                 && this.getType() != null)
289         {
290             type = this.getType().getFullyQualifiedName();
291             if (this.getType().isPrimitive())
292             {
293                 // Can't template primitive values, Objects only. Convert to wrapped.
294                 type = this.getType().getWrapperName();
295             }
296             // Allow List<Type[]> implementations.
297             /*// Don't apply templating to modeled array types
298             if (this.getType().isArrayType())
299             {
300                 type = type.substring(0, type.length()-2);
301             }*/
302         }
303         return type;
304     }
305 
306     /**
307      * @see org.andromda.metafacades.uml.ParameterFacade#getGetterSetterTypeName()
308      */
309     @Override
310     protected String handleGetGetterSetterTypeName()
311     {
312         String name = null;
313         if (this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED)
314         {
315             final TypeMappings mappings = this.getLanguageMappings();
316             if (this.handleIsUnique())
317             {
318                 name =
319                     this.handleIsOrdered() ? mappings.getTo(UMLProfile.ORDERED_SET_TYPE_NAME)
320                                      : mappings.getTo(UMLProfile.SET_TYPE_NAME);
321             }
322             else
323             {
324                 name =
325                     this.handleIsOrdered() ? mappings.getTo(UMLProfile.LIST_TYPE_NAME)
326                                      : mappings.getTo(UMLProfile.COLLECTION_TYPE_NAME);
327             }
328 
329             // set this attribute's type as a template parameter if required
330             final String type=getTemplatingType();
331             if(type != null)
332             {
333                 /*Collection<GeneralizableElementFacade> specializations = this.handleGetType().getAllSpecializations();
334                 if ((specializations != null && !specializations.isEmpty()))
335                 {
336                     name += "<? extends " + type + '>';
337                 }
338                 else
339                 {*/
340                 name += '<' + type + '>';
341                 //}
342             }
343         }
344         if (name == null && this.getType() != null)
345         {
346             name = this.getType().getFullyQualifiedName();
347             // Special case: lower bound overrides primitive/wrapped type declaration
348             // TODO Apply to all primitive types, not just booleans. This is a special case because of is/get Getters.
349             if (this.getType().isBooleanType())
350             {
351                 if (this.getType().isPrimitive() && this.getLower() < 1)
352                 {
353                     // Type is optional, should not be primitive
354                     name = StringUtils.capitalize(name);
355                 }
356                 else if (!this.getType().isPrimitive() && this.getLower() > 0)
357                 {
358                     // Type is required, should not be wrapped
359                     name = StringUtils.uncapitalize(name);
360                 }
361             }
362         }
363         return name;
364     }
365 
366     /**
367      * @see org.andromda.metafacades.uml.ParameterFacade#getGetterSetterTypeNameImpl()
368      */
369     @Override
370     protected String handleGetGetterSetterTypeNameImpl()
371     {
372         String nameImpl = null;
373         if (this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED)
374         {
375             final TypeMappings mappings = this.getLanguageMappings();
376             if (this.handleIsUnique())
377             {
378                 nameImpl =
379                     this.handleIsOrdered() ? mappings.getTo(UMLProfile.ORDERED_SET_IMPL_TYPE_NAME)
380                                      : mappings.getTo(UMLProfile.SET_IMPL_TYPE_NAME);
381             }
382             else
383             {
384                 nameImpl =
385                     this.handleIsOrdered() ? mappings.getTo(UMLProfile.LIST_IMPL_TYPE_NAME)
386                                      : mappings.getTo(UMLProfile.COLLECTION_IMPL_TYPE_NAME);
387             }
388             // set this attribute's type as a template parameter if required
389             final String type=getTemplatingType();
390             if(type != null)
391             {
392                 nameImpl += '<' + type + '>';
393             }
394         }
395         if (nameImpl == null )
396         {
397             nameImpl = getGetterSetterTypeName();
398         }
399         return nameImpl;
400     }
401 
402     /**
403      * @see org.andromda.core.metafacade.MetafacadeBase#getValidationOwner()
404      */
405     @Override
406     public Object getValidationOwner()
407     {
408         Object owner = this.getOperation();
409         if (owner == null)
410         {
411             owner = this.getEvent();
412         }
413         return owner;
414     }
415 
416     /**
417      * Get the UML upper multiplicity
418      * @return int upperMultiplicity, based on UML multiplicity, default 1
419      */
420     @Override
421     protected int handleGetUpper()
422     {
423         return UmlUtilities.parseMultiplicity(this.metaObject.getUpperValue(), 1);
424     }
425 
426     /**
427      * Retrieve the default value for lower multiplicity from configured property defaultMultiplicity.
428      *
429      * @return 1/0
430      */
431     @SuppressWarnings("unused")
432     private int getDefaultMultiplicity()
433     {
434         final Object value = this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_MULTIPLICITY);
435         return (value != null ? Integer.valueOf(String.valueOf(value)).intValue() : 1);
436     }
437 
438     /**
439      * Get the UML lower multiplicity
440      * @return int lowerMultiplicity, based on primitive/wrapped type and UML multiplicity, default 1
441      */
442     @Override
443     protected int handleGetLower()
444     {
445         return UmlUtilities.parseLowerMultiplicity(this.metaObject.getLowerValue(),
446                 this.getType(),
447                 ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_MULTIPLICITY)));
448     }
449 }