users@jaxb.java.net

Re: Use Enum Member Field as value in serializing?

From: Wolfgang Laun <wolfgang.laun_at_gmail.com>
Date: Sun, 19 Jul 2009 08:54:27 +0200

Here is the complete code for the type adapter, as Aleksei has suggested,
for marhalling an integer in place of an enum.

@XmlJavaTypeAdapter( MyEnumAdapter.class )
public enum MyEnum {
    CONSTANT1(1, "constant1"),
    CONSTANT2(2, "constant2"),
    CONSTANT3(3, "constant3");

    private int id;
    private String name;

    MyEnum (int id, String name) {...}

    // ...getters
}

public final class MyEnumAdapter
    extends XmlAdapter<Integer,MyEnum> {

    private static Map<Integer,MyEnum> int2enum;

    private MyEnum convert( Integer i ){
        if( int2enum == null ){
            int2enum = new HashMap<Integer,MyEnum>();
            for( MyEnum me: EnumSet.allOf( MyEnum.class ) ){
        int2enum.put( me.getId(), me );
            }
        }
        return int2enum.get( i );
    }

    @Override
    public Integer marshal( MyEnum value ){
        return value.getId();
    }

    @Override
    public MyEnum unmarshal( Integer value ){
        return convert( value );
    }
}

public class MyClass {

    // final
    private MyEnum attr;

    @XmlAttribute(name="id")
    public MyEnum getAttr(){
        return attr;
    }

    public void setAttr( MyEnum attr ){
        if( this.attr != null ) throw new IllegalStateException( "..." );
        this.attr = attr;
    }
}

Cheers
-W

On Thu, Jul 16, 2009 at 11:26 PM, Pinch, Marnee <Marnee.Pinch_at_pearson.com>wrote:

> I have an enumeration where each member has an ‘int id’ field. I want to
> use this field to identify the member during marshalling and unmarshalling,
> not the name of the member itself.
>
>
>
> One way to do it is to add @XmlEnumValue with the String representation of
> the id:
>
>
>
> public enum MyEnum {
>
>
>
> @XmlEnumValue("1")
>
> CONSTANT1(1, "constant1"),
>
>
>
> @XmlEnumValue("2")
>
> CONSTANT2(2, "constant2"),
>
>
>
> ...
>
>
>
> MyEnum (int id, String name) {
>
> this.id = id;
>
> this.name = name;
>
> }
>
> }
>
>
>
> public class MyClass {
>
>
>
> @XmlAttribute(name="id")
>
> MyEnum someEnum;
>
> }
>
>
>
> So, the desired output is:
>
>
>
> <MyClass id="1"/>
>
>
>
> This works, but we have a lot of members and don’t want to have to annotate each member.
>
>
>
> There is a second way which doesn’t require annotating the enum members at all. This is the way I’m currently doing it. I use a private getter and setter in the class that references the enum, as follows:
>
>
>
> public class MyClass {
>
>
>
> private final SomeType type;
>
>
>
>
>
> @XmlAttribute(name="id")
>
>
>
> private int getTypeId() {
>
> return type.getID();
>
> }
>
>
>
> private void setTypeId(int typeId) {
>
> try {
>
> final Field typeField = getClass().getDeclaredField("type");
>
> typeField.setAccessible(true);
>
> typeField.set(this, SomeType.fromID(typeId));
>
> }
>
> catch (NoSuchFieldException ex) {
>
> throw new RuntimeException(ex);
>
> }
>
> catch (IllegalAccessException ex) {
>
> throw new RuntimeException(ex);
>
> }
>
> }
>
> }
>
> We need to use reflection to set the type field since it is final and we want it to stay that way.
>
> Both methods work.
>
>
>
> However, I am wondering if there might be an even easier way to indicate
> that the ‘id’ field in the enum member is to be used to identify the enum in
> the XML?
>
>
>
>
>
> Thanks,
>
> Marnee
>
>
>
>
>