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.core.metafacade.MetafacadeConstants;
10  import org.andromda.metafacades.uml.AssociationEndFacade;
11  import org.andromda.metafacades.uml.AttributeFacade;
12  import org.andromda.metafacades.uml.ClassifierFacade;
13  import org.andromda.metafacades.uml.DependencyFacade;
14  import org.andromda.metafacades.uml.Entity;
15  import org.andromda.metafacades.uml.EntityAssociationEnd;
16  import org.andromda.metafacades.uml.EntityAttribute;
17  import org.andromda.metafacades.uml.EntityMetafacadeUtils;
18  import org.andromda.metafacades.uml.EntityQueryOperation;
19  import org.andromda.metafacades.uml.FilteredCollection;
20  import org.andromda.metafacades.uml.MetafacadeUtils;
21  import org.andromda.metafacades.uml.ModelElementFacade;
22  import org.andromda.metafacades.uml.NameMasker;
23  import org.andromda.metafacades.uml.OperationFacade;
24  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
25  import org.andromda.metafacades.uml.UMLProfile;
26  import org.andromda.utils.StringUtilsHelper;
27  import org.apache.commons.collections.Closure;
28  import org.apache.commons.collections.CollectionUtils;
29  import org.apache.commons.collections.Predicate;
30  import org.apache.commons.collections.Transformer;
31  import org.apache.commons.lang.ObjectUtils;
32  import org.apache.commons.lang.StringUtils;
33  import org.omg.uml.foundation.core.Attribute;
34  import org.omg.uml.foundation.core.Classifier;
35  
36  
37  /**
38   * Metaclass facade implementation.
39   * @author Bob Fields
40   */
41  public class EntityLogicImpl
42      extends EntityLogic
43  {
44      private static final long serialVersionUID = 8742467678618468728L;
45  
46      /**
47       * @param metaObject
48       * @param context
49       */
50      public EntityLogicImpl(
51          final Object metaObject,
52          final String context)
53      {
54          super(metaObject, context);
55      }
56  
57      /**
58       * A collection of MOF ids for entities that have dynamic
59       * identifiers present.
60       */
61      private static final Collection dynamicIdentifiersPresent = new ArrayList();
62  
63      /**
64       * @see org.andromda.core.metafacade.MetafacadeBase#initialize()
65       */
66      public void initialize()
67      {
68          super.initialize();
69  
70          // if there are no identifiers on this entity, create and add one.
71          // enumeration don't have identifiers since they are not entities
72          if (!this.isIdentifiersPresent() && this.isAllowDefaultIdentifiers())
73          {
74              this.createIdentifier();
75              dynamicIdentifiersPresent.add(this.getId());
76          }
77      }
78  
79      /**
80       * Overridden to provide name masking.
81       *
82       * @see org.andromda.metafacades.uml.ModelElementFacade#getName()
83       */
84      @Override
85      protected String handleGetName()
86      {
87          final String nameMask = String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.ENTITY_NAME_MASK));
88          return NameMasker.mask(
89              super.handleGetName(),
90              nameMask);
91      }
92  
93      /**
94       * @see org.andromda.metafacades.uml.Entity#getQueryOperations()
95       */
96      @Override
97      protected Collection<OperationFacade> handleGetQueryOperations()
98      {
99          return this.getQueryOperations(false);
100     }
101 
102     /**
103      * @see org.andromda.metafacades.uml.Entity#getQueryOperations(boolean)
104      */
105     @Override
106     protected Collection<OperationFacade> handleGetQueryOperations(final boolean follow)
107     {
108         final Collection<OperationFacade> operations = new ArrayList<OperationFacade>(this.getOperations());
109         final Collection<OperationFacade> queryOperations = new ArrayList<OperationFacade>();
110 
111         MetafacadeUtils.filterByType(
112                 operations,
113             EntityQueryOperation.class);
114         for (OperationFacade operation : operations)
115         {
116             queryOperations.add((EntityQueryOperation)operation);
117         }
118         for (ClassifierFacade superClass = (ClassifierFacade)getGeneralization(); superClass != null && follow;
119             superClass = (ClassifierFacade)superClass.getGeneralization())
120         {
121             if (Entity.class.isAssignableFrom(superClass.getClass()))
122             {
123                 Entity entity = (Entity)superClass;
124                 queryOperations.addAll(entity.getQueryOperations());
125             }
126         }
127         return queryOperations;
128     }
129 
130     /**
131      * @see org.andromda.metafacades.uml.Entity#getIdentifiers()
132      */
133     @Override
134     protected Collection<ModelElementFacade> handleGetIdentifiers()
135     {
136         return this.getIdentifiers(true);
137     }
138 
139     /**
140      * @see org.andromda.metafacades.uml.Entity#getIdentifiers(boolean)
141      */
142     @Override
143     protected Collection<ModelElementFacade> handleGetIdentifiers(final boolean follow)
144     {
145         return EntityMetafacadeUtils.getIdentifiers(
146             this,
147             follow);
148     }
149 
150     /**
151      * Creates an identifier from the default identifier properties specified within a namespace.
152      */
153     private void createIdentifier()
154     {
155         // first check if the foreign identifier flag is set, and
156         // let those taken precedence if so
157         if (!this.checkForAndAddForeignIdentifiers())
158         {
159             this.createIdentifier(
160                 this.getDefaultIdentifier(),
161                 this.getDefaultIdentifierType(),
162                 this.getDefaultIdentifierVisibility());
163         }
164     }
165 
166     /**
167      * Creates a new identifier and adds it to the underlying meta model
168      * classifier instance.
169      *
170      * @param name the name to give the identifier
171      * @param type the type to give the identifier
172      * @param visibility the visibility to give the identifier
173      */
174     private void createIdentifier(
175         final String name,
176         final String type,
177         final String visibility)
178     {
179         final Classifier classifier = (Classifier)this.metaObject;
180 
181         // if we auto-create entity identifiers it will only be on hierarchy roots,
182         // problems would arise when calls to #checkForAndAddForeignIdentifiers()
183         // navigate over associated entities, effectively initializing their facade instances:
184         // this results in subclasses having an identifier generated before their ancestors
185         // ideally the method mentioned above would not make use of facades but meta-classes only,
186         // if one is to refactor it that way this comment may be removed together with the line of code under it
187         //
188         // notice how the next line of code does not make use of facades, this is done on purpose in order
189         // to avoid using uninitialized facades
190         //
191         // (Wouter, Sept. 20 2006) also see other UML implementations
192         if (!classifier.getGeneralization().isEmpty()) return;
193 
194         // only create the identifier if an identifer with the name doesn't
195         // already exist
196         if (!UML14MetafacadeUtils.attributeExists(
197                 classifier,
198                 name))
199         {
200             final Attribute identifier =
201                 UML14MetafacadeUtils.createAttribute(
202                     name,
203                     type,
204                     visibility,
205                     MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR);
206 
207             identifier.getStereotype().add(
208                 UML14MetafacadeUtils.findOrCreateStereotype(UMLProfile.STEREOTYPE_IDENTIFIER));
209 
210             classifier.getFeature().add(identifier);
211         }
212     }
213 
214     /**
215      * @see org.andromda.metafacades.uml.Entity#isIdentifiersPresent()
216      */
217     @Override
218     protected boolean handleIsIdentifiersPresent()
219     {
220         final Collection<ModelElementFacade> identifiers = this.getIdentifiers(true);
221         return identifiers != null && !identifiers.isEmpty();
222     }
223 
224     /**
225      * @see org.andromda.metafacades.uml.Entity#isDynamicIdentifiersPresent()
226      */
227     @Override
228     protected boolean handleIsDynamicIdentifiersPresent()
229     {
230         return dynamicIdentifiersPresent.contains(this.getId());
231     }
232 
233     /**
234      * @see org.andromda.metafacades.uml.Entity#getTableName()
235      */
236     @Override
237     protected String handleGetTableName()
238     {
239         final String prefixProperty = UMLMetafacadeProperties.TABLE_NAME_PREFIX;
240         final String tableNamePrefix =
241             this.isConfiguredProperty(prefixProperty)
242             ? ObjectUtils.toString(this.getConfiguredProperty(prefixProperty)) : null;
243         return EntityMetafacadeUtils.getSqlNameFromTaggedValue(
244             tableNamePrefix,
245             this,
246             UMLProfile.TAGGEDVALUE_PERSISTENCE_TABLE,
247             this.getMaxSqlNameLength(),
248             this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR),
249             this.getConfiguredProperty(UMLMetafacadeProperties.SHORTEN_SQL_NAMES_METHOD));
250     }
251 
252     /**
253      * @see org.andromda.metafacades.uml.Entity#getOperationCallFromAttributes(boolean)
254      */
255     @Override
256     protected String handleGetOperationCallFromAttributes(final boolean withIdentifiers)
257     {
258         return this.getOperationCallFromAttributes(
259             withIdentifiers,
260             false);
261     }
262 
263     /**
264      * @see org.andromda.metafacades.uml.Entity#getOperationCallFromAttributes(boolean, boolean)
265      */
266     @Override
267     protected String handleGetOperationCallFromAttributes(
268         final boolean withIdentifiers,
269         final boolean follow)
270     {
271         final StringBuilder buffer = new StringBuilder();
272         String separator = "";
273         buffer.append('(');
274 
275         final Collection<AttributeFacade> attributes = new ArrayList(this.getAttributes());
276 
277         for (ClassifierFacade superClass = (ClassifierFacade)getGeneralization(); superClass != null && follow;
278             superClass = (ClassifierFacade)superClass.getGeneralization())
279         {
280             if (superClass instanceof Entity)
281             {
282                 final Entity entity = (Entity)superClass;
283                 attributes.addAll(entity.getAttributes());
284             }
285         }
286 
287         if (!attributes.isEmpty())
288         {
289             for (final Iterator iterator = attributes.iterator(); iterator.hasNext();)
290             {
291                 final EntityAttribute attribute = (EntityAttribute)iterator.next();
292                 if (withIdentifiers || !attribute.isIdentifier())
293                 {
294                     buffer.append(separator);
295                     if (attribute.getType() != null)
296                     {
297                         buffer.append(attribute.getType().getFullyQualifiedName());
298                     }
299                     buffer.append(' ');
300                     buffer.append(attribute.getName());
301                     separator = ", ";
302                 }
303             }
304         }
305         buffer.append(')');
306         return buffer.toString();
307     }
308 
309     /**
310      * @see org.andromda.metafacades.uml.Entity#getAttributeTypeList(boolean, boolean)
311      */
312     @Override
313     protected String handleGetAttributeTypeList(
314         final boolean follow,
315         final boolean withIdentifiers)
316     {
317         return this.getTypeList(this.getAttributes(
318                 follow,
319                 withIdentifiers));
320     }
321 
322     /**
323      * @see org.andromda.metafacades.uml.Entity#getAttributeNameList(boolean, boolean)
324      */
325     @Override
326     protected String handleGetAttributeNameList(
327         final boolean follow,
328         final boolean withIdentifiers)
329     {
330         return this.getNameList(this.getAttributes(
331                 follow,
332                 withIdentifiers));
333     }
334 
335     /**
336      * @see org.andromda.metafacades.uml.Entity#getAttributeNameList(boolean, boolean, boolean)
337      */
338     @Override
339     protected String handleGetAttributeNameList(
340         final boolean follow,
341         final boolean withIdentifiers,
342         final boolean withDerived)
343     {
344         return this.getNameList(this.getAttributes(
345                 follow,
346                 withIdentifiers,
347                 withDerived));
348     }
349 
350     /**
351      * @see org.andromda.metafacades.uml.Entity#getRequiredAttributeTypeList(boolean, boolean)
352      */
353     @Override
354     protected String handleGetRequiredAttributeTypeList(
355         final boolean follow,
356         final boolean withIdentifiers)
357     {
358         return this.getTypeList(this.getRequiredAttributes(
359                 follow,
360                 withIdentifiers));
361     }
362 
363     /**
364      * @see org.andromda.metafacades.uml.Entity#getRequiredAttributeNameList(boolean, boolean)
365      */
366     @Override
367     protected String handleGetRequiredAttributeNameList(
368         final boolean follow,
369         final boolean withIdentifiers)
370     {
371         return this.getNameList(this.getRequiredAttributes(
372                 follow,
373                 withIdentifiers));
374     }
375 
376     /**
377      * @see org.andromda.metafacades.uml.Entity#getRequiredPropertyTypeList(boolean, boolean)
378      */
379     @Override
380     protected String handleGetRequiredPropertyTypeList(
381         final boolean follow,
382         final boolean withIdentifiers)
383     {
384         return this.getTypeList(this.getRequiredProperties(
385                 follow,
386                 withIdentifiers));
387     }
388 
389     /**
390      * @see org.andromda.metafacades.uml.Entity#getRequiredPropertyNameList(boolean, boolean)
391      */
392     @Override
393     protected String handleGetRequiredPropertyNameList(
394         final boolean follow,
395         final boolean withIdentifiers)
396     {
397         return this.getNameList(this.getRequiredProperties(
398                 follow,
399                 withIdentifiers));
400     }
401 
402     /**
403      * Constructs a comma separated list of attribute type names from the passed in collection of
404      * <code>attributes</code>.
405      *
406      * @param attributes the attributes to construct the list from.
407      * @return the comma separated list of attribute types.
408      */
409     private String getTypeList(final Collection attributes)
410     {
411         final StringBuilder list = new StringBuilder();
412         final String comma = ", ";
413         CollectionUtils.forAllDo(
414             attributes,
415             new Closure()
416             {
417                 public void execute(final Object object)
418                 {
419                     if (object instanceof AttributeFacade)
420                     {
421                         final AttributeFacade attribute = (AttributeFacade)object;
422                         if (attribute.getType() != null)
423                         {
424                             list.append(attribute.getType().getFullyQualifiedName());
425                             list.append(comma);
426                         }
427                     }
428                     if (object instanceof AssociationEndFacade)
429                     {
430                         final AssociationEndFacade associationEnd = (AssociationEndFacade)object;
431                         if (associationEnd.getType() != null)
432                         {
433                             list.append(associationEnd.getType().getFullyQualifiedName());
434                             list.append(comma);
435                         }
436                     }
437                 }
438             });
439         if (list.toString().endsWith(comma))
440         {
441             list.delete(
442                 list.lastIndexOf(comma),
443                 list.length());
444         }
445         return list.toString();
446     }
447 
448     /**
449      * Constructs a comma separated list of attribute names from the passed in collection of <code>attributes</code>.
450      *
451      * @param properties the properties to construct the list from.
452      * @return the comma separated list of attribute names.
453      */
454     private String getNameList(final Collection properties)
455     {
456         final StringBuilder list = new StringBuilder();
457         final String comma = ", ";
458         CollectionUtils.forAllDo(
459             properties,
460             new Closure()
461             {
462                 public void execute(Object object)
463                 {
464                     if (object instanceof EntityAttribute)
465                     {
466                         list.append(((AttributeFacade)object).getName());
467                         list.append(comma);
468                     }
469                     if (object instanceof EntityAssociationEnd)
470                     {
471                         list.append(((AssociationEndFacade)object).getName());
472                         list.append(comma);
473                     }
474                 }
475             });
476         if (list.toString().endsWith(comma))
477         {
478             list.delete(
479                 list.lastIndexOf(comma),
480                 list.length());
481         }
482         return list.toString();
483     }
484 
485     /**
486      * @see org.andromda.metafacades.uml.Entity#isChild()
487      */
488     @Override
489     protected boolean handleIsChild()
490     {
491         return CollectionUtils.find(
492             this.getAssociationEnds(),
493             new Predicate()
494             {
495                 public boolean evaluate(Object object)
496                 {
497                     return ((AssociationEndFacade)object).getOtherEnd().isComposition();
498                 }
499             }) != null;
500     }
501 
502     /**
503      * @see org.andromda.metafacades.uml.Entity#getParentEnd()
504      */
505     @Override
506     protected AssociationEndFacade handleGetParentEnd()
507     {
508         AssociationEndFacade parentEnd = null;
509         final AssociationEndFacade end =
510             (AssociationEndFacade)CollectionUtils.find(
511                 this.getAssociationEnds(),
512                 new Predicate()
513                 {
514                     public boolean evaluate(Object object)
515                     {
516                         return ((AssociationEndFacade)object).getOtherEnd().isComposition();
517                     }
518                 });
519         if (end != null)
520         {
521             parentEnd = end.getOtherEnd();
522         }
523         return parentEnd;
524     }
525 
526     /**
527      * @see org.andromda.metafacades.uml.Entity#getChildEnds()
528      */
529     @Override
530     protected Collection<AssociationEndFacade> handleGetChildEnds()
531     {
532         final Collection<AssociationEndFacade> childEnds =
533             new FilteredCollection(this.getAssociationEnds())
534             {
535                 private static final long serialVersionUID = -4602337379703645043L;
536 
537                 public boolean evaluate(Object object)
538                 {
539                     return ((AssociationEndFacade)object).isComposition();
540                 }
541             };
542         CollectionUtils.transform(
543             childEnds,
544             new Transformer()
545             {
546                 public Object transform(Object object)
547                 {
548                     return ((AssociationEndFacade)object).getOtherEnd();
549                 }
550             });
551         return childEnds;
552     }
553 
554     /**
555      * @see org.andromda.metafacades.uml.Entity#getBusinessOperations()
556      */
557     @Override
558     protected Collection<OperationFacade> handleGetBusinessOperations()
559     {
560         final Collection<OperationFacade> businessOperations = new ArrayList(this.getImplementationOperations());
561         MetafacadeUtils.filterByNotType(
562             businessOperations,
563             EntityQueryOperation.class);
564         return businessOperations;
565     }
566 
567     /**
568      * @see org.andromda.metafacades.uml.Entity#getEntityReferences()
569      */
570     @Override
571     protected Collection<DependencyFacade> handleGetEntityReferences()
572     {
573         return new FilteredCollection(this.getSourceDependencies())
574             {
575             private static final long serialVersionUID = -8696886289865317133L;
576 
577             public boolean evaluate(Object object)
578                 {
579                     ModelElementFacade targetElement = ((DependencyFacade)object).getTargetElement();
580                     return targetElement instanceof Entity;
581                 }
582             };
583     }
584 
585     /**
586      * @see org.andromda.metafacades.uml.Entity#getAttributes(boolean, boolean)
587      */
588     @Override
589     protected Collection handleGetAttributes(
590         boolean follow,
591         final boolean withIdentifiers)
592     {
593         return this.getAttributes(follow, withIdentifiers, true);
594     }
595 
596     /**
597      * @see org.andromda.metafacades.uml.Entity#getAttributes(boolean, boolean, boolean)
598      */
599     @Override
600     protected Collection handleGetAttributes(
601         boolean follow,
602         final boolean withIdentifiers,
603         final boolean withDerived)
604     {
605         final Collection attributes = this.getAttributes(follow);
606         CollectionUtils.filter(
607             attributes,
608             new Predicate()
609             {
610                 public boolean evaluate(Object object)
611                 {
612                     boolean valid = true;
613                     if (!withIdentifiers && object instanceof EntityAttribute)
614                     {
615                         valid = !((EntityAttribute)object).isIdentifier();
616                     }
617                     if (valid && !withDerived && object instanceof EntityAttribute)
618                     {
619                         valid = !((EntityAttribute)object).isDerived();
620                     }
621                     return valid;
622                 }
623             });
624         return attributes;
625     }
626 
627     /**
628      * @see org.andromda.metafacades.uml.Entity#getProperties(boolean, boolean)
629      */
630     @Override
631     protected Collection handleGetProperties(
632         boolean follow,
633         final boolean withIdentifiers)
634     {
635         final Collection properties = this.getProperties(follow);
636         CollectionUtils.filter(
637             properties,
638             new Predicate()
639             {
640                 public boolean evaluate(Object object)
641                 {
642                     boolean valid = true;
643                     if (!withIdentifiers && object instanceof EntityAttribute)
644                     {
645                         valid = !((EntityAttribute)object).isIdentifier();
646                     }
647                     return valid;
648                 }
649             });
650         return properties;
651     }
652 
653     /**
654      * @see org.andromda.metafacades.uml.Entity#getRequiredAttributes(boolean, boolean)
655      */
656     @Override
657     protected Collection handleGetRequiredAttributes(
658         boolean follow,
659         final boolean withIdentifiers)
660     {
661         final Collection attributes = this.getAttributes(
662                 follow,
663                 withIdentifiers, false);
664         CollectionUtils.filter(
665             attributes,
666             new Predicate()
667             {
668                 public boolean evaluate(Object object)
669                 {
670                     boolean valid;
671                     valid = ((AttributeFacade)object).isRequired();
672                     if (valid && !withIdentifiers && object instanceof EntityAttribute)
673                     {
674                         valid = !((EntityAttribute)object).isIdentifier();
675                     }
676                     return valid;
677                 }
678             });
679         return attributes;
680     }
681 
682     /**
683      * @see org.andromda.metafacades.uml.Entity#getRequiredProperties(boolean, boolean)
684      */
685     @Override
686     protected Collection handleGetRequiredProperties(
687         final boolean follow,
688         final boolean withIdentifiers)
689     {
690         final Set properties = new LinkedHashSet(this.getProperties(
691                     follow,
692                     withIdentifiers));
693         CollectionUtils.filter(
694             properties,
695             new Predicate()
696             {
697                 public boolean evaluate(final Object object)
698                 {
699                     boolean valid = false;
700                     if (object instanceof AttributeFacade)
701                     {
702                         AttributeFacade attribute = (AttributeFacade)object;
703                         valid = attribute.isRequired() && !attribute.isDerived();
704                         if (valid && !withIdentifiers && object instanceof EntityAttribute)
705                         {
706                             valid = !((EntityAttribute)object).isIdentifier();
707                         }
708                     }
709                     else if (object instanceof AssociationEndFacade)
710                     {
711                         valid = ((AssociationEndFacade)object).isRequired();
712                     }
713                     return valid;
714                 }
715             });
716 
717         List sortedProperties = new ArrayList(properties);
718         MetafacadeUtils.sortByFullyQualifiedName(sortedProperties);
719         return sortedProperties;
720     }
721 
722     /**
723      * Gets the maximum name length SQL names may be
724      */
725     @Override
726     protected short handleGetMaxSqlNameLength()
727     {
728         return Short.valueOf((String)this.getConfiguredProperty(UMLMetafacadeProperties.MAX_SQL_NAME_LENGTH));
729     }
730 
731     /**
732      * Returns true/false on whether or not default identifiers are allowed
733      */
734     private boolean isAllowDefaultIdentifiers()
735     {
736         return Boolean.valueOf((String)this.getConfiguredProperty(UMLMetafacadeProperties.ALLOW_DEFAULT_IDENTITIFIERS))
737                       .booleanValue();
738     }
739 
740     /**
741      * Gets the name of the default identifier.
742      */
743     private String getDefaultIdentifier()
744     {
745         return ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_IDENTIFIER_PATTERN))
746                           .replaceAll(
747             "\\{0\\}",
748             StringUtilsHelper.lowerCamelCaseName(this.getName()));
749     }
750 
751     /**
752      * Gets the name of the default identifier type.
753      */
754     private String getDefaultIdentifierType()
755     {
756         return (String)this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_IDENTIFIER_TYPE);
757     }
758 
759     /**
760      * Gets the default identifier visibility.
761      */
762     private String getDefaultIdentifierVisibility()
763     {
764         return (String)this.getConfiguredProperty(UMLMetafacadeProperties.DEFAULT_IDENTIFIER_VISIBILITY);
765     }
766 
767     /**
768      * Checks to see if this entity has any associations where the foreign identifier flag may be set, and if so creates
769      * and adds identifiers just like the foreign entity to this entity.
770      *
771      * @return true if any identifiers were added, false otherwise
772      */
773     private boolean checkForAndAddForeignIdentifiers()
774     {
775         boolean identifiersAdded = false;
776         final EntityAssociationEnd end = this.getForeignIdentifierEnd();
777         if (end != null && end.getType() instanceof Entity)
778         {
779             final Entity foreignEntity = (Entity)end.getOtherEnd().getType();
780             final Collection<ModelElementFacade> identifiers = EntityMetafacadeUtils.getIdentifiers(
781                     foreignEntity,
782                     true);
783             for (final ModelElementFacade facade : identifiers)
784             {
785                 if (facade instanceof AttributeFacade)
786                 {
787                     AttributeFacade identifier = (AttributeFacade)facade;
788                     this.createIdentifier(
789                             identifier.getName(),
790                             identifier.getType().getFullyQualifiedName(true),
791                             identifier.getVisibility());
792                 }
793                 else if (facade instanceof AssociationEndFacade)
794                 {
795                     AssociationEndFacade identifier = (AssociationEndFacade)facade;
796                     this.createIdentifier(
797                             identifier.getName(),
798                             identifier.getType().getFullyQualifiedName(true),
799                             identifier.getVisibility());
800                 }
801                 identifiersAdded = true;
802             }
803         }
804         return identifiersAdded;
805     }
806 
807     /**
808      * Override to filter out any association ends that point to model elements other than other entities.
809      *
810      * @see org.andromda.metafacades.uml.ClassifierFacade#getAssociationEnds()
811      */
812     @Override
813     public List handleGetAssociationEnds()
814     {
815         final List associationEnds = (List)this.shieldedElements(super.handleGetAssociationEnds());
816         CollectionUtils.filter(
817             associationEnds,
818             new Predicate()
819             {
820                 public boolean evaluate(Object object)
821                 {
822                     return ((AssociationEndFacade)object).getOtherEnd().getType() instanceof Entity;
823                 }
824             });
825         return associationEnds;
826     }
827 
828     /**
829      * @see org.andromda.metafacades.uml14.EntityLogic#handleIsUsingForeignIdentifier()
830      */
831     protected boolean handleIsUsingForeignIdentifier()
832     {
833         return this.getForeignIdentifierEnd() != null;
834     }
835 
836     /**
837      * Gets the association end that is flagged as having the foreign identifier set (or null if none is).
838      */
839     private EntityAssociationEnd getForeignIdentifierEnd()
840     {
841         return (EntityAssociationEnd)CollectionUtils.find(
842             this.getAssociationEnds(),
843             new Predicate()
844             {
845                 public boolean evaluate(Object object)
846                 {
847                     boolean valid = false;
848                     if (object != null && EntityAssociationEnd.class.isAssignableFrom(object.getClass()))
849                     {
850                         EntityAssociationEnd end = (EntityAssociationEnd)object;
851                         valid = end.isForeignIdentifier();
852                     }
853                     return valid;
854                 }
855             });
856     }
857 
858     /**
859      * @see org.andromda.metafacades.uml.Entity#isUsingAssignedIdentifier()
860      */
861     @Override
862     protected boolean handleIsUsingAssignedIdentifier()
863     {
864         boolean assigned = false;
865         final Collection<ModelElementFacade> identifiers = this.getIdentifiers();
866         if (identifiers != null && !identifiers.isEmpty())
867         {
868             ModelElementFacade facade = identifiers.iterator().next();
869             if (facade instanceof AttributeFacade)
870             {
871                 final AttributeFacade identifier = (AttributeFacade)facade;
872                 assigned =
873                     Boolean.valueOf(
874                        ObjectUtils.toString(
875                         identifier.findTaggedValue(UMLProfile.TAGGEDVALUE_PERSISTENCE_ASSIGNED_IDENTIFIER)))
876                        .booleanValue();
877             }
878         }
879         return assigned;
880     }
881 
882     /**
883      * @see org.andromda.metafacades.uml.Entity#getSchema()
884      */
885     @Override
886     protected String handleGetSchema()
887     {
888         String schemaName = ObjectUtils.toString(this.findTaggedValue(UMLProfile.TAGGEDVALUE_PERSISTENCE_SCHEMA));
889         if (StringUtils.isBlank(schemaName))
890         {
891             schemaName = ObjectUtils.toString(this.getConfiguredProperty(UMLMetafacadeProperties.SCHEMA_NAME));
892         }
893         return schemaName;
894     }
895 
896     /**
897      * @see org.andromda.metafacades.uml.Entity#getIdentifierAssociationEnds()
898      */
899     @Override
900     protected Collection handleGetIdentifierAssociationEnds()
901     {
902         final Collection<AssociationEndFacade> associationEnds = new ArrayList<AssociationEndFacade>(this.getAssociationEnds());
903         MetafacadeUtils.filterByStereotype(
904             associationEnds,
905             UMLProfile.STEREOTYPE_IDENTIFIER);
906         return associationEnds;
907     }
908 
909     /**
910      * @see org.andromda.metafacades.uml.Entity#isCompositeIdentifier()
911      */
912     @Override
913     protected boolean handleIsCompositeIdentifier()
914     {
915         int identifiers = (!this.getIdentifiers().isEmpty()) ? this.getIdentifiers().size() : 0;
916         identifiers =
917             identifiers +
918             (!this.getIdentifierAssociationEnds().isEmpty() ? this.getIdentifierAssociationEnds().size() : 0);
919         return identifiers >= 2;
920     }
921 
922     /**
923      * @see org.andromda.metafacades.uml.Entity#getAllEntityReferences()
924      */
925     @Override
926     protected Collection<DependencyFacade> handleGetAllEntityReferences()
927     {
928         final Collection<DependencyFacade> result = new LinkedHashSet<DependencyFacade> ();
929 
930         // get references of the service itself
931         result.addAll(this.getEntityReferences());
932 
933         // get references of all super classes
934         CollectionUtils.forAllDo(this.getAllGeneralizations(), new Closure()
935         {
936             public void execute(Object object)
937             {
938                 if (object instanceof Entity)
939                 {
940                     final Entity entity = (Entity)object;
941                     result.addAll(entity.getEntityReferences());
942                 }
943             }
944 
945         });
946         return result;
947     }
948 
949     /**
950      * @see org.andromda.metafacades.uml.Entity#getEmbeddedValues()
951      */
952     @Override
953     protected Collection<AttributeFacade> handleGetEmbeddedValues()
954     {
955         final Collection<AttributeFacade> embeddedValues = new ArrayList<AttributeFacade>();
956         for (final Iterator<AttributeFacade> iterator = this.getAttributes(true).iterator(); iterator.hasNext();)
957         {
958             final AttributeFacade attribute = iterator.next();
959             final ClassifierFacade type = attribute.getType();
960             if (type != null && type.isEmbeddedValue())
961             {
962                 embeddedValues.add(attribute);
963             }
964         }
965         return embeddedValues;
966     }
967 
968     /**
969      * @see org.andromda.metafacades.uml.Entity#getFullyQualifiedIdentifierTypeName()
970      */
971     @Override
972     public String handleGetFullyQualifiedIdentifierTypeName() {
973         if(isCompositeIdentifier())
974         {
975             return getFullyQualifiedName()+(String)this.getConfiguredProperty(UMLMetafacadeProperties.COMPOSITE_IDENTIFIER_TYPE_NAME_SUFIX);
976         }
977         else
978         {
979             ModelElementFacade facade = getIdentifiers().iterator().next();
980             if (facade instanceof AttributeFacade)
981             {
982                 return ((AttributeFacade)facade).getType().getFullyQualifiedName();
983             }
984             else if (facade instanceof AssociationEndFacade)
985             {
986                 return ((AssociationEndFacade)facade).getType().getFullyQualifiedName();
987             }
988             else
989             {
990                 return "";
991             }
992         }
993     }
994 
995     /**
996      * @see org.andromda.metafacades.uml.Entity#getIdentifierName()
997      */
998     @Override
999     public String handleGetIdentifierName() {
1000         if(isCompositeIdentifier())
1001         {
1002             return StringUtils.uncapitalize(getName())+(String)this.getConfiguredProperty(UMLMetafacadeProperties.COMPOSITE_IDENTIFIER_NAME_SUFIX);
1003         }
1004         else
1005         {
1006             return getIdentifiers().iterator().next().getName();
1007         }
1008     }
1009 
1010     /**
1011      * @see org.andromda.metafacades.uml.Entity#getIdentifierTypeName()
1012      */
1013     @Override
1014     public String handleGetIdentifierTypeName() {
1015         if(isCompositeIdentifier())
1016         {
1017             return getName()+(String)this.getConfiguredProperty(UMLMetafacadeProperties.COMPOSITE_IDENTIFIER_TYPE_NAME_SUFIX);
1018         }
1019         else
1020         {
1021             ModelElementFacade facade = getIdentifiers().iterator().next();
1022             if (facade instanceof AttributeFacade)
1023             {
1024                 return ((AttributeFacade)facade).getType().getName();
1025             }
1026             else if (facade instanceof AssociationEndFacade)
1027             {
1028                 return ((AssociationEndFacade)facade).getType().getName();
1029             }
1030             else
1031             {
1032                 return "";
1033             }
1034         }
1035     }
1036 
1037     /**
1038      * @see org.andromda.metafacades.uml.Entity#getIdentifierGetterName()
1039      */
1040     @Override
1041     public String handleGetIdentifierGetterName() {
1042         return "get"+StringUtils.capitalize(getIdentifierName());
1043     }
1044 
1045     /**
1046      * @see org.andromda.metafacades.uml.Entity#getIdentifierSetterName()
1047      */
1048     @Override
1049     public String handleGetIdentifierSetterName() {
1050         return "set"+StringUtils.capitalize(getIdentifierName());
1051     }
1052 }