Index: src/test/com/thoughtworks/acceptance/BooleanFieldsTest.java =================================================================== --- src/test/com/thoughtworks/acceptance/BooleanFieldsTest.java (revision 0) +++ src/test/com/thoughtworks/acceptance/BooleanFieldsTest.java (revision 0) @@ -0,0 +1,123 @@ +package com.thoughtworks.acceptance; + +import com.thoughtworks.xstream.converters.basic.BooleanConverter; + +import java.util.List; +import java.util.ArrayList; + +/** + * @author David Blevins + */ +public class BooleanFieldsTest extends AbstractAcceptanceTest { + + public static class Musican { + public String name; + public String genre; + public boolean alive; + + public Musican(String name, String genre, boolean alive) { + this.name = name; + this.genre = genre; + this.alive = alive; + } + } + + public void testTrueFalseValues() { + List jazzIcons = new ArrayList(); + jazzIcons.add(new Musican("Miles Davis", "jazz", false)); + jazzIcons.add(new Musican("Wynton Marsalis", "jazz", true)); + + xstream.alias("musician", Musican.class); + + String expectedXml = + "\n" + + " \n" + + " Miles Davis\n" + + " jazz\n" + + " false\n" + + " \n" + + " \n" + + " Wynton Marsalis\n" + + " jazz\n" + + " true\n" + + " \n" + + ""; + + assertBothWays(jazzIcons, expectedXml); + } + + public void testYesNoValues() { + List jazzIcons = new ArrayList(); + jazzIcons.add(new Musican("Miles Davis", "jazz", false)); + jazzIcons.add(new Musican("Wynton Marsalis", "jazz", true)); + + xstream.alias("musician", Musican.class); + xstream.registerConverter(BooleanConverter.YES_NO); + + String expectedXml = + "\n" + + " \n" + + " Miles Davis\n" + + " jazz\n" + + " no\n" + + " \n" + + " \n" + + " Wynton Marsalis\n" + + " jazz\n" + + " yes\n" + + " \n" + + ""; + + assertBothWays(jazzIcons, expectedXml); + } + + public void testBinaryValues() { + List jazzIcons = new ArrayList(); + jazzIcons.add(new Musican("Miles Davis", "jazz", false)); + jazzIcons.add(new Musican("Wynton Marsalis", "jazz", true)); + + xstream.alias("musician", Musican.class); + xstream.registerConverter(BooleanConverter.BINARY); + + String expectedXml = + "\n" + + " \n" + + " Miles Davis\n" + + " jazz\n" + + " 0\n" + + " \n" + + " \n" + + " Wynton Marsalis\n" + + " jazz\n" + + " 1\n" + + " \n" + + ""; + + assertBothWays(jazzIcons, expectedXml); + } + + public void testEmptyElementImplied() { + List jazzIcons = new ArrayList(); + jazzIcons.add(new Musican("Miles Davis", "jazz", false)); + jazzIcons.add(new Musican("Wynton Marsalis", "jazz", true)); + xstream.registerConverter(BooleanConverter.EMPTY_ELEMENT); + + xstream.alias("musician", Musican.class); + + String expectedXml = + "\n" + + " \n" + + " Miles Davis\n" + + " jazz\n" + + " \n" + + " \n" + + " Wynton Marsalis\n" + + " jazz\n" + + " \n" + + " \n" + + ""; + + assertBothWays(jazzIcons, expectedXml); + } + +} Index: src/java/com/thoughtworks/xstream/converters/basic/BooleanConverter.java =================================================================== --- src/java/com/thoughtworks/xstream/converters/basic/BooleanConverter.java (revision 847) +++ src/java/com/thoughtworks/xstream/converters/basic/BooleanConverter.java (working copy) @@ -1,19 +1,73 @@ package com.thoughtworks.xstream.converters.basic; +import com.thoughtworks.xstream.converters.ConditionalConverter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; + /** * Converts a boolean primitive or java.lang.Boolean wrapper to * a String. * * @author Joe Walnes + * @author David Blevins */ -public class BooleanConverter extends AbstractSingleValueConverter { +public class BooleanConverter implements Converter, ConditionalConverter { + public static final BooleanConverter TRUE_FALSE = new BooleanConverter("true", "false", false); + + public static final BooleanConverter YES_NO = new BooleanConverter("yes", "no", false); + + public static final BooleanConverter BINARY = new BooleanConverter("1", "0", true); + + public static final BooleanConverter EMPTY_ELEMENT = new BooleanConverter() { + public boolean shouldConvert(Class type, Object obj) { + Boolean value = (Boolean) obj; + return value.booleanValue(); + } + + public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + } + + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + return Boolean.TRUE; + } + }; + + private final String positive; + private final String negative; + private final boolean caseSensitive; + + public BooleanConverter(String positive, String negative, boolean caseSensitive) { + this.positive = positive; + this.negative = negative; + this.caseSensitive = caseSensitive; + } + + public BooleanConverter() { + this("true", "false", false); + } + + public boolean shouldConvert(Class type, Object value) { + return true; + } + public boolean canConvert(Class type) { return type.equals(boolean.class) || type.equals(Boolean.class); } - public Object fromString(String str) { - return str.equals("true") ? Boolean.TRUE : Boolean.FALSE; + public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + Boolean value = (Boolean) source; + writer.setValue(value.booleanValue() ? positive : negative); } + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + if (caseSensitive) { + return positive.equals(reader.getValue()) ? Boolean.TRUE : Boolean.FALSE; + } else { + return positive.equalsIgnoreCase(reader.getValue()) ? Boolean.TRUE : Boolean.FALSE; + } + } }