users@jaxb.java.net

FW: How to map Java enum to XML element (not #PCDATA) body?

From: Markus Karg <markus.karg_at_gmx.net>
Date: Thu, 17 Dec 2009 15:40:33 +0100

Anybody having an idea how to solve this?

 

From: Markus Karg [mailto:markus.karg_at_gmx.net]
Sent: Dienstag, 15. Dezember 2009 21:33
To: 'users_at_jaxb.dev.java.net'
Subject: RE: How to map Java enum to XML element (not #PCDATA) body?

 

Wolfgang,

 

your proposed solution unfortunately does not work! :-(

 

You are assuming that I know locations of any code that is using my enum.
But this is not the case. I am writing a library that anybody can use. The
job of providing a singleton has to be done *inside* my library (i. e. JAXB
itself must know that an instance has to be replaced by another instance
*before* providing the reference to a using instance), not *outside* (not in
the caller's class). Otherwise each user would have to know about the
singleton problem and take care of it, what is very, very error prone.

 

I need a solution that works *within* my library. Somethink like an
"Unmarshal Resolver". I know I can register unmarshal listeners, but how to
tell in that's event handler that the outcome is a *different* instance?

 

Thanks!

Markus

 

From: Wolfgang Laun [mailto:wolfgang.laun_at_gmail.com]
Sent: Dienstag, 15. Dezember 2009 20:15
To: users_at_jaxb.dev.java.net
Subject: Re: How to map Java enum to XML element (not #PCDATA) body?

 

What you want is a unique instance of E for each of the unique settings of
its fields v1, v2,... with a unique instance of V1, V2,..., respectively.

Since you are not compiling the Java classes from the XML schema, you could
write all setters of fields of type E so that

public void setE( E e ){
    this.e = E.getSingleton( e );
}

E.getSingleton() would have to determine which of e's fields v1, v2,... is
not null and return the corresponding E.V_1, E.V_2,...

-W

On Tue, Dec 15, 2009 at 5:58 PM, Markus Karg <markus.karg_at_gmx.net> wrote:

Using @XmlEnumValue it is possible to map Java enums to XML elements, like
in this example>

 

@XmlRootElement

public enum E {

  @XmlEnumValue("v1") V_1,

  @XmlEnumValue("v2") V_2,

  .

}

 

While this is working fine in case of #PCDATA values, I now am experiencing
the problem that I need to map values that are not #PCDATA but in fact are
XML elements:

 

For example,

 

<e><v1/></e>

 

shall result in the same Java enum instance than

 

<e>

    <v1>

    </v1>

</e>

 

and so on.

 

That means, I cannot write

 

@XmlEnumValue("<v1/>") V_1,

@XmlEnumValue("<v2/>") V_2,

 

in Java, because that would not result in an instance of B when
unmarshalling a formatted XML file.

 

Can anybody tell me a solution working in JAXB 2.1 that will solve this
problem?

 

I started with a rather complex workaround like this one (derived from the
singleton pattern):

 

@XmlAccessorType(FIELD)

@XmlRootElement

public class E {

  public static final E V_1 = new E(new V1());

  public static final E V_2 = new E(new V2());

  private V1 v1;

  private V2 v2;

  private E() { }

  private E(V1 v1) { this.v1 = v1; }

  private E(V2 v2) { this.v2 = v2; }

}

 

@XmlRootElement

public final class V1 { }

 

@XmlRootElement

public final class V2 { }

 

This perfectly unmarshalls any kind of formatting and whitespacing of
<e><v1/></e> and I am really happy with it so far, BUT it does not produce
singletongs. Instead, I am getting another instance of E and V1 each time.
This is rather bad, since I now must use the equals operator to compare
them, while it would be certainly great to in fact have the same instances
to be able to compare references:

 

if (unmarshalledObject == E.V1)

 

So my questions are:

 

* How can I get singletons, i. e. always the same instance of E.V1 and E.V2
instead of new copies for each reference?

 

* Ain't there a simpler way to get enums with dynamically formatted and
whitespaced XML element bodies?

 

BTW, since the XML schema is far out of my control, I am sorry, no, I cannot
change the fact that the body is not a #PCDATA but an XML element.

 

Thanks a lot!

Markus