Hi all,

I found in the mail archive that this problem has been raised in the past
but it seems haven't been resolved yet.

What I wanted to do is to marshal/unmarshal a simple enum type that has a
different string representation than its name.

Here's a simple test case that demonstrates it:

--- Foo.java

package test;

public class Foo {

    private BarType bar;

    public BarType getBar() {
        return bar;
    }

    public void setBar(BarType bar) {
        this.bar = bar;
    }
}

-- BarType.java

package test;

public enum BarType {
    PING, PONG;

    public String toString() {
        return name().toLowerCase();
    }

    public static BarType fromValue(String s) {
        return valueOf(s.toUpperCase());
    }
}

-- mapping.xml

<?xml version="1.0"?>
<mapping>
 <class name="test.Foo">
   <map-to xml="foo"/>
   <field name="bar" type="test.BarType"/>
 </class>
</mapping>

-- EnumMappingTest.java

package test;

import java.io.FileReader;
import java.io.FileWriter;

import junit.framework.TestCase;

import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.XMLContext;

public class EnumMappingTest extends TestCase {

    public void testEnumMapping() {
        try {
            Foo foo = new Foo();
            foo.setBar(BarType.PONG);

            XMLContext ctx = new XMLContext();
            Mapping mapping = ctx.createMapping();
            mapping.loadMapping("mapping.xml");
            ctx.addMapping(mapping);

            Marshaller ms = ctx.createMarshaller();
            ms.setWriter(new FileWriter("foo.xml"));
            ms.marshal(foo);

            Unmarshaller ums = ctx.createUnmarshaller();
            Foo foo2 = (Foo) ums.unmarshal(new FileReader("foo.xml"));

            assertEquals(foo.getBar(), foo2.getBar());
        } catch (Exception e) {
            e.printStackTrace();
            fail(e.toString());
        }
    }
}



-- And here's the (root) exception

Caused by: java.lang.IllegalStateException:
java.lang.IllegalArgumentException: No enum const class test.BarType.pong
 at
org.exolab.castor.mapping.handlers.EnumFieldHandler.convertUponSet(EnumFieldHandler.java:151)
 at
org.exolab.castor.mapping.GeneralizedFieldHandler.setValue(GeneralizedFieldHandler.java:274)
 at
org.exolab.castor.mapping.GeneralizedFieldHandler.setValue(GeneralizedFieldHandler.java:274)
 at
org.exolab.castor.xml.UnmarshalHandler.endElement(UnmarshalHandler.java:1085)
 at
org.exolab.castor.xml.UnmarshalHandler.endElement(UnmarshalHandler.java:1176)
 at
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
 at
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1772)
 at
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2923)
 at
com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
 at
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:508)
 at
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
 at
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
 at
com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
 at
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
 at
com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
 at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:748)
 at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:626)
 at test.EnumMappingTest.testEnumMapping(EnumMappingTest.java:30)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at junit.framework.TestCase.runTest(TestCase.java:164)
 at junit.framework.TestCase.runBare(TestCase.java:130)
 at junit.framework.TestResult$1.protect(TestResult.java:106)
 at junit.framework.TestResult.runProtected(TestResult.java:124)
 at junit.framework.TestResult.run(TestResult.java:109)
 at junit.framework.TestCase.run(TestCase.java:120)
 at junit.framework.TestSuite.runTest(TestSuite.java:230)
 at junit.framework.TestSuite.run(TestSuite.java:225)
 at
org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
 at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
 at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
 at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
 at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)



I traced through the source code and found that in EnumFieldHandler it is
ultimately calling BarType.valueOf(String) to resolve the string value.
However valueOf(String) is defined implicitly and cannot be overriden.

Moreover, what is point of defining BarType.fromValue(String)? I see it is
called in toPrimitive(...) but the return value is converted back to String
again in ToStringFieldHandler.convertUponSet()...

If I change BarType to pre-1.5 style enum (final class, private constructor)
and implement valueOf(String) then it works fine. (and fromValue() is not
needed too as BarType is no longer considered as primitive.)

I'm using the latest version of castor-xml (1.3). Any idea?

Kenneth

Reply via email to