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 java.util.List;
8   import java.util.Set;
9   import org.andromda.metafacades.uml.AssociationEndFacade;
10  import org.andromda.metafacades.uml.AttributeFacade;
11  import org.andromda.metafacades.uml.ClassifierFacade;
12  import org.andromda.metafacades.uml.DependencyFacade;
13  import org.andromda.metafacades.uml.FilteredCollection;
14  import org.andromda.metafacades.uml.GeneralizableElementFacade;
15  import org.andromda.metafacades.uml.MetafacadeUtils;
16  import org.andromda.metafacades.uml.ModelElementFacade;
17  import org.andromda.metafacades.uml.NameMasker;
18  import org.andromda.metafacades.uml.OperationFacade;
19  import org.andromda.metafacades.uml.TypeMappings;
20  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
21  import org.andromda.metafacades.uml.UMLMetafacadeUtils;
22  import org.andromda.metafacades.uml.UMLProfile;
23  import org.apache.commons.collections.CollectionUtils;
24  import org.apache.commons.collections.Predicate;
25  import org.apache.commons.collections.Transformer;
26  import org.apache.commons.lang.StringUtils;
27  import org.apache.log4j.Logger;
28  import org.omg.uml.foundation.core.Abstraction;
29  import org.omg.uml.foundation.core.AssociationClass;
30  import org.omg.uml.foundation.core.Attribute;
31  import org.omg.uml.foundation.core.Classifier;
32  import org.omg.uml.foundation.core.DataType;
33  import org.omg.uml.foundation.core.Interface;
34  import org.omg.uml.foundation.core.Namespace;
35  import org.omg.uml.foundation.core.Operation;
36  
37  /**
38   * Metaclass facade implementation.
39   * @author Bob Fields
40   */
41  public class ClassifierFacadeLogicImpl
42      extends ClassifierFacadeLogic
43  {
44      private static final long serialVersionUID = 34L;
45      /**
46       * @param metaObject
47       * @param context
48       */
49      public ClassifierFacadeLogicImpl(
50          Classifier metaObject,
51          String context)
52      {
53          super(metaObject, context);
54      }
55  
56      /**
57       * The logger instance.
58       */
59      private static final Logger logger = Logger.getLogger(ClassifierFacadeLogicImpl.class);
60  
61      /**
62       * Overridden to provide name masking.
63       *
64       * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
65       */
66      @Override
67      protected String handleGetName()
68      {
69          final String nameMask =
70              String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.CLASSIFIER_NAME_MASK));
71          return NameMasker.mask(super.handleGetName(), nameMask);
72      }
73  
74      /**
75       * @see org.andromda.metafacades.uml14.ClassifierFacadeLogic#handleGetOperations()
76       */
77      protected List<Operation> handleGetOperations()
78      {
79          return new FilteredCollection(this.metaObject.getFeature())
80          {
81              private static final long serialVersionUID = 34L;
82              public boolean evaluate(Object object)
83              {
84                  return object instanceof org.omg.uml.foundation.core.Operation;
85              }
86          };
87      }
88  
89      /**
90       * Note: if this instance represents an actual class we resolve any realized interfaces recursively, in case this
91       * instance represents an interface we return only the owned operations.
92       *
93       * @see org.andromda.metafacades.uml.ClassifierFacade#getOperations()
94       */
95      @Override
96      protected Collection<Operation> handleGetImplementationOperations()
97      {
98          final Collection<Operation> operations = new LinkedHashSet();
99  
100         // add all of this classifier's operations
101         operations.addAll(new FilteredCollection(metaObject.getFeature())
102         {
103             private static final long serialVersionUID = 34L;
104             public boolean evaluate(Object object)
105             {
106                 return object instanceof Operation;
107             }
108         });
109 
110         if (!this.isInterface())
111         {
112             final Collection<ClassifierFacade> interfaces = this.getInterfaceAbstractions();
113             for (Iterator interfaceIterator = interfaces.iterator(); interfaceIterator.hasNext();)
114             {
115                 final ClassifierFacade interfaceElement = (ClassifierFacade)interfaceIterator.next();
116                 operations.addAll(resolveInterfaceOperationsRecursively(interfaceElement));
117             }
118         }
119 
120         return operations;
121     }
122 
123     private static Collection<Operation> resolveInterfaceOperationsRecursively(ClassifierFacade interfaceClassifier)
124     {
125         final Collection<Operation> operations = new LinkedHashSet(interfaceClassifier.getOperations()); // preserve ordering
126 
127         final Collection<GeneralizableElementFacade> generalizations = interfaceClassifier.getGeneralizations();
128         for (Iterator<GeneralizableElementFacade> generalizationIterator = generalizations.iterator(); generalizationIterator.hasNext();)
129         {
130             final ClassifierFacade parent = (ClassifierFacade)generalizationIterator.next();
131             if (parent.isInterface())
132             {
133                 operations.addAll(resolveInterfaceOperationsRecursively(parent));
134             }
135         }
136 
137         return operations;
138     }
139 
140     /**
141      * @see org.andromda.metafacades.uml.ClassifierFacade#getAssociationEnds()
142      */
143     @Override
144     protected List handleGetAssociationEnds()
145     {
146         List associationEnds;
147         Collection participantAssociation =
148             UML14MetafacadeUtils.getCorePackage().getAParticipantAssociation().getAssociation(metaObject);
149 
150         if (participantAssociation instanceof List)
151         {
152             associationEnds = (List)participantAssociation;
153         }
154         else
155         {
156             associationEnds = new ArrayList();
157             associationEnds.addAll(participantAssociation);
158         }
159 
160         return associationEnds;
161     }
162 
163     /**
164      * @return Owner of this Classifier. UML2 only. UML14 returns the namespace (package).
165      * Used to distinguish between a regular class and a TemplateParameter Class/Interface/Type
166      * @see org.andromda.metafacades.uml.ClassifierFacade#getAttributes(boolean)
167      */
168     protected Namespace getOwner()
169     {
170         return this.metaObject.getNamespace();
171     }
172 
173     /**
174      * Indicates whether or not this classifier represents a primitive
175      * type. If this type has a wrapper then it's primitive, otherwise it isn't.
176      * @see org.andromda.metafacades.uml.ClassifierFacade#isPrimitive()
177      */
178     @Override
179     protected boolean handleIsPrimitive()
180     {
181         return this.getWrapperMappings() != null &&
182             this.getWrapperMappings().getMappings().containsFrom(this.getFullyQualifiedName());
183     }
184 
185     /**
186      * Indicates whether or not this classifier represents a wrapped primitive type.
187      * @see org.andromda.metafacades.uml.ClassifierFacade#isWrappedPrimitive()
188      */
189     @Override
190     protected boolean handleIsWrappedPrimitive()
191     {
192         // Try both the fully qualified name and the ClassName
193         return this.getWrapperMappings() != null &&
194         ( this.getWrapperMappings().getMappings().containsTo(this.getFullyQualifiedName())
195           || this.getWrapperMappings().getMappings().containsTo(this.getName()));
196     }
197 
198     /**
199      * @see org.andromda.metafacades.uml.ClassifierFacade#isArrayType()
200      */
201     @Override
202     protected boolean handleIsArrayType()
203     {
204         return this.getFullyQualifiedName(true).endsWith(this.getArraySuffix());
205     }
206 
207     /*
208      * Gets the array suffix from the configured metafacade properties.
209      *
210      * @return the array suffix.
211     private String getArraySuffix()
212     {
213         return String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.ARRAY_NAME_SUFFIX));
214     }
215      */
216 
217     /**
218      * @see org.andromda.metafacades.uml.ClassifierFacade#getWrapperName()
219      */
220     @Override
221     protected String handleGetWrapperName()
222     {
223         String wrapperName = null;
224         if (this.getWrapperMappings() != null)
225         {
226             if (this.getWrapperMappings().getMappings().containsFrom(this.getFullyQualifiedName()))
227             {
228                 wrapperName = this.getWrapperMappings().getTo(this.getFullyQualifiedName());
229             }
230         }
231         return wrapperName;
232     }
233 
234     /**
235      * Gets the mappings from primitive types to wrapper types. Some languages have primitives (i.e., Java) and some
236      * languages don't, so therefore this property is optional.
237      *
238      * @return the wrapper mappings
239      */
240     protected TypeMappings getWrapperMappings()
241     {
242         final String propertyName = UMLMetafacadeProperties.WRAPPER_MAPPINGS_URI;
243         final Object property = this.getConfiguredProperty(propertyName);
244         TypeMappings mappings = null;
245         String uri;
246         if (property instanceof String)
247         {
248             uri = (String)property;
249             try
250             {
251                 mappings = TypeMappings.getInstance(uri);
252                 this.setProperty(
253                     propertyName,
254                     mappings);
255             }
256             catch (final Throwable throwable)
257             {
258                 final String errMsg = "Error getting '" + propertyName + "' --> '" + uri + '\'';
259                 logger.error(
260                     errMsg,
261                     throwable);
262 
263                 // don't throw the exception
264             }
265         }
266         else
267         {
268             mappings = (TypeMappings)property;
269         }
270         return mappings;
271     }
272 
273     /**
274      * @see org.andromda.metafacades.uml.ClassifierFacade#isCollectionType()
275      */
276     @Override
277     protected boolean handleIsCollectionType()
278     {
279         return UMLMetafacadeUtils.isType(this, UMLProfile.COLLECTION_TYPE_NAME);
280     }
281 
282     /**
283      * @see org.andromda.metafacades.uml.ClassifierFacade#isListType()
284      */
285     @Override
286     protected boolean handleIsListType()
287     {
288         return UMLMetafacadeUtils.isType(this, UMLProfile.LIST_TYPE_NAME);
289     }
290 
291     /**
292      * @see org.andromda.metafacades.uml.ClassifierFacade#isSetType()
293      */
294     @Override
295     protected boolean handleIsSetType()
296     {
297         return UMLMetafacadeUtils.isType(this, UMLProfile.SET_TYPE_NAME);
298     }
299 
300     /**
301      * @see org.andromda.metafacades.uml.ClassifierFacade#isBooleanType()
302      */
303     @Override
304     protected boolean handleIsBooleanType()
305     {
306         return UMLMetafacadeUtils.isType(this, UMLProfile.BOOLEAN_TYPE_NAME);
307     }
308 
309     /**
310      * <p>
311      * Indicates if this type represents a char, Character, or java.lang.Character type or not.
312      * </p>
313      * @see org.andromda.metafacades.uml.ClassifierFacade#isCharacterType()
314      */
315     @Override
316     protected boolean handleIsCharacterType()
317     {
318         String characterType = UMLProfile.CHARACTER_TYPE_NAME;
319         // Check both char and Character by taking the part after datatype::
320         String charType = characterType.substring(characterType.indexOf(':')+1).substring(0, 4).toLowerCase();
321         return UMLMetafacadeUtils.isType(
322             this,
323             charType) ||
324             UMLMetafacadeUtils.isType(
325                 this,
326                 characterType);
327     }
328 
329     /**
330      * @see org.andromda.metafacades.uml.ClassifierFacade#isDateType()
331      */
332     @Override
333     protected boolean handleIsDateType()
334     {
335         return UMLMetafacadeUtils.isType(this, UMLProfile.DATE_TYPE_NAME);
336     }
337 
338     /**
339      * <p>
340      * Indicates whether or not this classifier represents a time type.
341      * </p>
342      * @see org.andromda.metafacades.uml.ClassifierFacade#isDoubleType()
343      */
344     @Override
345     protected boolean handleIsDoubleType()
346     {
347         return UMLMetafacadeUtils.isType(
348             this,
349             UMLProfile.DOUBLE_TYPE_NAME);
350     }
351 
352     /**
353      * <p>
354      * Indicates whether or not this classifier represents a float type.
355      * </p>
356      * @see org.andromda.metafacades.uml.ClassifierFacade#isFloatType()
357      */
358     @Override
359     protected boolean handleIsFloatType()
360     {
361         return UMLMetafacadeUtils.isType(
362             this,
363             UMLProfile.FLOAT_TYPE_NAME);
364     }
365 
366     /**
367      * <p>
368      * Indicates whether or not this classifier represents an integer type.
369      * </p>
370      * @see org.andromda.metafacades.uml.ClassifierFacade#isIntegerType()
371      */
372     @Override
373     protected boolean handleIsIntegerType()
374     {
375         String integerType = UMLProfile.INTEGER_TYPE_NAME;
376         // Check both int and Integer by taking the part after datatype::
377         String intType = integerType.substring(integerType.indexOf(':')+1).substring(0, 3).toLowerCase();
378         return UMLMetafacadeUtils.isType(
379             this,
380             intType) ||
381             UMLMetafacadeUtils.isType(
382                 this,
383                 integerType);
384     }
385 
386     /**
387      * <p>
388      * Indicates whether or not this classifier represents a long type.
389      * </p>
390      * @see org.andromda.metafacades.uml.ClassifierFacade#isLongType()
391      */
392     @Override
393     protected boolean handleIsLongType()
394     {
395         return UMLMetafacadeUtils.isType(
396             this,
397             UMLProfile.LONG_TYPE_NAME);
398     }
399 
400     /**
401      * @see org.andromda.metafacades.uml.ClassifierFacade#isTimeType()
402      */
403     @Override
404     protected boolean handleIsTimeType()
405     {
406         return UMLMetafacadeUtils.isType(this, UMLProfile.TIME_TYPE_NAME);
407     }
408 
409     /**
410      * @see org.andromda.metafacades.uml.ClassifierFacade#isFileType()
411      */
412     @Override
413     protected boolean handleIsFileType()
414     {
415         return UMLMetafacadeUtils.isType(this, UMLProfile.FILE_TYPE_NAME);
416     }
417 
418     /**
419      * @see org.andromda.metafacades.uml.ClassifierFacade#isBlobType()
420      */
421     @Override
422     protected boolean handleIsBlobType()
423     {
424         return UMLMetafacadeUtils.isType(this, UMLProfile.BLOB_TYPE_NAME);
425     }
426 
427     /**
428      * @see org.andromda.metafacades.uml.ClassifierFacade#isClobType()
429      */
430     @Override
431     protected boolean handleIsClobType()
432     {
433         return UMLMetafacadeUtils.isType(this, UMLProfile.CLOB_TYPE_NAME);
434     }
435 
436     /**
437      * @see org.andromda.metafacades.uml.ClassifierFacade#isMapType()
438      */
439     @Override
440     public boolean handleIsMapType()
441     {
442         return UMLMetafacadeUtils.isType(this, UMLProfile.MAP_TYPE_NAME);
443     }
444 
445     /**
446      * @see org.andromda.metafacades.uml.ClassifierFacade#isStringType()
447      */
448     @Override
449     protected boolean handleIsStringType()
450     {
451         // Allow mapping multiple model types to String type
452         return "String".equals(this.getFullyQualifiedName())
453            || "java.lang.String".equals(this.getFullyQualifiedName())
454            || UMLMetafacadeUtils.isType(this, UMLProfile.STRING_TYPE_NAME);
455     }
456 
457     /**
458      * @see org.andromda.metafacades.uml.ClassifierFacade#getAttributes()
459      */
460     @Override
461     protected List<Attribute> handleGetAttributes()
462     {
463         final List attributes = new ArrayList(this.metaObject.getFeature());
464         for (final Iterator iterator = attributes.iterator(); iterator.hasNext();)
465         {
466             if (!(iterator.next() instanceof Attribute))
467             {
468                 iterator.remove();
469             }
470         }
471         return attributes;
472     }
473 
474     /**
475      * @see org.andromda.metafacades.uml.ClassifierFacade#getAttributes(boolean)
476      */
477     @Override
478     protected List<AttributeFacade> handleGetAttributes(boolean follow)
479     {
480         final List<AttributeFacade> attributes = new ArrayList<AttributeFacade>(this.getAttributes());
481         for (ClassifierFacade superClass = (ClassifierFacade)getGeneralization(); superClass != null && follow;
482              superClass = (ClassifierFacade)superClass.getGeneralization())
483         {
484             for (final Iterator<AttributeFacade> iterator = superClass.getAttributes().iterator(); iterator.hasNext();)
485             {
486                 final AttributeFacade superAttribute = iterator.next();
487                 boolean present = false;
488                 for (final Iterator<AttributeFacade> attributeIterator = this.getAttributes().iterator(); attributeIterator.hasNext();)
489                 {
490                     final AttributeFacade attribute = attributeIterator.next();
491                     if (attribute.getName().equals(superAttribute.getName()))
492                     {
493                         present = true;
494                         break;
495                     }
496                 }
497                 if (!present)
498                 {
499                     attributes.add(superAttribute);
500                 }
501             }
502         }
503         return attributes;
504     }
505 
506     /**
507      * @see org.andromda.metafacades.uml.ClassifierFacade#getProperties()
508      */
509     @Override
510     protected List handleGetProperties()
511     {
512         final List properties = new ArrayList(this.getAttributes());
513         properties.addAll(this.getNavigableConnectingEnds());
514         return properties;
515     }
516 
517     /**
518      * @see org.andromda.metafacades.uml.ClassifierFacade#getAllProperties()
519      */
520     @Override
521     public Collection handleGetAllProperties()
522     {
523         return this.getProperties(true);
524     }
525 
526     /**
527      * @see org.andromda.metafacades.uml.ClassifierFacade#getAllRequiredConstructorParameters()
528      */
529     @Override
530     public Collection handleGetAllRequiredConstructorParameters()
531     {
532         final Collection allRequiredConstructorParameters = new ArrayList();
533         allRequiredConstructorParameters.addAll(this.getRequiredConstructorParameters());
534 
535         final Collection<GeneralizableElementFacade> generalizations = this.getGeneralizations();
536         for (Iterator<GeneralizableElementFacade> parents = generalizations.iterator(); parents.hasNext();)
537         {
538             final GeneralizableElementFacade parent = parents.next();
539             if (parent instanceof ClassifierFacade)
540             {
541                 allRequiredConstructorParameters.addAll(((ClassifierFacade)parent).getAllRequiredConstructorParameters());
542             }
543         }
544 
545         return allRequiredConstructorParameters;
546     }
547 
548     /**
549      * @see org.andromda.metafacades.uml.ClassifierFacade#getRequiredConstructorParameters()
550      */
551     @Override
552     public Collection handleGetRequiredConstructorParameters()
553     {
554         final Collection requiredConstructorParameters = new ArrayList();
555 
556         final Collection properties = this.getProperties();
557         for (Iterator propertyIterator = properties.iterator(); propertyIterator.hasNext();)
558         {
559             final Object property = propertyIterator.next();
560             if (property instanceof AttributeFacade)
561             {
562                 final AttributeFacade attribute = (AttributeFacade)property;
563                 if (!attribute.isDerived() && (attribute.isRequired() || attribute.isReadOnly()))
564                 {
565                     requiredConstructorParameters.add(attribute);
566                 }
567             }
568             else if (property instanceof AssociationEndFacade)
569             {
570                 final AssociationEndFacade associationEnd = (AssociationEndFacade)property;
571                 if (!associationEnd.isDerived() && (associationEnd.isRequired() || associationEnd.isReadOnly()))
572                 {
573                     requiredConstructorParameters.add(associationEnd);
574                 }
575             }
576         }
577 
578         return requiredConstructorParameters;
579     }
580 
581     /**
582      * @see org.andromda.metafacades.uml.ClassifierFacade#getProperties(boolean)
583      */
584     @Override
585     protected List handleGetProperties(boolean follow)
586     {
587         final List properties = new ArrayList(this.getAttributes(follow));
588         properties.addAll(this.getNavigableConnectingEnds());
589         if (follow)
590         {
591             for (ClassifierFacade superClass = (ClassifierFacade)getGeneralization(); superClass != null && follow;
592                  superClass = (ClassifierFacade)superClass.getGeneralization())
593             {
594                 for (final AssociationEndFacade superAssociationEnd : superClass.getNavigableConnectingEnds())
595                 {
596                     boolean present = false;
597                     for (final Iterator<AssociationEndFacade> endIterator = this.getAssociationEnds().iterator(); endIterator.hasNext();)
598                     {
599                         final AssociationEndFacade associationEnd = endIterator.next();
600                         if (associationEnd.getName().equals(superAssociationEnd.getName()))
601                         {
602                             present = true;
603                             break;
604                         }
605                     }
606                     if (!present)
607                     {
608                         properties.add(superAssociationEnd);
609                     }
610                 }
611             }
612         }
613         return properties;
614     }
615 
616     /**
617      * @see org.andromda.metafacades.uml.ClassifierFacade#getOperationCallFromAttributes()
618      */
619     @Override
620     protected String handleGetOperationCallFromAttributes()
621     {
622         final StringBuilder call = new StringBuilder();
623         String separator = "";
624         call.append('(');
625         for (final Iterator iterator = getAttributes().iterator(); iterator.hasNext();)
626         {
627             AttributeFacade attribute = (AttributeFacade)iterator.next();
628 
629             call.append(separator);
630             String typeName = attribute.getType().getFullyQualifiedName();
631             call.append(typeName);
632             call.append(' ');
633             call.append(attribute.getName());
634             separator = ", ";
635         }
636         call.append(')');
637         return call.toString();
638     }
639 
640     /**
641      * @see org.andromda.metafacades.uml.ClassifierFacade#isAbstract()
642      */
643     @Override
644     protected boolean handleIsAbstract()
645     {
646         return this.metaObject.isAbstract();
647     }
648 
649     /**
650      * @see org.andromda.metafacades.uml.ClassifierFacade#getStaticAttributes()
651      */
652     @Override
653     protected Collection<AttributeFacade> handleGetStaticAttributes()
654     {
655         return new FilteredCollection(this.getAttributes())
656         {
657             private static final long serialVersionUID = 34L;
658             public boolean evaluate(Object object)
659             {
660                 return ((AttributeFacade)object).isStatic();
661             }
662         };
663     }
664 
665     /**
666      * @see org.andromda.metafacades.uml.ClassifierFacade#getInterfaceAbstractions()
667      */
668     @Override
669     protected Collection<ClassifierFacade> handleGetInterfaceAbstractions()
670     {
671         final Collection<ClassifierFacade> interfaceAbstractions = new LinkedHashSet<ClassifierFacade>();
672         if (this.getAbstractions() != null)
673         {
674             for (Iterator<ClassifierFacade> abstractionIterator = this.getAbstractions().iterator(); abstractionIterator.hasNext();)
675             {
676                 final DependencyFacade abstraction = (DependencyFacade)abstractionIterator.next();
677                 final ModelElementFacade element = abstraction.getTargetElement();
678 
679                 if (element instanceof ClassifierFacade)
680                 {
681                     final ClassifierFacade classifier = (ClassifierFacade)element;
682                     if (classifier.isInterface())
683                     {
684                         interfaceAbstractions.add(classifier);
685                     }
686                 }
687             }
688         }
689 
690         return interfaceAbstractions;
691     }
692 
693     /**
694      * @see org.andromda.metafacades.uml.ClassifierFacade#getImplementedInterfaceList()
695      */
696     @Override
697     protected String handleGetImplementedInterfaceList()
698     {
699         final String interfaceList;
700 
701         final Collection<ClassifierFacade> interfaces = this.getInterfaceAbstractions();
702         if (interfaces.isEmpty())
703         {
704             interfaceList = "";
705         }
706         else
707         {
708             final StringBuilder list = new StringBuilder();
709             for (final Iterator iterator = interfaces.iterator(); iterator.hasNext();)
710             {
711                 final ModelElementFacade element = (ModelElementFacade)iterator.next();
712                 list.append(element.getBindedFullyQualifiedName(this));
713                 if (iterator.hasNext())
714                 {
715                     list.append(", ");
716                 }
717             }
718             interfaceList = list.toString();
719         }
720 
721         return interfaceList;
722     }
723 
724     /**
725      * @see org.andromda.metafacades.uml.ClassifierFacade#getInstanceAttributes()
726      */
727     @Override
728     protected Collection<AttributeFacade> handleGetInstanceAttributes()
729     {
730         return new FilteredCollection(this.getAttributes())
731         {
732             private static final long serialVersionUID = 34L;
733             public boolean evaluate(Object object)
734             {
735                 return !((AttributeFacade)object).isStatic();
736             }
737         };
738     }
739 
740     /**
741      * @see org.andromda.metafacades.uml.ClassifierFacade#getAbstractions()
742      */
743     @Override
744     protected Collection<ClassifierFacade> handleGetAbstractions()
745     {
746         return new FilteredCollection(this.metaObject.getClientDependency())
747         {
748             private static final long serialVersionUID = 34L;
749             public boolean evaluate(Object object)
750             {
751                 return object instanceof Abstraction;
752             }
753         };
754     }
755 
756     /**
757      * @see org.andromda.metafacades.uml.ClassifierFacade#isDataType()
758      */
759     @Override
760     protected boolean handleIsDataType()
761     {
762         return DataType.class.isAssignableFrom(this.metaObject.getClass());
763     }
764 
765     /**
766      * @see org.andromda.metafacades.uml.ClassifierFacade#isInterface()
767      */
768     @Override
769     protected boolean handleIsInterface()
770     {
771         return Interface.class.isAssignableFrom(this.metaObject.getClass());
772     }
773 
774     /**
775      * @see org.andromda.metafacades.uml.ClassifierFacade#getNonArray()
776      */
777     @Override
778     protected ClassifierFacade handleGetNonArray()
779     {
780         ClassifierFacade nonArrayType = (ClassifierFacade)this.THIS();
781         if (this.getFullyQualifiedName().contains(this.getArraySuffix()))
782         {
783             nonArrayType =
784                 (ClassifierFacade)this.getRootPackage().findModelElement(
785                     StringUtils.replace(
786                         this.getFullyQualifiedName(true),
787                         this.getArraySuffix(),
788                         ""));
789         }
790         return nonArrayType;
791     }
792 
793     /**
794      * @see org.andromda.metafacades.uml.ClassifierFacade#getArray()
795      */
796     @Override
797     protected ClassifierFacade handleGetArray()
798     {
799         ClassifierFacade arrayType = (ClassifierFacade)this.THIS();
800         String name = this.getFullyQualifiedName(true);
801         if (!name.contains(this.getArraySuffix()))
802         {
803             name = name + this.getArraySuffix();
804             arrayType = (ClassifierFacade)this.getRootPackage().findModelElement(name);
805         }
806         return arrayType;
807     }
808 
809     /**
810      * @see org.andromda.metafacades.uml.ClassifierFacade#isEnumeration()
811      */
812     @Override
813     protected boolean handleIsEnumeration()
814     {
815         return this.hasStereotype(UMLProfile.STEREOTYPE_ENUMERATION);
816     }
817 
818     /**
819      * <p>
820      * A String representing the new Constructor value for this classifier type to
821      * be used in a Java environment.
822      * </p>
823      * @see org.andromda.metafacades.uml.ClassifierFacade#getJavaNullString()
824      */
825     @Override
826     protected String handleGetJavaNewString()
827     {
828         String javaNewString;
829         if (this.isPrimitive())
830         {
831             if (UMLMetafacadeUtils.isType(
832                     this,
833                     UMLProfile.BOOLEAN_TYPE_NAME))
834             {
835                 javaNewString = "false";
836             }
837             else
838             {
839                 javaNewString = "0";
840             }
841         }
842         else if (this.isWrappedPrimitive())
843         {
844             if (UMLMetafacadeUtils.isType(
845                 this,
846                 UMLProfile.BOOLEAN_TYPE_NAME))
847             {
848                 javaNewString = "Boolean.FALSE";
849             }
850             else
851             {
852                 javaNewString = this.getFullyQualifiedName() + ".valueOf(0)";
853             }
854         }
855         else
856         {
857             javaNewString = "new " + this.getFullyQualifiedName() + "()";
858         }
859         return javaNewString;
860     }
861 
862     /**
863      * @see org.andromda.metafacades.uml.ClassifierFacade#getJavaNullString()
864      */
865     @Override
866     protected String handleGetJavaNullString()
867     {
868         String javaNullString;
869         if (isPrimitive())
870         {
871             if (UMLMetafacadeUtils.isType(
872                     this,
873                     UMLProfile.BOOLEAN_TYPE_NAME))
874             {
875                 javaNullString = "false";
876             }
877             else
878             {
879                 javaNullString = "0";
880             }
881         }
882         else
883         {
884             javaNullString = "null";
885         }
886         return javaNullString;
887     }
888 
889     /**
890      * @see org.andromda.metafacades.uml.ClassifierFacade#getStaticOperations()
891      */
892     @Override
893     protected List<OperationFacade> handleGetStaticOperations()
894     {
895         return new FilteredCollection(this.getOperations())
896         {
897             private static final long serialVersionUID = 34L;
898             public boolean evaluate(Object object)
899             {
900                 return ((OperationFacade)object).isStatic();
901             }
902         };
903     }
904 
905     /**
906      * @see org.andromda.metafacades.uml.ClassifierFacade#getInstanceOperations()
907      */
908     @Override
909     protected List<OperationFacade> handleGetInstanceOperations()
910     {
911         return new FilteredCollection(this.getOperations())
912         {
913             private static final long serialVersionUID = 34L;
914             public boolean evaluate(Object object)
915             {
916                 return !((OperationFacade)object).isStatic();
917             }
918         };
919     }
920 
921     /**
922      * @see org.andromda.metafacades.uml.ClassifierFacade#findAttribute(String)
923      */
924     @Override
925     protected AttributeFacade handleFindAttribute(final String name)
926     {
927         return (AttributeFacade)CollectionUtils.find(
928             this.getAttributes(true),
929             new Predicate()
930             {
931                 public boolean evaluate(Object object)
932                 {
933                     final AttributeFacade attribute = (AttributeFacade)object;
934                     return StringUtils.trimToEmpty(attribute.getName()).equals(name);
935                 }
936             });
937     }
938 
939     /**
940      * @see org.andromda.metafacades.uml.ClassifierFacade#getArrayName()
941      */
942     @Override
943     protected String handleGetArrayName()
944     {
945         return this.getName() + this.getArraySuffix();
946     }
947 
948     /**
949      * @see org.andromda.metafacades.uml.ClassifierFacade#getFullyQualifiedArrayName()
950      */
951     @Override
952     protected String handleGetFullyQualifiedArrayName()
953     {
954         return this.getFullyQualifiedName() + this.getArraySuffix();
955     }
956 
957     /**
958      * @see org.andromda.metafacades.uml.ClassifierFacade#getSerialVersionUID()
959      */
960     @Override
961     protected long handleGetSerialVersionUID()
962     {
963         long serialVersionUID;
964         final String serialVersionString = UML14MetafacadeUtils.getSerialVersionUID(this);
965         if (serialVersionString != null)
966         {
967             serialVersionUID = Long.parseLong(serialVersionString);
968         }
969         else
970         {
971             serialVersionUID = MetafacadeUtils.calculateDefaultSUID(this);
972         }
973         return serialVersionUID;
974     }
975 
976     /**
977      * @see org.andromda.metafacades.uml.ClassifierFacade#getNavigableConnectingEnds()
978      */
979     @Override
980     protected Collection handleGetNavigableConnectingEnds()
981     {
982         // TODO Change model return type from <ClassifierFacade> to <AssociationEndFacade>
983         final List<AssociationEndFacade> connectingEnds = new ArrayList<AssociationEndFacade>(this.getAssociationEnds());
984         CollectionUtils.transform(
985             connectingEnds,
986             new Transformer()
987             {
988                 public AssociationEndFacade transform(final Object object)
989                 {
990                     return ((AssociationEndFacade)object).getOtherEnd();
991                 }
992             });
993         CollectionUtils.filter(
994             connectingEnds,
995             new Predicate()
996             {
997                 public boolean evaluate(final Object object)
998                 {
999                     return ((AssociationEndFacade)object).isNavigable();
1000                 }
1001             });
1002         return connectingEnds;
1003     }
1004 
1005     /**
1006      * @see org.andromda.metafacades.uml.ClassifierFacade#getNavigableConnectingEnds(boolean)
1007      */
1008     @Override
1009     protected List<AssociationEndFacade> handleGetNavigableConnectingEnds(boolean follow)
1010     {
1011         final List<AssociationEndFacade> connectionEnds = new ArrayList(this.getNavigableConnectingEnds());
1012 
1013         for (ClassifierFacade superClass = (ClassifierFacade)getGeneralization(); superClass != null && follow;
1014              superClass = (ClassifierFacade)superClass.getGeneralization())
1015         {
1016             for (final AssociationEndFacade superAssociationEnd : superClass.getNavigableConnectingEnds())
1017             {
1018                 boolean present = false;
1019                 for (final Iterator<AssociationEndFacade> endIterator = this.getAssociationEnds().iterator(); endIterator.hasNext();)
1020                 {
1021                     final AssociationEndFacade associationEnd = endIterator.next();
1022                     if (associationEnd.getName().equals(superAssociationEnd.getName()))
1023                     {
1024                         present = true;
1025                         break;
1026                     }
1027                 }
1028                 if (!present)
1029                 {
1030                     connectionEnds.add(superAssociationEnd);
1031                 }
1032             }
1033         }
1034         return connectionEnds;
1035     }
1036 
1037     /**
1038      * @see org.andromda.metafacades.uml.ClassifierFacade#isLeaf()
1039      */
1040     @Override
1041     protected boolean handleIsLeaf()
1042     {
1043         return this.metaObject.isLeaf();
1044     }
1045 
1046     /**
1047      * @see org.andromda.metafacades.uml14.ClassifierFacadeLogic#handleIsAssociationClass()
1048      */
1049     protected boolean handleIsAssociationClass()
1050     {
1051         return AssociationClass.class.isAssignableFrom(this.metaObject.getClass());
1052     }
1053 
1054     /**
1055      * @see org.andromda.metafacades.uml14.ClassifierFacadeLogic#handleGetAssociatedClasses()
1056      */
1057     protected Collection<ClassifierFacade> handleGetAssociatedClasses()
1058     {
1059         final Set<ClassifierFacade> associatedClasses = new LinkedHashSet<ClassifierFacade>();
1060 
1061         final List<AssociationEndFacade> associationEnds = this.getAssociationEnds();
1062         for (int i = 0; i < associationEnds.size(); i++)
1063         {
1064             final AssociationEndFacade associationEndFacade = associationEnds.get(i);
1065             associatedClasses.add(associationEndFacade.getOtherEnd().getType());
1066         }
1067 
1068         return associatedClasses;
1069     }
1070 
1071     /**
1072      * @see org.andromda.metafacades.uml14.ClassifierFacadeLogic#handleGetAllAssociatedClasses()
1073      */
1074     protected Collection<ClassifierFacade> handleGetAllAssociatedClasses()
1075     {
1076         final Set<ClassifierFacade> associatedClasses = new LinkedHashSet<ClassifierFacade>();
1077         associatedClasses.addAll(this.getAssociatedClasses());
1078         for (Iterator<GeneralizableElementFacade> parentIterator = this.getGeneralizations().iterator(); parentIterator.hasNext();)
1079         {
1080             final ClassifierFacade parent = (ClassifierFacade)parentIterator.next();
1081             associatedClasses.addAll(parent.getAllAssociatedClasses());
1082         }
1083 
1084         return associatedClasses;
1085     }
1086 
1087     /**
1088      * @see org.andromda.metafacades.uml14.ClassifierFacadeLogic#handleGetSuperClass()
1089      */
1090     protected ClassifierFacade handleGetSuperClass()
1091     {
1092         final GeneralizableElementFacade superClass = this.getGeneralization();
1093         return (ClassifierFacade)(superClass instanceof ClassifierFacade ? superClass : null);
1094     }
1095 
1096     /**
1097      * @see org.andromda.metafacades.uml14.ClassifierFacadeLogic#handleIsEmbeddedValue()
1098      */
1099     protected boolean handleIsEmbeddedValue()
1100     {
1101         return this.hasStereotype(UMLProfile.STEREOTYPE_EMBEDDED_VALUE);
1102     }
1103 }