users@jaxb.java.net

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

From: Wolfgang Laun <wolfgang.laun_at_gmail.com>
Date: Thu, 17 Dec 2009 20:52:32 +0100

So I should caution you that @XmlJavaTypeAdapter and @XmlRootElement are not
compatible. The adapter is not called if <e> is a document root.

For classes such as ThirdPartyElement, which users contribute for
marshalling and
unmarshalling, you can force them to use factory methods
  public E newInstance(final V1 v1){
      return V_1;
  }
  public E newInstance(final V2 v2){
      return V_2;
  }
which won't let them create any wild E objects in the first place.

-W


On Thu, Dec 17, 2009 at 7:54 PM, Markus Karg <markus.karg_at_gmx.net> wrote:

> Wolfgang,
>
>
>
> I never said that your code is not working at all, but just the proposed
> solution it outlines does not work in my particular case. The problem is
> that third parties might use class E in conjunction with their own code, e.
> g.
>
>
>
> @XmlRootElement
>
> public class ThirdPartyElement {
>
> public E e;
>
> }
>
>
>
> In that case, the third party author must take care to implement the
> singleton support you are proposing. As a result, that singleton support
> ends up in lots of places, and if only one of them are broken…: Happy
> searching! ;-)
>
>
>
> The cause is that the unmarshall-Callbacks cannot replace the current
> object. It just can modify the object, or it can modify the parent, what
> both is suboptimal.
>
>
>
> The solution I just sent to the mailing list solves this problem, as the
> singleton stuff in self-contained in the class E itself. So no third party
> author has to take care, resulting in no code places which could break. For
> me, this looks like the ultimate solution to the problem, but maybe you have
> a better idea? :-)
>
>
>
> Regards
>
> Markus
>
>
>
> *From:* Wolfgang Laun [mailto:wolfgang.laun_at_gmail.com]
> *Sent:* Donnerstag, 17. Dezember 2009 18:45
>
> *To:* users_at_jaxb.dev.java.net
> *Subject:* Re: FW: How to map Java enum to XML element (not #PCDATA) body?
>
>
>
> Markus,
>
> this has to be discussed with a little more background. I understand that
> you have an XML schema, which apparently defines <e> with a subordinate
> choice with alternatives <v1/>,...<vN/>. No Java code is generated from this
> schema; you write the class E by hand.
>
> One would think that elements <e> occurs in the XML schema, and that's why
> I wonder what these objects E might have to do with the API you are
> providing. If you are providing unmarshalling for XML according to the
> schema, my proposed solution works.
>
> Marshalling is slightly different, but you haven't used this word yet ;-)
>
> A short sample code of what your API must provide in connection with class
> E might help.
>
> -W
>
>
> On Thu, Dec 17, 2009 at 3:40 PM, Markus Karg <markus.karg_at_gmx.net> wrote:
>
> 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
>
>
>
>
>