History | Log In     View a printable version of the current page. Get help!  
Issue Details [XML]

Key: EJB-57
Type: Bug Bug
Status: Open Open
Priority: Major Major
Assignee: Vance Karimi
Reporter: Tun Schlechter
Votes: (View)
Watchers: (View)
Operations

If you were logged in you would be able to see more operations.
EJB Cartridge

UML {ordered} produces invalid code

Created: 17/May/07 06:54 PM   Updated: 10/Jun/08 05:19 PM
Component/s: None
Affects Version/s: None
Fix Version/s: None

File Attachments: 1. Zip Archive bugreport-ordered.zip (63 kb)

Environment: AndroMDA 3.3-SNAPSHOT on Windows using EJB3-cartridge (HEAD-checkout from 16th may 2007)


 Description   
A one to many association between 2 <<entity>> classes [Class_1 and Class_2] with {ordered} tag on the many side produces the following code within Class_1:

private java.util.Set<Class_2> class_2s = new java.util.ArrayList<Class_2>();

and thus the expected following error:

C:\work\bugreport-ordered\core\target\src\Class_1.java:[35,46] incompatible types
found : java.util.ArrayList<Class_2>
required: java.util.Set<Class_2>


 All   Comments   Change History      Sort Order:
Comment by Tun Schlechter [17/May/07 06:56 PM]
Attached a zargo-file (ArgoUML, zip including .xmi-file) with an example Model, the generated code and log-files

Comment by Leandro Hermida [09/Jun/08 05:21 PM]
Hi Vance,

I am trying to fix this small bug and just having a bit of trouble figuring out why the current EJB3 cart code is not working.

First, in EntityEmbeddable.vsl, the area of interest:

[code]#* *##if ($target.many)
    private $target.getterSetterTypeName $target.name = $target.collectionTypeImplementation;
#* *##else[/code]

So I then go to find out why the getterSetterTypeName is giving the wrong datatype. So in EJB3AssociationEndFacadeLogicImpl.java:

[code] public String getGetterSetterTypeName()
    {
        String getterSetterTypeName = null;
        
        if (this.isMany())
        {
            final boolean specificInterfaces =
                Boolean.valueOf(
                    ObjectUtils.toString(this.getConfiguredProperty(SPECIFIC_COLLECTION_INTERFACES))).booleanValue();
            
            final TypeMappings mappings = this.getLanguageMappings();
            if (mappings != null)
            {
                if (this.isMap())
                {
                    getterSetterTypeName = mappings.getTo(UMLProfile.MAP_TYPE_NAME);
                }
                else if (specificInterfaces)
                {
                    if (this.isSet())
                    {
                        getterSetterTypeName = mappings.getTo(UMLProfile.SET_TYPE_NAME);
                    }
                    else if (this.isList())
                    {
                        getterSetterTypeName = mappings.getTo(UMLProfile.LIST_TYPE_NAME);
                    }
                    else if (this.isCollection())
                    {
                        getterSetterTypeName = mappings.getTo(UMLProfile.COLLECTION_TYPE_NAME);
                    }
                }
                else
                {
                    getterSetterTypeName = this.getDefaultCollectionInterface();
                }
            }
            else
            {
                getterSetterTypeName = this.getDefaultCollectionInterface();
            }
        }[/code]


What is causing getterSetterTypeName to evaluate to the default java.util.Set when the association end is ordered? Is it falling through into one of the two else statements which assign the default java.util.Set dataype. To me it looks like it should be working properly...

leandro

Comment by Vance Karimi [10/Jun/08 05:19 PM]
Hi Leandro,

You're right, the reason why the datatype defaults to java.util.Set is because the 'specificCollectionInterfaces' namespace property is set to false in the namespace.xml of the cartridge. Hence, the default datatype is defined in the 'defaultCollectionInterface' namespace property, which as you guessed, is java.util.Set.

Then, getCollectionTypeImplementation calls getCollectionTypeImplemenationClass which checks if the many end is modeled as a set, map, list or collection (in that order). The isSet, isMap, isList and isCollection methods all check if the ordering has been set. If ordering is set, then the set and map types are not used. So for list or collection ends, the ArrayList implementation is used.

I can't remember what impact it will have to set the specificCollectionInterfaces namespace property to true, but I do recall I had problems using List. Look back through the forums and have a read of the changes.xml (Line 127). I originally changed it from List to to SortedSet, then later changed it to TreeSet (Line 249), then finally changed it to Set (Line 254).

We could leave the defaultCollectionInterfaces as is (Set). In getGetterSetterTypeName where we are invoking getDefaultCollectionInterface to get the default type, we should instead check if ordering has been defined and return an appropriate type, such as List. This would require a bit of testing.