Thanks Jörg. It works for me.

Best regards,
Pawel 

-----Original Message-----
From: Jörg Schaible [mailto:joerg.schai...@swisspost.com] 
Sent: Monday, February 03, 2014 2:53 PM
To: user@xstream.codehaus.org
Subject: [xstream-user] Re: Alternative converter invocation when previous's 
call failed

Hi Pawel,

Kowalski, Pawel wrote:

> 
> Hi,
> 
> I have plenty of data (joda DateTime objects) serialized with default
> (ReflectionConverter) now I'd like to simplify serialization and 
> created my own Converter for these  objects. The issue is I'd like to 
> have possibility to support both versions at the same time as there is 
> no possibility to convert already exiting records. What I'm trying to 
> do is simply create new converter that will work more or less like following:
> 
> Try to unmarshall in new version
> If failed
>                 Do something to call another converter (in my case
>                 Reflection Converter)???
> 
> Is there possibility to manage above with existing XStream API? I mean 
> is there any way like throwing some exception to call alternative 
> converter once previous failed, or should I register converters in 
> some specific way?

No.

> How to get access to one converter from another? How to reset the 
> reader to point the same element as it was primary called with (once 
> data read multiple times moveDown/moveUp etc. and then  failed)?

Actually this last question is the problem, why it cannot work this way. 
XStream is stream-based and relies on the underlaying XML parser. There is no 
possibility to reset the individual parsers to a specific mark nor can you 
control the input stream because the parsers also use different caching 
mechanisms i.e. you never know how many of the read bytes have actually been 
processed by the XML parser.

The best option is to use a version attribute in your root element:

========== %< ============
 <root version="2">
[...]
 </root>
========== %< ============

Derive from the converter that will normally handle this element and get the 
version in the unmarshal method:

========== %< ============
  public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext 
context) {
    String version = reader.getAttribute("version");
    context.put("version", version == null ? "1" : version);
    return super.unmarshal(reader, context);
  }
========== %< ============

Now you take a similar approach for the Joda-Time types you want to handle. 
Simply derive from the converter that handled the type in the last version 
(assuming ReflectionConverter for now):

========== %< ============
  class JodaTimeTypeConverter extends ReflectionConverter {
    public JodaTimeTypeConverter(Mapper mapper, ReflectionProvider
reflectionProvider) {
      super(mapper, reflectionProvider);
    }
    boolean canConvert(Class type) {
      return <true for the Joda-Time-Type this converter handles>;
    }
    public void marshal(Object source, HierarchicalStreamWriter writer, 
MarshallingContext context) {
      // your implementation for the new representation
    }
    public Object unmarshal(HierarchicalStreamReader reader, 
UnmarshallingContext context) {
      String version = content.get("version");
      if ("1".equals(version)) { // old format
        return super.unmarshal(reader, context);
      } else {
        // your implementation for the new representation
      }
    }
}
========== %< ============

Cheers,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to