Hi Shelly,

It's by (bad) design unfortunately. Initially it wasn't like that, but
to allow people to wrap/unwrap collections so they can be treated as
first class objects (they have an xml element assigned to them) or
simple containers (no xml element for the container itself, only
items/fields within the container are marshalled) a "hack" was added
when the field is a collection. This was really needed when a class had
two collections with the same types of fields.

With non-collection fields there are only two behaviors with the
container attribute. Either it's a container, or it's not. Not
specifying a container defaults to false. If you set container="true"
for an object, only it's fields are marshalled and the object itself has
no representation.

However with a collection, it's a bit different and here's where it can
get tricky (bad-design). Normally the field mapping for a collection
contains some information about both the collection and it's items, but
primarily it controls the items within the collection and not really the
collection itself. So the container attribute was originally intended to
be applied to the items of the collection and not to the collection,
because four years ago we assumed all collections should be containers.
Since the Castor marshaller by default handles all collections as
containers, people eventually needed a way to say that the collection
itself was *not* a container. So a long time ago, on one cold, damp,
rainy (or snowy, you decide) weekend night I decided that I could
squeeze this bit of extra information out of the mapping file without
making any changes to the mapping file object model itself. I decided
that I could make the container attribute apply to both the collection
and the items depending on the IMPLIED nature of attributes. I came up
with explicit container="false" hack. I figured that most people
wouldn't bother putting container="false" in their mapping file since
"false" was implied anyway, so I decided that I could use the explicit
container="false" as a way of saying the collection itself should not be
a container, and therefore should have an element representation. And
there you have it...the bad-design has been exposed. 

So to sum up that paragraph, when dealing with collections, the
container attribute applies to both the container and the items within
the container.

Implied:

So in the mapping file if you don't specify the container attribute on a
collection field, it's assumed to be true for the collection and false
for the items of the collection, so no xml element will be output for
the collection itself. The name specified in the bind-xml (or derived
from the field name) is used as the element name of the items within the
collection. So that's why you get address-list as the element name for
each item when you don't have the container attribute specified. 

Explicit declaration:

If you specify container="false" (my little hack) then this tells the
marshaller that both the collection itself and the items are not
containers. The container is a first class object and should have an
element representation. The element name of the collection is the one
specified in the bind-xml and the element name of the items are taken
from the class mapping for the item itself.

If you specify container="true", it tells the marshaller that both the
collection and the items should be treated as containers...so neither
will have an xml representation. So that's why you get all the fields of
the address objects grouped together like that.


Hopefully that makes sense as to why you get different behaviors, even
if it makes no sense as to why we/I decided to do it that way.

This might be a good summary to add somewhere on the Website or the
CastorWiki.

Anyway...this may be something we may need to revisit, especially now
that we have the "location" attribute support, adding wrappers around
collections is pretty easy.

--Keith

"Mujtaba,Shelly" wrote:
> 
> Sorry about the long winded email...
> I am seeing strange behavior with castor 0.9.5/0.9.4 container attribute:
> I have an employee test class which contains a collection (arraylist) of
> addresses:
> 
> here is the mapping snippet
> <mapping>
>     <class name="org.o2xmapper.test.Employee" auto-complete="false">
>         <description>Default mapping for class
> org.o2xmapper.test.Employee</description>
>         <map-to xml="employee"/>
> ..
>         <field name="addressList" type="org.o2xmapper.test.Address"
>             required="false" direct="false" transient="false"
> container="false" collection="collection">
>             <bind-xml name="address-list" node="element"/>
>         </field>
>     </class>
>  <class name="org.o2xmapper.test.Address" auto-complete="false">
>         <description>Default mapping for class
> org.o2xmapper.test.Address</description>
>         <map-to xml="address"/>
>         <field name="address3" type="string" required="false"
>             direct="false" transient="false">
>             <bind-xml name="address3" node="element"/>
>         </field>
> ...
> Setting container attribute to "false" gives me the following result
> <address-list>
>         <address>
>                 <address2>Chicago</address2>
>                 <address1>1 n franklin</address1>
>                 <state>il</state>
>         </address>
>         <address>
>                 <address2>chicago</address2>
>                 <address1>320 w ohio</address1>
>                 <state>ILLINOIS</state>
>         </address>
> </address-list>
> 
> Now when I set the address list fields container attribute to "true", I get
> the following output for address:
> <address2>Chicago</address2>
> <address1>1 n franklin</address1>
> <state>il</state>
> <address2>chicago</address2>
> <address1>320 w ohio</address1>
> <state>ILLINOIS</state>
> and so on...
> 
> I notice that not only the 'address-list' element is gone, but also the
> 'address' element
> 
> Finally I remove the container attribute completely from the mapping and
> here's my result:
> 
> <address-list>
>         <address2>Chicago</address2>
>         <address1>1 n franklin</address1>
>         <state>il</state>
> </address-list>
> <address-list>
>         <address2>chicago</address2>
>         <address1>320 w ohio</address1>
>         <state>ILLINOIS</state>
> </address-list>
> 
> So I get 3 different behaviors for a boolean attribute
> Just for fun I tried castor 0.9.4 and the  results are similar.
> 
> Is this behavior as designed? If so why ignore the address class level
> mapping if container=true.
> 
> btw, the location feature is very cool, its already the dev. teams at my
> company some serious time.
> 
> -----------------------------------------------------------
> If you wish to unsubscribe from this mailing, send mail to
> [EMAIL PROTECTED] with a subject of:
>         unsubscribe castor-dev

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[EMAIL PROTECTED] with a subject of:
        unsubscribe castor-dev

Reply via email to