2015-01-13 3 views
2

Я хочу использовать определенный вариант NamedMapConverter (из библиотеки XStream).Можно ли использовать NamedMapConverter в аннотации? Как?

new NamedMapConverter(xstream.getMapper(), "mapping", "value", String.class, "color", HexColor.class, true, true, xstream.getConverterLookup()); 

Но я хочу использовать его в качестве аннотации. Моя догадка внизу. SingleValueConverter для HexColor уже реализован.

@XStreamConverter(value = NamedMapConverter.class, strings = { "mapping", "value", "color" }, booleans = { true, true }, types = { String.class, HexColor.class }) 
    private Map<String, HexColor> colorMappings; 

Но, что удивительно, оно не работает. Что я делаю не так? Пример результата ниже.

<colorMappings> 
     <mapping> 
       <value>Something</value> 
       <color>007cc2</color> 
     </mapping> 
    </colorMappings> 

Я нашел причину странного поведения. Это вызвано ошибкой в ​​библиотеке XStream. В классе AnnotationMapper существует метод cacheConverter.

private Converter cacheConverter(final XStreamConverter annotation, 
    final Class targetType) { 
    Converter result = null; 
    final Object[] args; 
    final List<Object> parameter = new ArrayList<Object>(); 
    if (targetType != null && annotation.useImplicitType()) { 
     parameter.add(targetType); 
    } 
    final List<Object> arrays = new ArrayList<Object>(); 
    arrays.add(annotation.booleans()); 
    arrays.add(annotation.bytes()); 
    arrays.add(annotation.chars()); 
    arrays.add(annotation.doubles()); 
    arrays.add(annotation.floats()); 
    arrays.add(annotation.ints()); 
    arrays.add(annotation.longs()); 
    arrays.add(annotation.shorts()); 
    arrays.add(annotation.strings()); 
    arrays.add(annotation.types()); 
    for(Object array : arrays) { 
     if (array != null) { 
      int length = Array.getLength(array); 
      for (int i = 0; i < length; i++) { 
       Object object = Array.get(array, i); 
       if (!parameter.contains(object)) { 
        parameter.add(object); 
       } 
      } 
     } 
    } 

Ключевой фрагмент повторяется ниже.

   if (!parameter.contains(object)) { 
        parameter.add(object); 
       } 

В результате, если есть два одинаковых значения в любом из массивов (в данном случае - булевы истинные и верные, но проблема будет иметь место и для других повторяющихся значений) только один из них будет добавлен к параметрам. Следовательно, список параметров был бы неправильным (один логический отсутствует) и не соответствовал бы правильному конструктору.

Однако на данный момент я понятия не имею, как создать код вокруг этой проблемы.

+0

Какую версию XStream вы использовали? Знаете ли вы, что это уже исправлено? Указанный метод выглядит иначе в текущей версии '1.4.9'. –

+1

Да, проблема исправлена ​​(я думаю, они исправили ее в версии '1.4.8'). ;] –

ответ

1

простой (но некрасиво) исправление создать новый конвертер, который расширяет NamedMapConverter

public class BetterNamedMapConverter extends NamedMapConverter { 

    public BetterNamedMapConverter(Mapper mapper, String entryName, String keyName, Class keyType, String valueName, Class valueType, 
      boolean asAttributes, ConverterLookup lookup) { 
     super(mapper, entryName, keyName, keyType, valueName, valueType, asAttributes, asAttributes, lookup); 
    } 

} 

и изменить аннотацию

@XStreamConverter(value = BetterNamedMapConverter.class, strings = { "mapping", "value", "color" }, booleans = { true }, types = { String.class, HexColor.class }, useImplicitType = false) 

Тем не менее, ошибка озадачивает меня (и есть случаи, когда работают вокруг этого нужны еще худшие хаки).

Смежные вопросы