001package org.andromda.cartridges.hibernate.metafacades;
002
003import java.util.ArrayList;
004import java.util.Collection;
005
006import org.andromda.cartridges.hibernate.HibernateProfile;
007import org.andromda.cartridges.hibernate.HibernateUtils;
008import org.andromda.metafacades.uml.ClassifierFacade;
009import org.andromda.metafacades.uml.EntityAssociationEnd;
010import org.andromda.metafacades.uml.EntityMetafacadeUtils;
011import org.andromda.metafacades.uml.ModelElementFacade;
012import org.andromda.metafacades.uml.NameMasker;
013import org.andromda.metafacades.uml.TypeMappings;
014import org.andromda.metafacades.uml.UMLMetafacadeProperties;
015import org.andromda.metafacades.uml.UMLProfile;
016import org.andromda.utils.JavaTypeConverter;
017import org.apache.commons.lang.BooleanUtils;
018import org.apache.commons.lang.ObjectUtils;
019import org.apache.commons.lang.StringUtils;
020
021/**
022 * MetafacadeLogic implementation for
023 * org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd.
024 *
025 * @see org.andromda.cartridges.hibernate.metafacades.HibernateAssociationEnd
026 */
027public class HibernateAssociationEndLogicImpl
028    extends HibernateAssociationEndLogic
029{
030    private static final long serialVersionUID = 34L;
031    /**
032     * @param metaObject
033     * @param context
034     */
035    public HibernateAssociationEndLogicImpl(
036        Object metaObject,
037        String context)
038    {
039        super(metaObject, context);
040    }
041
042    /**
043     * Value for set
044     */
045    private static final String COLLECTION_TYPE_SET = "set";
046
047    /**
048     * Value for map
049     */
050    private static final String COLLECTION_TYPE_MAP = "map";
051
052    /**
053     * Value for bags
054     */
055    private static final String COLLECTION_TYPE_BAG = "bag";
056
057    /**
058     * Value for list
059     */
060    private static final String COLLECTION_TYPE_LIST = "list";
061
062    /**
063     * Value for collections
064     */
065    private static final String COLLECTION_TYPE_COLLECTION = "collection";
066
067    /**
068     * Stores the valid collection types
069     */
070    private static final Collection<String> collectionTypes = new ArrayList<String>();
071
072    static
073    {
074        collectionTypes.add(COLLECTION_TYPE_SET);
075        collectionTypes.add(COLLECTION_TYPE_MAP);
076        collectionTypes.add(COLLECTION_TYPE_BAG);
077        collectionTypes.add(COLLECTION_TYPE_LIST);
078        collectionTypes.add(COLLECTION_TYPE_COLLECTION);
079    }
080
081    /**
082     * Stores the property indicating whether or not composition should define
083     * the eager loading strategy.
084     */
085    private static final String COMPOSITION_DEFINES_EAGER_LOADING = "compositionDefinesEagerLoading";
086
087    /**
088     * Stores the default outerjoin setting for this association end.
089     */
090    private static final String PROPERTY_ASSOCIATION_END_OUTERJOIN = "hibernateAssociationEndOuterJoin";
091
092    /**
093     * Stores the default collection index name.
094     */
095    private static final String COLLECTION_INDEX_NAME = "associationEndCollectionIndexName";
096
097    /**
098     * Stores the default collection index type.
099     */
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}