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