Log Message
ToAttributedValueConverter fails to write enums as attributes (XSTR-741).
Modified Paths
Diff
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java (2080 => 2081)
--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java 2013-07-01 23:32:45 UTC (rev 2080)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/ToAttributedValueConverter.java 2013-07-02 22:52:03 UTC (rev 2081)
@@ -22,16 +22,21 @@
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
+import com.thoughtworks.xstream.converters.ConverterMatcher;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.DuplicateFieldException;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
+import com.thoughtworks.xstream.core.JVM;
+import com.thoughtworks.xstream.core.util.DependencyInjectionFactory;
import com.thoughtworks.xstream.core.util.FastField;
import com.thoughtworks.xstream.core.util.HierarchicalStreams;
import com.thoughtworks.xstream.core.util.Primitives;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.AttributeMapper;
+import com.thoughtworks.xstream.mapper.DefaultMapper;
import com.thoughtworks.xstream.mapper.Mapper;
@@ -50,6 +55,7 @@
private static final String STRUCTURE_MARKER = "";
private final Class type;
private final Mapper mapper;
+ private final Mapper enumMapper;
private final ReflectionProvider reflectionProvider;
private final ConverterLookup lookup;
private final Field valueField;
@@ -100,8 +106,23 @@
}
this.valueField = field;
}
+ enumMapper = JVM.is15() ? createEnumMapper(mapper) : null;
}
+ private Mapper createEnumMapper(final Mapper mapper) {
+ try {
+ Class enumMapperClass = Class.forName(
+ "com.thoughtworks.xstream.mapper.EnumMapper", true,
+ Mapper.class.getClassLoader());
+ return (Mapper)DependencyInjectionFactory.newInstance(
+ enumMapperClass,
+ new Object[]{new UseAttributeForEnumMapper(mapper
+ .lookupMapperOfType(DefaultMapper.class))});
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
public boolean canConvert(final Class type) {
return this.type == type;
}
@@ -135,7 +156,9 @@
throw exception;
}
- Converter converter = mapper.getLocalConverter(definedIn, fieldName);
+ ConverterMatcher converter = isEnum(type)
+ ? enumMapper.getConverterFromItemType(null, type, null)
+ : mapper.getLocalConverter(definedIn, fieldName);
if (converter == null) {
converter = lookup.lookupConverterForType(type);
}
@@ -219,7 +242,9 @@
Class type = field.getType();
final Class declaringClass = field.getDeclaringClass();
- Converter converter = mapper.getLocalConverter(declaringClass, fieldName);
+ ConverterMatcher converter = isEnum(type)
+ ? enumMapper.getConverterFromItemType(null, type, null)
+ : mapper.getLocalConverter(declaringClass, fieldName);
if (converter == null) {
converter = lookup.lookupConverterForType(type);
}
@@ -315,4 +340,39 @@
return valueField.getName().equals(field.getName())
&& valueField.getDeclaringClass().getName().equals(field.getDeclaringClass());
}
+
+ private static boolean isEnum(Class type) {
+ while(type != Object.class) {
+ if (type.getName().equals("java.lang.Enum")) {
+ return true;
+ }
+ type = type.getSuperclass();
+ }
+ return false;
+ }
+
+ private static class UseAttributeForEnumMapper extends AttributeMapper {
+
+ public UseAttributeForEnumMapper(Mapper wrapped) {
+ super(wrapped, null, null);
+ }
+
+ @Override
+ public boolean shouldLookForSingleValueConverter(String fieldName, Class type,
+ Class definedIn) {
+ return isEnum(type);
+ }
+
+ @Override
+ public SingleValueConverter getConverterFromItemType(String fieldName, Class type,
+ Class definedIn) {
+ return null;
+ }
+
+ @Override
+ public SingleValueConverter getConverterFromAttribute(Class definedIn,
+ String attribute, Class type) {
+ return null;
+ }
+ }
}
Modified: trunk/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java (2080 => 2081)
--- trunk/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java 2013-07-01 23:32:45 UTC (rev 2080)
+++ trunk/xstream/src/test/com/thoughtworks/acceptance/annotations/ParametrizedConverterTest.java 2013-07-02 22:52:03 UTC (rev 2081)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011, 2012 XStream Committers.
+ * Copyright (C) 2008, 2009, 2011, 2012, 2013 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -21,6 +21,7 @@
import com.thoughtworks.xstream.annotations.XStreamConverters;
import com.thoughtworks.xstream.converters.basic.BooleanConverter;
import com.thoughtworks.xstream.converters.collections.MapConverter;
+import com.thoughtworks.xstream.converters.enums.SimpleEnum;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import com.thoughtworks.xstream.converters.extended.ToStringConverter;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
@@ -106,7 +107,7 @@
String expected = ""
+ "<type>\n"
+ " <decimal>1.5</decimal>\n"
- + " <bool>true</bool>\n"
+ + " <boolean>true</boolean>\n"
+ " <agreement>yes</agreement>\n"
+ "</type>";
@@ -124,6 +125,7 @@
@XStreamConverter(ToStringConverter.class)
private Decimal decimal = null;
@XStreamConverter(ToStringConverter.class)
+ @XStreamAlias("boolean")
private Boolean bool = null;
@XStreamConverter(value=BooleanConverter.class, booleans={true}, strings={"yes", "no"})
private Boolean agreement = null;
@@ -136,19 +138,22 @@
}
public void testConverterWithSecondTypeParameter() {
- final Type value = new DerivedType(new Decimal("1.5"), new Boolean(true));
- String expected = "<dtype bool='true' agreement='yes'>1.5</dtype>".replace('\'', '"');
+ final Type value = new DerivedType(new Decimal("1.5"), new Boolean(true), DerivedType.E.FOO);
+ String expected = "<dtype boolean='true' agreement='yes' enum='FOO'>1.5</dtype>".replace('\'', '"');
assertBothWays(value, expected);
}
@XStreamAlias("dtype")
@XStreamConverter(value=ToAttributedValueConverter.class, types={Type.class}, strings={"decimal"})
public static class DerivedType extends Type {
+ public enum E { FOO, BAR };
+ @XStreamAlias("enum")
+ private E e;
- public DerivedType(Decimal decimal, Boolean bool) {
+ public DerivedType(Decimal decimal, Boolean bool, E e) {
super(decimal, bool);
+ this.e = e;
}
-
}
public void testAnnotatedJavaBeanConverter() {
Modified: trunk/xstream-distribution/src/content/changes.html (2080 => 2081)
--- trunk/xstream-distribution/src/content/changes.html 2013-07-01 23:32:45 UTC (rev 2080)
+++ trunk/xstream-distribution/src/content/changes.html 2013-07-02 22:52:03 UTC (rev 2081)
@@ -119,6 +119,7 @@
<ul>
<li>JIRA:XSTR-709: Locks up on Mac with Apple JVM due to unwanted initialization of AWT.</li>
<li>JIRA:XSTR-711: DateConverter cannot handle dates in different era.</li>
+ <li>JIRA:XSTR-741: ToAttributedValueConverter fails to write enums as attributes.</li>
<li>JIRA:XSTR-712: HibernateMapper throws NPE if a collection contains null.</li>
<li>DateConverter supports now localized formats.</li>
<li>JIRA:XSTR-710: JsonWriter does not write BigInteger and BigDecimal as number values.</li>
To unsubscribe from this list please visit:
