2016-02-13 5 views
0

Я хотел бы маршаллировать и unmarshall объекты, поля которых относятся к внутреннему классу своего класса (синтетический класс, если я не ошибаюсь).Xstream: unmarshalling внутренние классы

class A { 
    private B field_b=null; 
    public static class B { 
     public static B B1 = new B("b1"); 
     public static B B2 = new B("b2"); 

     private final String name; 
     private B(String name) { 
      this.name=name; 
      } 
     } 
    public B getBforName(String name) { 
     if (B1.name.equals(name) return B1;    
     else if (B2.name.equals(name) return B2; 
     else return null;    
    } 

И производят и чтения из XML:

<A> 
    <field_B>b1</field_B> 
</A> 

Сочинение часть легко.

Читающая часть более сложная.

Я хотел написать конвертер:

public class BConverter implements Converter { 
    public boolean canConvert(Class type) { 
     return B.class.isAssignableFrom(type) ; 
    } 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     // ... 
    } 
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
     A parent_v1 = (A) context.getCurrentObject(); // !!! always empty 
     A parent_v2 = (A) context.get("current_unmarshalled_A"); 

     return parent_v2.getBforName((String)reader.getValue()); 

    } 
} 

В context.getCurrentObject() возвращает нуль и, кажется устаревшим (из форумов я читал).

context.get("current_unmarshalled_A") потребует, чтобы я включил этот ключ unMarshallingContext в этот ключ, а объект A был неармаллирован. Я не нахожу этого, не записывая AConverter. И это не очень удобно, так как я потерял бы стандартное поведение без помех для класса A.

У кого-нибудь есть идея?

ответ

0

Я не уверен, что это самый чистый путь к этому, но он работает.

Я использую статический метод в классе B ...

class A { 
    private B field_b=null; 
    public static class B { 
     public static B B1 = new B("b1"); 
     public static B B2 = new B("b2"); 

     public static B getForName(String name) { 
      if (B1.name.equals(name) return B1;    
      else if (B2.name.equals(name) return B2; 
      else return null;    
     } 

     private final String name; 
     private B(String name) { 
      this.name=name; 
      } 
    } 

... и отражение в конвертер

public class BConverter implements Converter { 
    public boolean canConvert(Class type) { 
     return B.class.isAssignableFrom(type) ; 
    } 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     writer.setValue(((B)source).getName()) 
    } 
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
     try { 
      Method method = context.getRequiredType().getMethod("getForName", String.class); 
      final String v = reader.getValue(); 
      Object b= method.invoke(null, v); 
      if (b== null) 
       throw new ConversionException("Could not retrieve a B object for \"" + v + "\""); 
      return b; 
     } catch (Exception ex) { 
      throw new ConversionException("Error while retrieving a B object", ex); 
     } 
    } 
}