2015-04-22 2 views
5

Для локального конвертера, при сортировке по XML, есть ли способ доступа к родительскому объекту?XStream получить родительский объект в конвертере

Мне нужно собрать коллекцию с элементами из стороннего источника - с использованием идентификатора, хранящегося в родительском объекте.

Увы, похоже, нет способа запросить путь объекта, ведущий к текущему объекту. Или есть?

+0

У меня есть проблемы похожую. Вы нашли решение? TIA – t777

+0

Я принял это, потому что это давно. :-) –

ответ

0

Я нашел решение с мало-мальски reflaction:

import java.io.InputStream; 
import java.lang.reflect.Field; 
import java.util.List; 
import java.util.Map; 

import org.junit.Test; 
import org.springframework.util.ReflectionUtils; 

import com.thoughtworks.xstream.XStream; 
import com.thoughtworks.xstream.annotations.XStreamAlias; 
import com.thoughtworks.xstream.annotations.XStreamAsAttribute; 
import com.thoughtworks.xstream.converters.Converter; 
import com.thoughtworks.xstream.converters.MarshallingContext; 
import com.thoughtworks.xstream.converters.UnmarshallingContext; 
import com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller; 
import com.thoughtworks.xstream.io.HierarchicalStreamReader; 
import com.thoughtworks.xstream.io.HierarchicalStreamWriter; 
import com.thoughtworks.xstream.io.path.Path; 

import lombok.Data; 

public class XStreamGetInfoFromParentTest { 

    @Test 
    public void smokeTest() { 
     InputStream file = XStreamGetInfoFromParentTest.class.getResourceAsStream("XStreamGetInfoFromParentTest.xml"); 

     XStream xStream = new XStream() { 
      @Override 
      public void registerConverter(Converter converter, int priority) { 
       Converter myConverter = new MyConverterWrapper(converter); 
       super.registerConverter(myConverter, priority); 
      } 
     }; 
     xStream.processAnnotations(Papa.class); 
     xStream.processAnnotations(Baby.class); 

     Papa papa = (Papa) xStream.fromXML(file); 

     System.out.println(papa); 
    } 

    public class MyConverterWrapper implements Converter { 

     private Converter converter; 
     private boolean isBabyClass; 

     public MyConverterWrapper(Converter converter) { 
      this.converter = converter; 
     } 

     @Override 
     public boolean canConvert(Class type) { 
      this.isBabyClass = type.equals(Baby.class); 
      return converter.canConvert(type); 
     } 

     @Override 
     public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
      this.converter.marshal(source, writer, context); 
     } 

     @SuppressWarnings({ "unchecked", "rawtypes" }) 
     @Override 
     public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
      if (isBabyClass) { 
       AbstractReferenceUnmarshaller runm = (AbstractReferenceUnmarshaller) context; 

       Field field = ReflectionUtils.findField(AbstractReferenceUnmarshaller.class, "values"); 
       field.setAccessible(true); 
       Map values = (Map) ReflectionUtils.getField(field, runm); 

       values.forEach((key, value) -> { 
        System.out.println(key + " : " + value); 
       }); 

       Papa papa = (Papa) values.get(new Path("/papa")); 
       System.out.println(papa.firstname); 
      } 

      return converter.unmarshal(reader, context); 
     } 

    } 

    @XStreamAlias("papa") 
    @Data 
    public class Papa { 

     @XStreamAsAttribute 
     private String firstname; 

     private int age; 

     private List<Baby> babies; 

    } 

    @XStreamAlias("baby") 
    @Data 
    public class Baby { 
     private String firstname; 
    } 

} 

XML:

<?xml version="1.0" encoding="UTF-8"?> 
<papa firstname="Adam"> 
     <age>33</age> 
     <babies> 
      <baby> 
       <firstname>Eva</firstname> 
      </baby> 
     </babies> 
</papa> 
Смежные вопросы