View Javadoc
1   package org.andromda.metafacades.emf.uml22;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Iterator;
6   import java.util.LinkedHashSet;
7   import org.andromda.metafacades.uml.ClassifierFacade;
8   import org.andromda.metafacades.uml.ConstraintFacade;
9   import org.andromda.metafacades.uml.DependencyFacade;
10  import org.andromda.metafacades.uml.MetafacadeUtils;
11  import org.andromda.metafacades.uml.ModelElementFacade;
12  import org.andromda.metafacades.uml.NameMasker;
13  import org.andromda.metafacades.uml.OperationFacade;
14  import org.andromda.metafacades.uml.ParameterFacade;
15  import org.andromda.metafacades.uml.TypeMappings;
16  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
17  import org.andromda.metafacades.uml.UMLProfile;
18  import org.andromda.translation.ocl.ExpressionKinds;
19  import org.apache.commons.collections.CollectionUtils;
20  import org.apache.commons.collections.Predicate;
21  import org.apache.commons.collections.Transformer;
22  import org.apache.commons.lang.BooleanUtils;
23  import org.apache.commons.lang.ObjectUtils;
24  import org.apache.commons.lang.StringUtils;
25  import org.apache.log4j.Logger;
26  import org.eclipse.uml2.uml.CallConcurrencyKind;
27  import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
28  import org.eclipse.uml2.uml.Operation;
29  import org.eclipse.uml2.uml.Parameter;
30  import org.eclipse.uml2.uml.ParameterDirectionKind;
31  import org.eclipse.uml2.uml.Type;
32  
33  /**
34   * MetafacadeLogic implementation for
35   * org.andromda.metafacades.uml.OperationFacade.
36   *
37   * @see org.andromda.metafacades.uml.OperationFacade
38   * @author Bob Fields
39   */
40  public class OperationFacadeLogicImpl
41      extends OperationFacadeLogic
42  {
43      private static final long serialVersionUID = 34L;
44      /**
45       * The logger instance.
46       */
47      private static final Logger LOGGER = Logger.getLogger(OperationFacadeLogicImpl.class);
48  
49      /**
50       * @param metaObject
51       * @param context
52       */
53      public OperationFacadeLogicImpl(
54          final Operation metaObject,
55          final String context)
56      {
57          super(metaObject, context);
58      }
59  
60      /**
61       * Not yet implemented, always returns null. To implement: walk through the
62       * related elements from the Sequence Diagram or OCL Body in the UML model to produce compilable code.
63       * @return null
64       * @see org.andromda.metafacades.uml.OperationFacade#getMethodBody()
65       */
66      @Override
67      protected String handleGetMethodBody()
68      {
69          return null;
70      }
71  
72      /**
73       * Overridden to provide name masking.
74       *
75       * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
76       */
77      @Override
78      protected String handleGetName()
79      {
80          final String nameMask = String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.OPERATION_NAME_MASK));
81          return NameMasker.mask(
82              super.handleGetName(),
83              nameMask);
84      }
85  
86      /**
87       * @see org.andromda.metafacades.uml.OperationFacade#getSignature()
88       */
89      @Override
90      protected String handleGetSignature()
91      {
92          return this.getSignature(true);
93      }
94  
95      /**
96       * @see org.andromda.metafacades.uml.OperationFacade#getCall()
97       */
98      @Override
99      protected String handleGetCall()
100     {
101         return this.getCall(this.handleGetName());
102     }
103 
104     /**
105      * Constructs the operation call with the given <code>name</code>
106      *
107      * @param name
108      *            the name form which to construct the operation call.
109      * @return the operation call.
110      */
111     private String getCall(final String name)
112     {
113         final StringBuilder buffer = new StringBuilder(name);
114         buffer.append('(');
115         buffer.append(this.getArgumentNames());
116         buffer.append(')');
117         return buffer.toString();
118     }
119 
120     /**
121      * @see org.andromda.metafacades.uml.OperationFacade#getTypedArgumentList()
122      */
123     @Override
124     protected String handleGetTypedArgumentList()
125     {
126         return this.getTypedArgumentList(true);
127     }
128 
129     private String getTypedArgumentList(final boolean withArgumentNames)
130     {
131         // TODO: Possible covariant of the method 'getTypedArgumentList' defined in the class 'OperationFacadeLogic'
132         return MetafacadeUtils.getTypedArgumentList(
133             this.getArguments(),
134             withArgumentNames,
135             null);
136     }
137 
138     /**
139      * @see org.andromda.metafacades.uml.OperationFacade#isStatic()
140      */
141     @Override
142     protected boolean handleIsStatic()
143     {
144         return this.metaObject.isStatic();
145     }
146 
147     /**
148      * @see org.andromda.metafacades.uml.OperationFacade#isAbstract()
149      */
150     @Override
151     protected boolean handleIsAbstract()
152     {
153         return this.metaObject.isAbstract();
154     }
155 
156     /**
157      * @see org.andromda.metafacades.uml.OperationFacade#getExceptionList()
158      */
159     @Override
160     protected String handleGetExceptionList()
161     {
162         return this.getExceptionList(null);
163     }
164 
165     /**
166      * Finds both exceptions and exception dependency references
167      * @see org.andromda.metafacades.uml.OperationFacade#getExceptions()
168      */
169     @Override
170     protected Collection handleGetExceptions()
171     {
172         final Collection<DependencyFacade> exceptions = new LinkedHashSet<DependencyFacade>();
173 
174         // finds both exceptions and exception references
175         final class ExceptionFilter
176                 implements Predicate
177         {
178             public boolean evaluate(final Object object)
179             {
180                 boolean hasException = object instanceof DependencyFacade;
181                 if (hasException)
182                 {
183                     final DependencyFacade dependency = (DependencyFacade)object;
184                     // first check for exception references
185                     hasException = dependency.hasStereotype(UMLProfile.STEREOTYPE_EXCEPTION_REF);
186 
187                     // if there wasn't any exception reference
188                     // now check for actual exceptions
189                     if (!hasException)
190                     {
191                         final ModelElementFacade targetElement = dependency.getTargetElement();
192                         hasException = targetElement != null && targetElement.hasStereotype(
193                                 UMLProfile.STEREOTYPE_EXCEPTION);
194                     }
195                 }
196                 return hasException;
197             }
198         }
199 
200         // first get any dependencies on this operation's
201         // owner (because these will represent the default exception(s))
202         final Collection<DependencyFacade> ownerDependencies = new ArrayList<DependencyFacade>(this.getOwner().getSourceDependencies());
203         if (!ownerDependencies.isEmpty())
204         {
205             CollectionUtils.filter(ownerDependencies, new ExceptionFilter());
206             exceptions.addAll(ownerDependencies);
207         }
208 
209         final Collection<DependencyFacade> operationDependencies = new ArrayList<DependencyFacade>(this.getSourceDependencies());
210         // now get any exceptions directly on the operation
211         if (!operationDependencies.isEmpty())
212         {
213             CollectionUtils.filter(operationDependencies, new ExceptionFilter());
214             exceptions.addAll(operationDependencies);
215         }
216 
217         // now transform the dependency(s) to the actual exception(s)
218         CollectionUtils.transform(exceptions, new Transformer()
219         {
220             public Object transform(final Object object)
221             {
222                 if (object == null) return null;
223                 return ((DependencyFacade)object).getTargetElement();
224             }
225         });
226 
227         // finally add in any members of the UML2 RaisedException list
228         // (the 'proper' UML2 way of doing exceptions .. or at least one way).
229         final Collection<Type> raisedExceptions = this.metaObject.getRaisedExceptions();
230         exceptions.addAll(this.shieldedElements(raisedExceptions));
231 
232         return exceptions;
233     }
234 
235 
236     /**
237      * @see org.andromda.metafacades.uml.OperationFacade#isReturnTypePresent()
238      */
239     @Override
240     protected boolean handleIsReturnTypePresent()
241     {
242         boolean hasReturnType = false;
243         if (this.getReturnType() != null)
244         {
245             hasReturnType = !("void".equalsIgnoreCase(StringUtils.trimToEmpty(this.getReturnType().getFullyQualifiedName()))
246                 || StringUtils.trimToEmpty(this.getReturnType().getFullyQualifiedName(true)).equals(UMLProfile.VOID_TYPE_NAME));
247         }
248         if (LOGGER.isDebugEnabled())
249         {
250             final String rtnFQN = this.getReturnType().getFullyQualifiedName(true);
251             final boolean voidType = "void".equalsIgnoreCase(StringUtils.trimToEmpty(this.getReturnType().getFullyQualifiedName()));
252             final String voidRtn = this.getReturnType().getFullyQualifiedName();
253             LOGGER.debug("OperationFacadeLogicImpl.handleIsReturnTypePresent rtnFQN=" + rtnFQN + " voidType=" + voidType + " voidRtn=" + voidRtn + " hasReturnType=" + hasReturnType);
254         }
255         return hasReturnType;
256     }
257 
258     /**
259      * @see org.andromda.metafacades.uml.OperationFacade#isExceptionsPresent()
260      */
261     @Override
262     protected boolean handleIsExceptionsPresent()
263     {
264         return !this.getExceptions().isEmpty();
265     }
266 
267     /**
268      * @see org.andromda.metafacades.uml.OperationFacade#getArgumentNames()
269      */
270     @Override
271     protected String handleGetArgumentNames()
272     {
273         final StringBuilder buffer = new StringBuilder();
274 
275         final Iterator<Parameter> iterator = this.metaObject.getOwnedParameters().iterator();
276 
277         boolean commaNeeded = false;
278         final String comma = ", ";
279         while (iterator.hasNext())
280         {
281             final Parameter parameter = iterator.next();
282             if (!parameter.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL))
283             {
284                 if (commaNeeded)
285                 {
286                     buffer.append(comma);
287                 }
288                 final ParameterFacade facade = (ParameterFacade)this.shieldedElement(parameter);
289                 buffer.append(facade.getName());
290                 commaNeeded = true;
291             }
292         }
293         return buffer.toString();
294     }
295 
296     /**
297      * @see org.andromda.metafacades.uml.OperationFacade#getArgumentTypeNames()
298      */
299     @Override
300     protected String handleGetArgumentTypeNames()
301     {
302         final StringBuilder buffer = new StringBuilder();
303 
304         final Iterator<Parameter> iterator = this.metaObject.getOwnedParameters().iterator();
305 
306         boolean commaNeeded = false;
307         while (iterator.hasNext())
308         {
309             final Parameter parameter = iterator.next();
310 
311             if (!parameter.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL))
312             {
313                 if (commaNeeded)
314                 {
315                     buffer.append(", ");
316                 }
317                 final ParameterFacade facade = (ParameterFacade)this.shieldedElement(parameter);
318                 buffer.append(facade.getType().getFullyQualifiedName());
319                 commaNeeded = true;
320             }
321         }
322         return buffer.toString();
323     }
324 
325     /**
326      * @see org.andromda.metafacades.uml.OperationFacade#isQuery()
327      */
328     @Override
329     protected boolean handleIsQuery()
330     {
331         return this.metaObject.isQuery();
332     }
333 
334     /**
335      * @see org.andromda.metafacades.uml.OperationFacade#getConcurrency()
336      */
337     @Override
338     protected String handleGetConcurrency()
339     {
340         String concurrency = null;
341 
342         final CallConcurrencyKind concurrencyKind = this.metaObject.getConcurrency();
343         if (concurrencyKind == null || concurrencyKind.equals(CallConcurrencyKind.CONCURRENT_LITERAL))
344         {
345             concurrency = "concurrent";
346         }
347         else if (concurrencyKind.equals(CallConcurrencyKind.GUARDED_LITERAL))
348         {
349             concurrency = "guarded";
350         }
351         else// CallConcurrencyKindEnum.CCK_SEQUENTIAL
352         {
353             concurrency = "sequential";
354         }
355 
356         final TypeMappings languageMappings = this.getLanguageMappings();
357         if (languageMappings != null)
358         {
359             concurrency = languageMappings.getTo(concurrency);
360         }
361 
362         return concurrency;
363     }
364 
365     /**
366      * Gets the pattern for constructing the precondition name.
367      *
368      * @return the precondition pattern.
369      */
370     private String getPreconditionPattern()
371     {
372         return String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.PRECONDITION_NAME_PATTERN));
373     }
374 
375     /**
376      * Gets the pattern for constructing the postcondition name.
377      *
378      * @return the postcondition pattern.
379      */
380     private String getPostconditionPattern()
381     {
382         return String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.POSTCONDITION_NAME_PATTERN));
383     }
384 
385     /**
386      * @see org.andromda.metafacades.uml.OperationFacade#getPreconditionName()
387      */
388     @Override
389     protected String handleGetPreconditionName()
390     {
391         return this.getPreconditionPattern().replaceAll(
392             "\\{0\\}",
393             this.handleGetName());
394     }
395 
396     /**
397      * @see org.andromda.metafacades.uml.OperationFacade#getPostconditionName()
398      */
399     @Override
400     protected String handleGetPostconditionName()
401     {
402         return this.getPostconditionPattern().replaceAll(
403             "\\{0\\}",
404             this.handleGetName());
405     }
406 
407     /**
408      * @see org.andromda.metafacades.uml.OperationFacade#getPreconditionSignature()
409      */
410     @Override
411     protected String handleGetPreconditionSignature()
412     {
413         return MetafacadeUtils.getSignature(
414             this.getPreconditionName(),
415             this.getArguments(),
416             true,
417             null);
418     }
419 
420     /**
421      * @see org.andromda.metafacades.uml.OperationFacade#getPreconditionCall()
422      */
423     @Override
424     protected String handleGetPreconditionCall()
425     {
426         return this.getCall(this.getPreconditionName());
427     }
428 
429     /**
430      * @see org.andromda.metafacades.uml.OperationFacade#isPreconditionsPresent()
431      */
432     @Override
433     protected boolean handleIsPreconditionsPresent()
434     {
435         final Collection<ConstraintFacade> preconditions = this.getPreconditions();
436         return preconditions != null && !preconditions.isEmpty();
437     }
438 
439     /**
440      * @see org.andromda.metafacades.uml.OperationFacade#isPostconditionsPresent()
441      */
442     @Override
443     protected boolean handleIsPostconditionsPresent()
444     {
445         final Collection<ConstraintFacade> postconditions = this.getPostconditions();
446         return postconditions != null && !postconditions.isEmpty();
447     }
448 
449     /**
450      * @see org.andromda.metafacades.uml.OperationFacade#findTaggedValue(String,
451      *      boolean)
452      */
453     @Override
454     protected Object handleFindTaggedValue(
455         final String name,
456         final boolean follow)
457     {
458         final String trimName = StringUtils.trimToEmpty(name);
459         Object value = this.findTaggedValue(trimName);
460         if (follow)
461         {
462             ClassifierFacade type = this.getReturnType();
463             while (value == null && type != null)
464             {
465                 value = type.findTaggedValue(trimName);
466                 type = (ClassifierFacade)type.getGeneralization();
467             }
468         }
469         return value;
470     }
471 
472     /**
473      * @see org.andromda.metafacades.uml.OperationFacade#getExceptionList(String)
474      */
475     @Override
476     protected String handleGetExceptionList(String initialExceptions)
477     {
478         initialExceptions = StringUtils.trimToEmpty(initialExceptions);
479         final StringBuilder exceptionList = new StringBuilder(initialExceptions);
480         // TODO getExceptions = Collection<ClassifierFacade> or <ModelElementFacade>?
481         final Collection exceptions = this.getExceptions();
482         if (exceptions != null && !exceptions.isEmpty())
483         {
484             if (StringUtils.isNotBlank(initialExceptions))
485             {
486                 exceptionList.append(", ");
487             }
488             final Iterator exceptionIt = exceptions.iterator();
489             while (exceptionIt.hasNext())
490             {
491                 final ModelElementFacade exception = (ModelElementFacade)exceptionIt.next();
492                 exceptionList.append(exception.getFullyQualifiedName());
493                 if (exceptionIt.hasNext())
494                 {
495                     exceptionList.append(", ");
496                 }
497             }
498         }
499 
500         return exceptionList.toString();
501     }
502 
503     /**
504      * @see org.andromda.metafacades.uml.OperationFacade#getSignature(boolean)
505      */
506     @Override
507     protected String handleGetSignature(final boolean withArgumentNames)
508     {
509         return MetafacadeUtils.getSignature(
510             this.handleGetName(),
511             this.getArguments(),
512             withArgumentNames,
513             null);
514     }
515 
516     /**
517      * @see org.andromda.metafacades.uml.OperationFacade#getTypedArgumentList(String)
518      */
519     @Override
520     protected String handleGetTypedArgumentList(final String modifier)
521     {
522         return MetafacadeUtils.getTypedArgumentList(
523             this.getArguments(),
524             true,
525             modifier);
526     }
527 
528     /**
529      * @see org.andromda.metafacades.uml.OperationFacade#getSignature(String)
530      */
531     @Override
532     protected String handleGetSignature(final String argumentModifier)
533     {
534         return MetafacadeUtils.getSignature(
535             this.handleGetName(),
536             this.getArguments(),
537             true,
538             argumentModifier);
539     }
540 
541     /**
542      * @see org.andromda.metafacades.uml.OperationFacade#getOwner()
543      */
544     @Override
545     protected Object handleGetOwner()
546     {
547         Object obj = null;
548         // Fix from UML2, no longer calls getOwner to get the owning Class
549         if (this.metaObject.getInterface()!=null)
550         {
551             obj = this.metaObject.getInterface();
552         }
553         else if (this.metaObject.getDatatype()!=null)
554         {
555             obj = this.metaObject.getDatatype();
556         }
557         else
558         {
559             obj = this.metaObject.getClass_();
560         }
561         return obj;
562     }
563 
564     /**
565      * @see org.andromda.metafacades.uml.OperationFacade#getParameters()
566      */
567     @Override
568     protected Collection<Parameter> handleGetParameters()
569     {
570         final Collection<Parameter> params = new ArrayList<Parameter>(this.metaObject.getOwnedParameters());
571         params.add(this.metaObject.getReturnResult());
572         CollectionUtils.filter(
573             params,
574             new Predicate()
575             {
576                 public boolean evaluate(final Object object)
577                 {
578                     return object != null && !((Parameter)object).isException();
579                 }
580             });
581         return params;
582     }
583 
584     /**
585      * @see org.andromda.metafacades.uml.OperationFacade#getReturnType()
586      */
587     @Override
588     protected Type handleGetReturnType()
589     {
590         return this.metaObject.getType();
591     }
592 
593     /**
594      * @return this.getReturnType().getFullyQualifiedName()
595      * @see org.andromda.metafacades.uml.OperationFacade#getGetterSetterReturnTypeName()
596      */
597     protected String handleGetGetterSetterReturnTypeName()
598     {
599         String name = null;
600         final ClassifierFacade returnType = this.getReturnType();
601 
602         if (returnType!=null && (this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED))
603         {
604             final TypeMappings mappings = this.getLanguageMappings();
605             name =
606                 this.handleIsOrdered() ? mappings.getTo(UMLProfile.LIST_TYPE_NAME)
607                                  : mappings.getTo(UMLProfile.COLLECTION_TYPE_NAME);
608 
609             // set this attribute's type as a template parameter if required
610             if (BooleanUtils.toBoolean(
611                     ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING))))
612             {
613                 String type = returnType.getFullyQualifiedName();
614                 if (returnType.isPrimitive())
615                 {
616                     // Can't template primitive values, Objects only. Convert to wrapped.
617                     type = this.getReturnType().getWrapperName();
618                 }
619                 // Allow List<Type[]> implementations.
620                 /*// Don't apply templating to modeled array types
621                 if (returnType.isArrayType())
622                 {
623                     type = type.substring(0, type.length()-2);
624                 }*/
625                 /*Collection<GeneralizableElementFacade> specializations = returnType.getAllSpecializations();
626                 if ((specializations != null && !specializations.isEmpty()))
627                 {
628                     name += "<? extends " + type + '>';
629                 }
630                 else
631                 {*/
632                 name += '<' + type + '>';
633                 //}
634             }
635         }
636         if (name == null && returnType != null)
637         {
638             name = returnType.getFullyQualifiedName();
639             // Special case: lower bound overrides primitive/wrapped type declaration
640             // TODO Apply to all primitive types, not just booleans. This is a special case because of is/get Getters.
641             if (this.getReturnType().isBooleanType())
642             {
643                 if (this.getReturnType().isPrimitive() && (this.getLower() < 1))
644                 {
645                     // Type is optional, should not be primitive
646                     name = StringUtils.capitalize(name);
647                 }
648                 else if (!this.getReturnType().isPrimitive() && this.getLower() > 0)
649                 {
650                     // Type is required, should not be wrapped
651                     name = StringUtils.uncapitalize(name);
652                 }
653             }
654         }
655         return name;
656     }
657 
658     /**
659      * @return this.metaObject.isOrdered()
660      * @see org.andromda.metafacades.uml.OperationFacade#isOrdered()
661      */
662     protected boolean handleIsOrdered()
663     {
664         return this.metaObject.isOrdered();
665     }
666 
667     /**
668      * @return this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED
669      * @see org.andromda.metafacades.uml.OperationFacade#isMany()
670      */
671     protected boolean handleIsMany()
672     {
673         // Because of MD11.5 (their multiplicity are String), we cannot use
674         // isMultiValued()
675         // RJF3 True if either the operation is many or the return parameter is many
676         final ParameterFacade returnParameter = this.getReturnParameter();
677         // Parameter or parameter type may be null during model validation
678         final boolean returnMany = returnParameter!=null && returnParameter.getType()!=null &&
679            (returnParameter.getUpper() > 1 ||
680             returnParameter.getUpper() == LiteralUnlimitedNatural.UNLIMITED
681             || returnParameter.getType().isArrayType()
682             || returnParameter.getType().isCollectionType());
683         return returnMany || this.getUpper() > 1 || this.getUpper() == LiteralUnlimitedNatural.UNLIMITED;
684     }
685 
686     /**
687      * @see org.andromda.metafacades.uml.OperationFacade#getArguments()
688      */
689     @Override
690     protected Collection<Parameter> handleGetArguments()
691     {
692         final Collection<Parameter> arguments = new ArrayList<Parameter>(this.metaObject.getOwnedParameters());
693         CollectionUtils.filter(
694             arguments,
695             new Predicate()
696             {
697                 public boolean evaluate(final Object object)
698                 {
699                     final Parameter param = (Parameter)object;
700                     return !param.getDirection().equals(ParameterDirectionKind.RETURN_LITERAL) && !param.isException();
701                 }
702             });
703         return arguments;
704     }
705 
706     /**
707      * @see org.andromda.metafacades.uml.OperationFacade#getPreconditions()
708      */
709     @Override
710     protected Collection<ConstraintFacade> handleGetPreconditions()
711     {
712         return this.handleGetConstraints(ExpressionKinds.PRE);
713     }
714 
715     /**
716      * @see org.andromda.metafacades.uml.OperationFacade#getPostconditions()
717      */
718     @Override
719     protected Collection<ConstraintFacade> handleGetPostconditions()
720     {
721         return this.handleGetConstraints(ExpressionKinds.POST);
722     }
723 
724     /**
725      * @see org.andromda.core.metafacade.MetafacadeBase#getValidationOwner()
726      */
727     @Override
728     public Object getValidationOwner()
729     {
730         return this.getOwner();
731     }
732 
733     /**
734      * @see org.andromda.metafacades.uml.OperationFacade#findParameter(String)
735      */
736     @Override
737     protected ParameterFacade handleFindParameter(final String name)
738     {
739         return (ParameterFacade)this.shieldedElement(this.metaObject.getOwnedParameter(name, null));
740     }
741 
742     /**
743      * Get the UML upper multiplicity Not implemented for UML1.4
744      * @return multiplicity upperBound
745      */
746     @Override
747     protected int handleGetUpper()
748     {
749         // MD11.5 Exports multiplicity as String
750         return this.metaObject.getUpper();
751         //return UmlUtilities.parseMultiplicity(this.metaObject.getUpper(), 1);
752     }
753 
754     /**
755      * Get the UML lower multiplicity Not implemented for UML1.4
756      * @return multiplicity lowerBound
757      */
758     @Override
759     protected int handleGetLower()
760     {
761         // MD11.5 Exports multiplicity as String
762         return this.metaObject.getLower();
763         //return UmlUtilities.parseLowerMultiplicity(this.metaObject.getLower(),
764         //    (ClassifierFacade) this.getReturnType(), "0");
765             // ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_MULTIPLICITY)));
766     }
767 
768     /**
769      * Get the first UML2 ReturnResult parameter. Not implemented for UML1.4
770      * @return ReturnResult parameter
771      */
772     @Override
773     public ParameterFacade handleGetReturnParameter()
774     {
775         return (ParameterFacade)this.shieldedElement(this.metaObject.getReturnResult());
776     }
777 
778     /*
779      * Override to change private to public, since it makes no sense to have private operations in generated code
780      * Allows for protected, package level visibility of operations in the model
781      * @return String visibility
782     @Override
783     protected String handleGetVisibility()
784     {
785         String visibility = super.handleGetVisibility();
786         if (visibility==null || visibility.equals("private"))
787         {
788             visibility = "public";
789         }
790         return visibility;
791     }
792      */
793 
794     /**
795      * @see org.andromda.metafacades.uml.OperationFacade#isOverriding()
796      */
797     @Override
798     protected boolean handleIsOverriding()
799     {
800         return this.getOverriddenOperation() != null;
801     }
802 
803     /**
804      * @see org.andromda.metafacades.uml.OperationFacade#getOverriddenOperation()
805      */
806     @Override
807     protected OperationFacade handleGetOverriddenOperation()
808     {
809         OperationFacade overriddenOperation = null;
810 
811         final String signature = this.getSignature(false);
812 
813         ClassifierFacade ancestor = this.getOwner().getSuperClass();
814         while (overriddenOperation == null && ancestor != null)
815         {
816             for (final Iterator<OperationFacade> operationIterator = ancestor.getOperations().iterator();
817                  overriddenOperation == null && operationIterator.hasNext();)
818             {
819                 final OperationFacade ancestorOperation = operationIterator.next();
820                 if (signature.equals(ancestorOperation.getSignature(false)))
821                 {
822                     overriddenOperation = ancestorOperation;
823                 }
824             }
825 
826             ancestor = ancestor.getSuperClass();
827         }
828 
829         return overriddenOperation;
830     }
831 
832     /**
833      * @return this.metaObject.isLeaf()
834      * @see org.andromda.metafacades.uml.OperationFacade#isLeaf()
835      */
836     protected boolean handleIsLeaf()
837     {
838         return this.metaObject.isLeaf();
839     }
840 
841     /**
842      * @return this.metaObject.isUnique()
843      * @see org.andromda.metafacades.uml.OperationFacade#isUnique()
844      */
845     protected boolean handleIsUnique()
846     {
847         return this.metaObject.isUnique();
848     }
849 }