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
>
>
>
>
>