View Javadoc
1   package org.andromda.cartridges.hibernate.metafacades;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   
6   import org.andromda.cartridges.hibernate.HibernateProfile;
7   import org.andromda.cartridges.hibernate.HibernateUtils;
8   import org.andromda.metafacades.uml.ClassifierFacade;
9   import org.andromda.metafacades.uml.EntityAssociationEnd;
10  import org.andromda.metafacades.uml.EntityMetafacadeUtils;
11  import org.andromda.metafacades.uml.ModelElementFacade;
12  import org.andromda.metafacades.uml.NameMasker;
13  import org.andromda.metafacades.uml.TypeMappings;
14  import org.andromda.metafacades.uml.UMLMetafacadeProperties;
15  import org.andromda.metafacades.uml.UMLProfile;
16  import org.andromda.utils.JavaTypeConverter;
17  import org.apache.commons.lang.BooleanUtils;
18  import org.apache.commons.lang.ObjectUtils;
19  import org.apache.commons.lang.StringUtils;
20  
21  /**
22   * MetafacadeLogic implementation for
23   * org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd.
24   *
25   * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd
26   */
27  public class HibernateAssociationEndLogicImpl
28      extends HibernateAssociationEndLogic
29  {
30      private static final long serialVersionUID = 34L;
31      /**
32       * @param metaObject
33       * @param context
34       */
35      public HibernateAssociationEndLogicImpl(
36          Object metaObject,
37          String context)
38      {
39          super(metaObject, context);
40      }
41  
42      /**
43       * Value for set
44       */
45      private static final String COLLECTION_TYPE_SET = "set";
46  
47      /**
48       * Value for map
49       */
50      private static final String COLLECTION_TYPE_MAP = "map";
51  
52      /**
53       * Value for bags
54       */
55      private static final String COLLECTION_TYPE_BAG = "bag";
56  
57      /**
58       * Value for list
59       */
60      private static final String COLLECTION_TYPE_LIST = "list";
61  
62      /**
63       * Value for collections
64       */
65      private static final String COLLECTION_TYPE_COLLECTION = "collection";
66  
67      /**
68       * Stores the valid collection types
69       */
70      private static final Collection<String> collectionTypes = new ArrayList<String>();
71  
72      static
73      {
74          collectionTypes.add(COLLECTION_TYPE_SET);
75          collectionTypes.add(COLLECTION_TYPE_MAP);
76          collectionTypes.add(COLLECTION_TYPE_BAG);
77          collectionTypes.add(COLLECTION_TYPE_LIST);
78          collectionTypes.add(COLLECTION_TYPE_COLLECTION);
79      }
80  
81      /**
82       * Stores the property indicating whether or not composition should define
83       * the eager loading strategy.
84       */
85      private static final String COMPOSITION_DEFINES_EAGER_LOADING = "compositionDefinesEagerLoading";
86  
87      /**
88       * Stores the default outerjoin setting for this association end.
89       */
90      private static final String PROPERTY_ASSOCIATION_END_OUTERJOIN = "hibernateAssociationEndOuterJoin";
91  
92      /**
93       * Stores the default collection index name.
94       */
95      private static final String COLLECTION_INDEX_NAME = "associationEndCollectionIndexName";
96  
97      /**
98       * Stores the default collection index type.
99       */
100     private static final String COLLECTION_INDEX_TYPE = "associationEndCollectionIndexType";
101 
102     /**
103      * Stores the value of the cascade behavior when modeling an aggregation.
104      */
105     private static final String HIBERNATE_AGGREGATION_CASCADE = "hibernateAggregationCascade";
106 
107     /**
108      * Stores the value of the cascade behavior when modeling a composition.
109      */
110     private static final String HIBERNATE_COMPOSITION_CASCADE = "hibernateCompositionCascade";
111 
112     /**
113      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEndLogic#handleIsOne2OnePrimary()
114      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isOne2OnePrimary()
115      */
116     @Override
117     protected boolean handleIsOne2OnePrimary()
118     {
119         boolean primary  = !BooleanUtils.toBoolean(
120             ObjectUtils.toString(this.getOtherEnd().findTaggedValue(
121                 HibernateProfile.TAGGEDVALUE_PERSISTENCE_ASSOCIATION_END_PRIMARY)));
122         if (primary)
123         {
124             primary = (this.isOne2One() && (this.isAggregation() || this.isComposition()) ||
125                 BooleanUtils.toBoolean(ObjectUtils.toString(
126                     this.findTaggedValue(HibernateProfile.TAGGEDVALUE_PERSISTENCE_ASSOCIATION_END_PRIMARY))));
127         }
128         return primary;
129     }
130 
131     /**
132      * @see org.andromda.metafacades.uml.AssociationEndFacade#getGetterSetterTypeName()
133      */
134     public String getGetterSetterTypeName()
135     {
136         String getterSetterTypeName = null;
137 
138         if (this.isMany())
139         {
140             final boolean specificInterfaces =
141                     Boolean.valueOf(
142                     ObjectUtils.toString(this.getConfiguredProperty(HibernateGlobals.SPECIFIC_COLLECTION_INTERFACES)))
143                        .booleanValue();
144 
145             final TypeMappings mappings = this.getLanguageMappings();
146             if (mappings != null)
147             {
148                 if (this.isMap())
149                 {
150                     getterSetterTypeName = mappings.getTo(UMLProfile.MAP_TYPE_NAME);
151                 }
152                 else if (specificInterfaces)
153                 {
154                     if (this.isSet())
155                     {
156                         getterSetterTypeName = mappings.getTo(UMLProfile.SET_TYPE_NAME);
157                     }
158                     else if (this.isList())
159                     {
160                         getterSetterTypeName = mappings.getTo(UMLProfile.LIST_TYPE_NAME);
161                     }
162                 }
163                 else
164                 {
165                     getterSetterTypeName =
166                         ObjectUtils.toString(this.getConfiguredProperty(HibernateGlobals.DEFAULT_COLLECTION_INTERFACE));
167                 }
168             }
169             else
170             {
171                 getterSetterTypeName =
172                     ObjectUtils.toString(this.getConfiguredProperty(HibernateGlobals.DEFAULT_COLLECTION_INTERFACE));
173             }
174         }
175         else
176         {
177             final ClassifierFacade type = this.getType();
178 
179             if (type instanceof HibernateEntity)
180             {
181                 final String typeName = ((HibernateEntity)type).getFullyQualifiedEntityName();
182 
183                 if (StringUtils.isNotBlank(typeName))
184                 {
185                     getterSetterTypeName = typeName;
186                 }
187             }
188         }
189 
190         if (StringUtils.isBlank(getterSetterTypeName))
191         {
192             getterSetterTypeName = super.getGetterSetterTypeName();
193         }
194         else if (this.isMany())
195         {
196             // set this association end's type as a template parameter if required
197             if (Boolean.valueOf(String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING)))
198                        .booleanValue())
199             {
200                 final StringBuilder lBuffer = new StringBuilder();
201                 lBuffer.append(getterSetterTypeName);
202                 lBuffer.append('<');
203                 if (this.isMap())
204                 {
205                     lBuffer.append(this.getCollectionIndexType());
206                     lBuffer.append(", ");
207                 }
208                 lBuffer.append(this.getType().getFullyQualifiedName());
209                 lBuffer.append('>');
210                 getterSetterTypeName = lBuffer.toString();
211             }
212         }
213 
214         return getterSetterTypeName;
215     }
216 
217     /**
218      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isLazy()
219      */
220     @Override
221     protected boolean handleIsLazy()
222     {
223         String lazyString = (String)findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_LAZY);
224         boolean lazy = true;
225 
226         if (StringUtils.isBlank(lazyString))
227         {
228             // check whether or not composition defines eager loading is turned
229             // on
230             boolean compositionDefinesEagerLoading =
231                 Boolean.valueOf(String.valueOf(this.getConfiguredProperty(COMPOSITION_DEFINES_EAGER_LOADING)))
232                        .booleanValue();
233 
234             if (compositionDefinesEagerLoading)
235             {
236                 lazy = !this.getOtherEnd().isComposition();
237             }
238         }
239         else
240         {
241             lazy = Boolean.valueOf(lazyString).booleanValue();
242         }
243 
244         return lazy;
245     }
246 
247     /**
248      * calculates the hibernate cascade attribute of this association end.
249      *
250      * @return null if no relevant cascade attribute to deliver
251      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getHibernateCascade()
252      */
253     protected String handleGetHibernateCascade()
254     {
255         String cascade = null;
256         final String individualCascade = (String)findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_CASCADE);
257 
258         if ((individualCascade != null) && (individualCascade.length() > 0))
259         {
260             cascade = individualCascade;
261         }
262         else if (this.isChild()) // other end is a composition
263         {
264             if (StringUtils.isBlank(this.getHibernateCompositionCascade()))
265             {
266                 cascade = HibernateGlobals.HIBERNATE_CASCADE_DELETE;
267 
268                 final Object type = this.getType();
269 
270                 if (type != null && type instanceof HibernateEntity)
271                 {
272                     HibernateEntity entity = (HibernateEntity)type;
273                     final String defaultCascade = entity.getHibernateDefaultCascade();
274 
275                     if (defaultCascade.equalsIgnoreCase(HibernateGlobals.HIBERNATE_CASCADE_SAVE_UPDATE) ||
276                         defaultCascade.equalsIgnoreCase(HibernateGlobals.HIBERNATE_CASCADE_ALL))
277                     {
278                         if (this.isMany())
279                         {
280                             cascade = HibernateGlobals.HIBERNATE_CASCADE_ALL_DELETE_ORPHAN;
281                         }
282                         else
283                         {
284                             cascade = HibernateGlobals.HIBERNATE_CASCADE_ALL;
285                         }
286                     }
287                 }
288             }
289             else
290             {
291                 cascade = this.getHibernateCompositionCascade();
292             }
293         }
294         else if (this.isComposition())
295         {
296             // on the composition side, always enforce "none", overriding a
297             // default-cascade value
298             cascade = HibernateGlobals.HIBERNATE_CASCADE_NONE;
299         }
300         else if (StringUtils.isNotBlank(this.getHibernateAggregationCascade()))
301         {
302             // on the aggregation side, always enforce "none", overriding a
303             // default-cascade value
304             if (this.isAggregation())
305             {
306                 cascade = HibernateGlobals.HIBERNATE_CASCADE_NONE;
307             }
308             else if (this.getOtherEnd() != null && this.getOtherEnd().isAggregation())
309             {
310                 cascade = this.getHibernateAggregationCascade();
311             }
312         }
313         return cascade;
314     }
315 
316     /**
317      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isHibernateInverse()
318      */
319     @Override
320     protected boolean handleIsHibernateInverse()
321     {
322         // inverse can only be true if the relation is bidirectional
323         boolean inverse = this.isNavigable() && this.getOtherEnd().isNavigable();
324 
325         if (inverse)
326         {
327             inverse = this.isMany2One();
328 
329             // for many-to-many we just put the flag on the side that
330             // is aggregation or composition
331             if (this.isMany2Many() && !inverse)
332             {
333                 if (this.getOtherEnd().isAggregation() || this.getOtherEnd().isComposition())
334                 {
335                     inverse = true;
336                 }
337                 else
338                 {
339                     inverse=false;
340                 }
341                 if (inverse && this.isBidirectionalOrderedListChild() && (this.isVersion3() || this.isVersion4()))
342                 { // A special case - when using ver 3 of hibernate for a bi-dir
343                   // ordered list, "inverse" should be set to FALSE, rather than
344                   // the usual TRUE. See http://www.hibernate.org/193.html
345                     inverse = false;
346                 }
347             }
348         }
349 
350         return inverse;
351     }
352 
353     /**
354      * Hibernate 2 outer join option
355      */
356     private static final String HIBERNATE_OUTER_JOIN_YES = "yes";
357 
358     /**
359      * Hibernate 2 outer join option
360      */
361     private static final String HIBERNATE_OUTER_JOIN_AUTO = "auto";
362 
363     /**
364      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getOuterJoin()
365      */
366     @Override
367     protected String handleGetOuterJoin()
368     {
369         Object value = this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_OUTER_JOIN);
370 
371         if (value == null)
372         {
373             value = this.getConfiguredProperty(PROPERTY_ASSOCIATION_END_OUTERJOIN);
374         }
375         String outerValue = StringUtils.trimToEmpty(String.valueOf(value));
376         String version = (String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_VERSION);
377 
378         if (StringUtils.isBlank(version) || version.startsWith(HibernateGlobals.HIBERNATE_VERSION_3)
379             || version.startsWith(HibernateGlobals.HIBERNATE_VERSION_4))
380         {
381             outerValue =
382                 (outerValue.equals(HIBERNATE_OUTER_JOIN_AUTO) || outerValue.equals(HIBERNATE_OUTER_JOIN_YES))
383                 ? "select" : "join";
384         }
385         return outerValue;
386     }
387 
388     /**
389      * Overridden to provide handling of inheritance.
390      *
391      * @see org.andromda.metafacades.uml.AssociationEndFacade#isRequired()
392      */
393     public boolean isRequired()
394     {
395         boolean required = super.isRequired();
396         Object type = this.getOtherEnd().getType();
397 
398         if ((type != null) && HibernateEntity.class.isAssignableFrom(type.getClass()))
399         {
400             HibernateEntity entity = (HibernateEntity)type;
401 
402             if (entity.isHibernateInheritanceClass() && (entity.getGeneralization() != null))
403             {
404                 required = false;
405             }
406         }
407 
408         return required;
409     }
410 
411     /**
412      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getCollectionType()
413      */
414     @Override
415     protected String handleGetCollectionType()
416     {
417         String collectionType = this.getSpecificCollectionType();
418 
419         if (!collectionTypes.contains(collectionType))
420         {
421             if (this.isOrdered())
422             {
423                 collectionType = COLLECTION_TYPE_LIST;
424             }
425             else
426             {
427                 collectionType =
428                     (String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_ASSOCIATION_COLLECTION_TYPE);
429             }
430         }
431 
432         return collectionType;
433     }
434 
435     /**
436      * Gets the collection type defined on this association end.
437      *
438      * @return the specific collection type.
439      */
440     private String getSpecificCollectionType()
441     {
442         return ObjectUtils.toString(
443             this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_ASSOCIATION_COLLECTION_TYPE));
444     }
445 
446     /**
447      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getSortType()
448      */
449     @Override
450     protected String handleGetSortType()
451     {
452         return ObjectUtils.toString(this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_ASSOCIATION_SORT_TYPE));
453     }
454 
455     /**
456      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getOrderByColumns()
457      */
458     @Override
459     protected String handleGetOrderByColumns()
460     {
461         String orderColumns =
462             (String)this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_ASSOCIATION_ORDER_BY_COLUMNS);
463 
464         if (StringUtils.isBlank(orderColumns))
465         {
466             orderColumns = ((EntityAssociationEnd)this.getOtherEnd()).getColumnName();
467         }
468 
469         return orderColumns;
470     }
471 
472     /**
473      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getWhereClause()
474      */
475     @Override
476     protected String handleGetWhereClause()
477     {
478         return (String)this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_ASSOCIATION_WHERE_CLAUSE);
479     }
480 
481     /**
482      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isIndexedCollection()
483      */
484     @Override
485     protected boolean handleIsIndexedCollection()
486     {
487         boolean indexed = false;
488 
489         if (this.isOrdered())
490         {
491             if ((
492                     this.getCollectionType().equals(COLLECTION_TYPE_LIST) ||
493                     this.getCollectionType().equals(COLLECTION_TYPE_MAP)
494                 ) && StringUtils.isNotBlank(this.getCollectionIndexName()))
495             {
496                 indexed = true;
497             }
498         }
499 
500         return indexed;
501     }
502 
503     /**
504      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getCollectionIndexName()
505      */
506     @Override
507     protected String handleGetCollectionIndexName()
508     {
509         Object value = this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_ASSOCIATION_INDEX);
510 
511         if ((value == null) && this.isConfiguredProperty(COLLECTION_INDEX_NAME))
512         {
513             value = this.getConfiguredProperty(COLLECTION_INDEX_NAME);
514 
515             if (StringUtils.isBlank(ObjectUtils.toString(value)))
516             {
517                 value = null;
518             }
519         }
520 
521         if (value != null)
522         {
523             return ObjectUtils.toString(value);
524         }
525         final String otherEntityName = ((HibernateEntity)this.getOtherEnd().getType()).getEntityName();
526         final Object separator = this.getConfiguredProperty(UMLMetafacadeProperties.SQL_NAME_SEPARATOR);
527         return EntityMetafacadeUtils.toSqlName(
528             otherEntityName,
529             separator) + separator + EntityMetafacadeUtils.toSqlName(
530             this.getName(),
531             separator) + separator + "IDX";
532     }
533 
534     /**
535      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getCollectionIndexType()
536      */
537     @Override
538     protected String handleGetCollectionIndexType()
539     {
540         Object value = this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_ASSOCIATION_INDEX_TYPE);
541 
542         if (value == null)
543         {
544             value = this.getConfiguredProperty(COLLECTION_INDEX_TYPE);
545 
546             if (StringUtils.isBlank(ObjectUtils.toString(value)))
547             {
548                 value = null;
549             }
550         }
551 
552         if (value != null)
553         {
554             if (value instanceof String)
555             {
556                 ModelElementFacade element = this.getRootPackage().findModelElement((String)value);
557                 if (element!=null)
558                 {
559                     value = element.getFullyQualifiedName();
560                 }
561                 // Otherwise, just use the taggedValue String, and hope things line up with the model.
562                 // Add java.lang. if needed...
563                 value = JavaTypeConverter.getJavaLangTypeName((String)value);
564             }
565             if (value instanceof HibernateType)
566             {
567                 value = ((HibernateType)value).getFullyQualifiedHibernateType();
568             }
569         }
570 
571         return (value != null) ? ObjectUtils.toString(value) : null;
572     }
573 
574     /**
575      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isMap()
576      */
577     @Override
578     protected boolean handleIsMap()
579     {
580         boolean isMap = this.getCollectionType().equalsIgnoreCase(COLLECTION_TYPE_MAP);
581 
582         if (isMap && StringUtils.isBlank(this.getSpecificCollectionType()))
583         {
584             isMap = !this.isOrdered();
585         }
586 
587         return isMap;
588     }
589 
590     /**
591      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isList()
592      */
593     @Override
594     protected boolean handleIsList()
595     {
596         boolean isList = this.getCollectionType().equalsIgnoreCase(COLLECTION_TYPE_LIST);
597 
598         if (!isList && StringUtils.isBlank(this.getSpecificCollectionType()))
599         {
600             isList = this.isOrdered();
601         }
602 
603         return isList;
604     }
605 
606     /**
607      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isSet()
608      */
609     @Override
610     protected boolean handleIsSet()
611     {
612         boolean isSet = this.getCollectionType().equalsIgnoreCase(COLLECTION_TYPE_SET);
613 
614         if (isSet && StringUtils.isBlank(this.getSpecificCollectionType()))
615         {
616             isSet = !this.isOrdered();
617         }
618 
619         return isSet;
620     }
621 
622     /**
623      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isBag()
624      */
625     @Override
626     protected boolean handleIsBag()
627     {
628         return this.getCollectionType().equalsIgnoreCase(COLLECTION_TYPE_BAG);
629     }
630 
631     /**
632      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getCollectionTypeImplementation()
633      */
634     @Override
635     protected String handleGetCollectionTypeImplementation()
636     {
637         StringBuilder implementation = new StringBuilder();
638 
639         if (this.isMany())
640         {
641             implementation.append("new ");
642 
643             if (this.isSet())
644             {
645                 implementation.append(this.getConfiguredProperty(HibernateGlobals.SET_TYPE_IMPLEMENTATION));
646             }
647             else if (this.isMap())
648             {
649                 implementation.append(this.getConfiguredProperty(HibernateGlobals.MAP_TYPE_IMPLEMENTATION));
650             }
651             else if (this.isBag())
652             {
653                 implementation.append(this.getConfiguredProperty(HibernateGlobals.BAG_TYPE_IMPLEMENTATION));
654             }
655             else if (this.isList())
656             {
657                 implementation.append(this.getConfiguredProperty(HibernateGlobals.LIST_TYPE_IMPLEMENTATION));
658             }
659 
660             // set this association end's type as a template parameter if required
661             if (Boolean.valueOf(String.valueOf(this.getConfiguredProperty(UMLMetafacadeProperties.ENABLE_TEMPLATING)))
662                        .booleanValue())
663             {
664                 implementation.append('<');
665                 if (this.isMap())
666                 {
667                     implementation.append(this.getCollectionIndexType());
668                     implementation.append(", ");
669                 }
670                 implementation.append(this.getType().getFullyQualifiedName());
671                 implementation.append('>');
672             }
673 
674             implementation.append("()");
675         }
676 
677         return implementation.toString();
678     }
679 
680     /**
681      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getHibernateAggregationCascade()
682      */
683     @Override
684     protected String handleGetHibernateAggregationCascade()
685     {
686         return StringUtils.trimToEmpty(ObjectUtils.toString(this.getConfiguredProperty(HIBERNATE_AGGREGATION_CASCADE)));
687     }
688 
689     /**
690      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getHibernateCompositionCascade()
691      */
692     @Override
693     protected String handleGetHibernateCompositionCascade()
694     {
695         return StringUtils.trimToEmpty(ObjectUtils.toString(this.getConfiguredProperty(HIBERNATE_COMPOSITION_CASCADE)));
696     }
697 
698     /**
699      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isBidirectionalOrderedListParent()
700      */
701     @Override
702     protected boolean handleIsBidirectionalOrderedListParent()
703     {
704         boolean isBidirectionalOrderedListParent = false;
705         boolean biDirectional = this.isNavigable() && this.getOtherEnd().isNavigable();
706 
707         if (biDirectional && this.isOne2Many() && (this.getOtherEnd() instanceof HibernateAssociationEnd))
708         {
709             HibernateAssociationEnd otherEnd = (HibernateAssociationEnd)this.getOtherEnd();
710 
711             isBidirectionalOrderedListParent =
712                 otherEnd.getCollectionType().equals(COLLECTION_TYPE_LIST) && otherEnd.isIndexedCollection();
713         }
714 
715         return isBidirectionalOrderedListParent;
716     }
717 
718     /**
719      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isBidirectionalOrderedListChild()
720      */
721     @Override
722     protected boolean handleIsBidirectionalOrderedListChild()
723     {
724         boolean biDirectional = false;
725         if (this.getOtherEnd() instanceof HibernateAssociationEnd)
726         {
727             HibernateAssociationEnd otherEnd = (HibernateAssociationEnd)this.getOtherEnd();
728             biDirectional = otherEnd.isBidirectionalOrderedListParent();
729         }
730         return biDirectional;
731     }
732 
733     /**
734      * @return HibernateGlobals.HIBERNATE_VERSION
735      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd
736      */
737     protected boolean handleIsUsingHibernate3()
738     {
739         boolean usingHibernate3 = false;
740         String property = (String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_VERSION);
741         if (property != null)
742         {
743             usingHibernate3 = property.startsWith(HibernateGlobals.HIBERNATE_VERSION_3);
744         }
745         return usingHibernate3;
746     }
747 
748     /**
749      * @return NameMasker.mask(this.getCollectionIndexName(), NameMasker.UPPERCAMELCASE)
750      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getCollectionIndexName()
751      */
752     protected String handleGetCollectionIndexNameGetter()
753     {
754         return "get" + NameMasker.mask(
755             this.getCollectionIndexName(),
756             NameMasker.UPPERCAMELCASE);
757     }
758 
759     /**
760      * @return NameMasker.mask(this.getCollectionIndexName(), NameMasker.UPPERCAMELCASE)
761      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getCollectionIndexName()
762      */
763     protected String handleGetCollectionIndexNameSetter()
764     {
765         return "set" + NameMasker.mask(
766             this.getCollectionIndexName(),
767             NameMasker.UPPERCAMELCASE);
768     }
769 
770     private boolean isVersion3()
771     {
772         return HibernateUtils.isVersion3((String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_VERSION));
773     }
774 
775     private boolean isVersion4()
776     {
777         return HibernateUtils.isVersion4((String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_VERSION));
778     }
779 
780     private boolean isXMLPersistenceActive()
781     {
782         return HibernateUtils.isXmlPersistenceActive(
783             (String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_VERSION),
784             (String)this.getConfiguredProperty(HibernateGlobals.HIBERNATE_XML_PERSISTENCE));
785     }
786 
787     /**
788      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getEmbedXML()
789      */
790     @Override
791     protected String handleGetEmbedXML()
792     {
793         String embedVal = null;
794 
795         if (isXMLPersistenceActive())
796         {
797             embedVal = (String)this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_XML_EMBED);
798 
799             if (StringUtils.isBlank(embedVal))
800             {
801                 boolean isBiDirectional = this.isNavigable() && this.getOtherEnd().isNavigable();
802                 if (isBiDirectional && this.isMany())
803                 {
804                     embedVal = "false";
805                 }
806                 else
807                 {
808                     embedVal = "true";
809                 }
810             }
811         }
812         return (StringUtils.isBlank(embedVal)) ? null : embedVal;
813     }
814 
815     /**
816      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#getXmlTagName()
817      */
818     @Override
819     protected String handleGetXmlTagName()
820     {
821         String tagName = null;
822 
823         if (isXMLPersistenceActive())
824         {
825             tagName = (String)this.findTaggedValue(HibernateProfile.TAGGEDVALUE_HIBERNATE_XML_TAG_NAME);
826 
827             if (StringUtils.isBlank(tagName))
828             {
829                 tagName = this.getName();
830             }
831         }
832         return (StringUtils.isBlank(tagName)) ? null : tagName;
833     }
834 
835     /**
836      * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd#isOwning()
837      */
838     @Override
839     protected boolean handleIsOwning()
840     {
841         boolean owning = false;
842         if (this.isAggregation() || this.isComposition())
843         {
844             owning = true;
845         }
846         else if (!this.isNavigable())
847         {
848             owning = true;
849         }
850         return owning;
851     }
852 }