001package org.andromda.metafacades.emf.uml22;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Iterator;
006import java.util.LinkedHashSet;
007import org.andromda.metafacades.uml.ClassifierFacade;
008import org.andromda.metafacades.uml.ConstraintFacade;
009import org.andromda.metafacades.uml.DependencyFacade;
010import org.andromda.metafacades.uml.MetafacadeUtils;
011import org.andromda.metafacades.uml.ModelElementFacade;
012import org.andromda.metafacades.uml.NameMasker;
013import org.andromda.metafacades.uml.OperationFacade;
014import org.andromda.metafacades.uml.ParameterFacade;
015import org.andromda.metafacades.uml.TypeMappings;
016import org.andromda.metafacades.uml.UMLMetafacadeProperties;
017import org.andromda.metafacades.uml.UMLProfile;
018import org.andromda.translation.ocl.ExpressionKinds;
019import org.apache.commons.collections.CollectionUtils;
020import org.apache.commons.collections.Predicate;
021import org.apache.commons.collections.Transformer;
022import org.apache.commons.lang.BooleanUtils;
023import org.apache.commons.lang.ObjectUtils;
024import org.apache.commons.lang.StringUtils;
025import org.apache.log4j.Logger;
026import org.eclipse.uml2.uml.CallConcurrencyKind;
027import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
028import org.eclipse.uml2.uml.Operation;
029import org.eclipse.uml2.uml.Parameter;
030import org.eclipse.uml2.uml.ParameterDirectionKind;
031import org.eclipse.uml2.uml.Type;
032
033/**
034 * MetafacadeLogic implementation for
035 * org.andromda.metafacades.uml.OperationFacade.
036 *
037 * @see org.andromda.metafacades.uml.OperationFacade
038 * @author Bob Fields
039 */
040public class OperationFacadeLogicImpl
041    extends OperationFacadeLogic
042{
043    private static final long serialVersionUID = 34L;
044    /**
045     * The logger instance.
046     */
047    private static final Logger LOGGER = Logger.getLogger(OperationFacadeLogicImpl.class);
048
049    /**
050     * @param metaObject
051     * @param context
052     */
053    public OperationFacadeLogicImpl(
054        final Operation metaObject,
055        final String context)
056    {
057        super(metaObject, context);
058    }
059
060    /**
061     * Not yet implemented, always returns null. To implement: walk through the
062     * related elements from the Sequence Diagram or OCL Body in the UML model to produce compilable code.
063     * @return null
064     * @see org.andromda.metafacades.uml.OperationFacade#getMethodBody()
065     */
066    @Override
067    protected String handleGetMethodBody()
068    {
069        return null;
070    }
071
072    /**
073     * Overridden to provide name masking.
074     *
075     * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
076     */
077    @Override
078    protected String handleGetName()
079    {
080        final String nameMask = String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.OPERATION_NAME_MASK));
081        return NameMasker.mask(
082            super.handleGetName(),
083            nameMask);
084    }
085
086    /**
087     * @see org.andromda.metafacades.uml.OperationFacade#getSignature()
088     */
089    @Override
090    protected String handleGetSignature()
091    {
092        return this.getSignature(true);
093    }
094
095    /**
096     * @see org.andromda.metafacades.uml.OperationFacade#getCall()
097     */
098    @Override
099    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}