castor
  1. castor
  2. CASTOR-1313

Cannot unmarshall HashMap with multivalued value

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 0.9.9.1
    • Fix Version/s: 1.1.1
    • Component/s: XML
    • Labels:
      None
    • Environment:
      Java 1.3.1_06 on Win2K and Solaris
    • Number of attachments :
      3

      Description

      If you marshal a HashMap that has values that are themselves collections or arrays (see #1175 for this problem related to String[]), the marshalling works, but Castor cannot unmarshall what it creates. A mapping that looks like the following should allow a Collection value:
      <mapping>
      <class name="Outer" auto-complete="false" >
      <map-to xml="outer"/>
      <field name="theMap" collection="map">
      <bind-xml name="map-name" node="element">
      <class name="org.exolab.castor.mapping.MapItem">
      <field name="key" type="string"/>
      <field name="value" collection="collection"/>
      </class>
      </bind-xml>
      </field>
      </class>
      </mapping>

      However, Castor complains that:

      The return type for method public java.lang.Object org.exolab.castor.mapping.MapItem.getValue() does not match the declared field type java.util.Collection

      Without the collection attribute on the field mapping, Castor complains that:

      element "value" occurs more than once.

      To workaround this issue, I created a class like MapItem, called MapCollectionItem (attached), that had:
      Collection value;
      Collection getValue()

      { return value; }

      void setValue( Collection val )

      { value = val; }

      and I added support for using this class where MapItem is used now, when the value is a collection. Changes were to:
      org.exolab.castor.mapping.loader.J1CollectionHandlers.java
      org.exolab.castor.mapping.loader.J2CollectionHandlers.java
      org.exolab.castor.xml.Marshaller.java
      org.exolab.castor.xml.UnmarshalHandler.java

      I also think a change is needed in test code GACollections.

      After this, the marshalled class included the MapCollectionItem reference, but the unmarshall still failed with "element "value" occurs more than once." I tracked this to being a problem where the XMLFieldDescriptor for the value field in the Unmarshaller had the _multivalued flag set to false, even though the collection attribute is set in the field mapping, and the XMLFieldDescriptor for the value field when loading the mapping file has _multivalued set correctly to true. To work around this, I added the following hack to UnmarshalHandler.endElement, around line 729 in the 0.9.9.1 version:

      /****** HACK! HACK! HACK! *************/
      // I cannot get Castor to handle List values in a HashMap.
      // I added support for a MapCollectionItem similar to MapItem, but
      // the XLFieldDescriptor has _multivalued false when it should be true.
      // I could not figure out why, so I override it here.
      if( ! descriptor.isMultivalued() ) {
      if( descriptor instanceof XMLFieldDescriptorImpl ) {
      if( ((XMLFieldDescriptorImpl)descriptor).getFieldType() == Collection.class )

      { ((XMLFieldDescriptorImpl)descriptor).setMultivalued(true); }

      }
      }
      /****** end HACK! HACK! HACK! *************/

      With these changes, I can unmarshal a List value from a HashMap. I do not pretend that my workaround is a fix to the codebase for this problem, as it is ugly and does not handle all multivalued HashMap values (e.g. #1175 would require a different MapItem class for each array type)

        Issue Links

          Activity

          Hide
          Bryan Helm added a comment -

          Failing test case added in bug1313.zip. May need to alter mapping xml file path to run.

          Show
          Bryan Helm added a comment - Failing test case added in bug1313.zip. May need to alter mapping xml file path to run.
          Hide
          Bryan Helm added a comment -

          Added some debug logging, fixed unmarshalling fail message

          Show
          Bryan Helm added a comment - Added some debug logging, fixed unmarshalling fail message
          Hide
          Bryan Helm added a comment -

          I could not figure out a way to update the attachment, so pay attention to date/time and ignore earlier bug1313.zip attachment.

          Show
          Bryan Helm added a comment - I could not figure out a way to update the attachment, so pay attention to date/time and ignore earlier bug1313.zip attachment.
          Hide
          Ralf Joachim added a comment -

          I removed the earlier attachment.

          Show
          Ralf Joachim added a comment - I removed the earlier attachment.
          Hide
          Bryan Helm added a comment -

          Support for mapping HashMap with array value.

          Show
          Bryan Helm added a comment - Support for mapping HashMap with array value.
          Hide
          Bryan Helm added a comment -

          To marshal and unmarshal a HashMap that has array values (see bug #1175), a similar workaround worked. I created a class MapArrayItem (attached), and added support for it everywhere MapItem was referenced, when the value is an instanceof Object[]. I would still like to see Castor be able to unmarshal everything it can marshal, and to support coleciton or array HashMap values with a simpler mapping, but this works for me for now.

          Show
          Bryan Helm added a comment - To marshal and unmarshal a HashMap that has array values (see bug #1175), a similar workaround worked. I created a class MapArrayItem (attached), and added support for it everywhere MapItem was referenced, when the value is an instanceof Object[]. I would still like to see Castor be able to unmarshal everything it can marshal, and to support coleciton or array HashMap values with a simpler mapping, but this works for me for now.
          Hide
          Werner Guttmann added a comment -

          The current XML test suite has numerous tests in this area, incl. maps of arrays, maps of collections, nested maps, etc. As such, I think this issue has been fully resolved some timoe ago.

          Show
          Werner Guttmann added a comment - The current XML test suite has numerous tests in this area, incl. maps of arrays, maps of collections, nested maps, etc. As such, I think this issue has been fully resolved some timoe ago.
          Hide
          Werner Guttmann added a comment -

          Looks like this has been resolved already (most likely when working towards 1.1 or 1.1.1). Marking this as duplicate as such.

          Show
          Werner Guttmann added a comment - Looks like this has been resolved already (most likely when working towards 1.1 or 1.1.1). Marking this as duplicate as such.

            People

            • Assignee:
              Werner Guttmann
              Reporter:
              Bryan Helm
            • Votes:
              2 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: