Title: [2176] branches/v-1.4.x: Merge new NamedArrayConverter from trunk.

Diff

Copied: branches/v-1.4.x/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedArrayConverter.java (from rev 2175, trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedArrayConverter.java) (0 => 2176)


--- branches/v-1.4.x/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedArrayConverter.java	                        (rev 0)
+++ branches/v-1.4.x/xstream/src/java/com/thoughtworks/xstream/converters/extended/NamedArrayConverter.java	2013-12-03 23:49:41 UTC (rev 2176)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 XStream Committers.
+ * All rights reserved.
+ *
+ * The software in this package is published under the terms of the BSD
+ * style license a copy of which has been included with this distribution in
+ * the LICENSE.txt file.
+ *
+ * Created on 03. December 2013 by Joerg Schaible
+ */
+package com.thoughtworks.xstream.converters.extended;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.core.util.HierarchicalStreams;
+import com.thoughtworks.xstream.core.util.Primitives;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+/**
+ * @author Jörg Schaible
+ *
+ * @since upcoming
+ */
+public class NamedArrayConverter implements Converter {
+
+    private final Class arrayType;
+    private final String itemName;
+    private final Mapper mapper;
+
+    /**
+     * Construct a NamedArrayConverter.
+     * @param arrayType
+     * @param mapper
+     * @param itemName
+     * @since upcoming
+     */
+    public NamedArrayConverter(final Class arrayType, final Mapper mapper, final String itemName) {
+        if (!arrayType.isArray()) {
+            throw new IllegalArgumentException(arrayType.getName() + " is not an array");
+        }
+        this.arrayType = arrayType;
+        this.mapper = mapper;
+        this.itemName = itemName;
+    }
+
+    public boolean canConvert(final Class type) {
+        return type == arrayType;
+    }
+
+    public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
+        final int length = Array.getLength(source);
+        for (int i = 0; i < length; ++i) {
+            final Object item = Array.get(source, i);
+            final Class itemType = item == null 
+                    ? Mapper.Null.class 
+                    : arrayType.getComponentType().isPrimitive()
+                        ?  Primitives.unbox(item.getClass())
+                        : item.getClass();
+            ExtendedHierarchicalStreamWriterHelper.startNode(writer, itemName, itemType);
+            if (!itemType.equals(arrayType.getComponentType())) {
+                final String attributeName = mapper.aliasForSystemAttribute("class");
+                if (attributeName != null) {
+                    writer.addAttribute(attributeName, mapper.serializedClass(itemType));
+                }
+            }
+            if (item != null) {
+                context.convertAnother(item);
+            }
+            writer.endNode();
+        }
+    }
+
+    public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
+        final List list = new ArrayList();
+        while (reader.hasMoreChildren()) {
+            reader.moveDown();
+            final Object item;
+            final String className = HierarchicalStreams.readClassAttribute(reader, mapper);
+            final Class itemType = className == null ? arrayType.getComponentType() : mapper.realClass(className);
+            if (Mapper.Null.class.equals(itemType)) {
+                item = null;
+            } else {
+                item = context.convertAnother(null, itemType);
+            }
+            list.add(item);
+            reader.moveUp();
+        }
+        final Object array = Array.newInstance(arrayType.getComponentType(), list.size());
+        for (int i = 0; i < list.size(); ++i) {
+            Array.set(array, i, list.get(i));
+        }
+        return array;
+    }
+
+}

Modified: branches/v-1.4.x/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java (2175 => 2176)


--- branches/v-1.4.x/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java	2013-12-03 23:46:40 UTC (rev 2175)
+++ branches/v-1.4.x/xstream/src/test/com/thoughtworks/acceptance/NamedLocalElementsTest.java	2013-12-03 23:49:41 UTC (rev 2176)
@@ -6,7 +6,7 @@
  * style license a copy of which has been included with this distribution in
  * the LICENSE.txt file.
  *
- * Created on 20.09.2013 by Joerg Schaible
+ * Created on 20. September 2013 by Joerg Schaible
  */
 package com.thoughtworks.acceptance;
 
@@ -17,6 +17,7 @@
 
 import com.thoughtworks.acceptance.objects.Category;
 import com.thoughtworks.acceptance.objects.SampleMaps;
+import com.thoughtworks.xstream.converters.extended.NamedArrayConverter;
 import com.thoughtworks.xstream.converters.extended.NamedCollectionConverter;
 import com.thoughtworks.xstream.converters.extended.NamedMapConverter;
 
@@ -31,6 +32,7 @@
         super.setUp();
         xstream.alias("category", Category.class);
         xstream.alias("maps", SampleMaps.class);
+        xstream.alias("arrays", Arrays.class);
         xstream.aliasField("products", SampleMaps.class, "good");
         xstream.addDefaultImplementation(LinkedHashMap.class, Map.class);
     }
@@ -478,4 +480,124 @@
             // OK
         }
     }
+    
+    public static class Arrays {
+        String[] strings;
+        Object[] objects;
+        int[] ints;
+        short[][] shortArrays;
+    }
+    
+    public void testArrayWithFinalType() {
+        xstream.registerLocalConverter(Arrays.class, "strings", 
+            new NamedArrayConverter(String[].class, xstream.getMapper(), "name"));
+        
+        Arrays arrays = new Arrays();
+        arrays.strings = new String[] {
+            "joe", "mauro" 
+        };
+        
+        String expected = ""
+            + "<arrays>\n"
+            + "  <strings>\n"
+            + "    <name>joe</name>\n"
+            + "    <name>mauro</name>\n"
+            + "  </strings>\n"
+            + "</arrays>";
+        
+        assertBothWays(arrays, expected);
+    }
+    
+    public void testArrayWithSuperTypes() {
+        xstream.registerLocalConverter(Arrays.class, "objects", 
+            new NamedArrayConverter(Object[].class, xstream.getMapper(), "item"));
+        
+        Arrays arrays = new Arrays();
+        arrays.objects = new Object[] {
+            "joe", Boolean.TRUE, new Integer(47) 
+        };
+        
+        String expected = (""
+            + "<arrays>\n"
+            + "  <objects>\n"
+            + "    <item class='string'>joe</item>\n"
+            + "    <item class='boolean'>true</item>\n"
+            + "    <item class='int'>47</item>\n"
+            + "  </objects>\n"
+            + "</arrays>").replace('\'', '"');
+        
+        assertBothWays(arrays, expected);
+    }
+    
+    public void testArrayWithNullElement() {
+        xstream.registerLocalConverter(Arrays.class, "strings", 
+            new NamedArrayConverter(String[].class, xstream.getMapper(), "name"));
+        
+        Arrays arrays = new Arrays();
+        arrays.strings = new String[] {
+            "joe", null, "mauro" 
+        };
+        
+        String expected = ""
+            + "<arrays>\n"
+            + "  <strings>\n"
+            + "    <name>joe</name>\n"
+            + "    <name class=\"null\"/>\n"
+            + "    <name>mauro</name>\n"
+            + "  </strings>\n"
+            + "</arrays>";
+        
+        assertBothWays(arrays, expected);
+    }
+    
+    public void testArrayWithPrimitives() {
+        xstream.registerLocalConverter(Arrays.class, "ints", 
+            new NamedArrayConverter(int[].class, xstream.getMapper(), "value"));
+        
+        Arrays arrays = new Arrays();
+        arrays.ints = new int[] {
+            47, 0, -3 
+        };
+        
+        String expected = ""
+            + "<arrays>\n"
+            + "  <ints>\n"
+            + "    <value>47</value>\n"
+            + "    <value>0</value>\n"
+            + "    <value>-3</value>\n"
+            + "  </ints>\n"
+            + "</arrays>";
+        
+        assertBothWays(arrays, expected);
+    }
+    
+    public void testArrayWithPrimitiveArrays() {
+        xstream.registerLocalConverter(Arrays.class, "shortArrays", 
+            new NamedArrayConverter(short[][].class, xstream.getMapper(), "values"));
+        
+        Arrays arrays = new Arrays();
+        arrays.shortArrays = new short[][] {
+            {47, 0, -3},
+            null,
+            {13, 7} 
+        };
+        
+        String expected = ""
+            + "<arrays>\n"
+            + "  <shortArrays>\n"
+            + "    <values>\n"
+            + "      <short>47</short>\n"
+            + "      <short>0</short>\n"
+            + "      <short>-3</short>\n"
+            + "    </values>\n"
+            + "    <values class=\"null\"/>\n"
+            + "    <values>\n"
+            + "      <short>13</short>\n"
+            + "      <short>7</short>\n"
+            + "    </values>\n"
+            + "  </shortArrays>\n"
+            + "</arrays>";
+        
+        assertBothWays(arrays, expected);
+    }
 }

Modified: branches/v-1.4.x/xstream-distribution/src/content/changes.html (2175 => 2176)


--- branches/v-1.4.x/xstream-distribution/src/content/changes.html	2013-12-03 23:46:40 UTC (rev 2175)
+++ branches/v-1.4.x/xstream-distribution/src/content/changes.html	2013-12-03 23:49:41 UTC (rev 2176)
@@ -63,6 +63,7 @@
     	</li>
     	<li>JIRA:XSTR-739 and JIRA:XSTR-746: OrderRetainingMap fails if HashMap.putAll(Map) of Java Runtime is not
     	implemented calling put for every element within the map.</li>
+    	<li>New NamedArrayConverter to define names of inner elements.</li>
     </ul>
 
     <h2>Minor changes</h2>
@@ -75,6 +76,7 @@
     <h2>API changes</h2>
 
     <ul>
+    	<li>Added c.t.x.converters.extended.NamedArrayConverter for free element names in arrays.</li>
     	<li>Added constructors to c.t.x.io.xml.StandardStaxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>
     	<li>Deprecated constructors of c.t.x.io.xml.StandardStaxDriver taking a XmlFriendlyNameCoder.</li>
     	<li>Added constructors to c.t.x.io.xml.BEAStaxDriver taking NameCoder instead of XmlFriendlyNameCoder.</li>

Modified: branches/v-1.4.x/xstream-distribution/src/content/converters.html (2175 => 2176)


--- branches/v-1.4.x/xstream-distribution/src/content/converters.html	2013-12-03 23:46:40 UTC (rev 2175)
+++ branches/v-1.4.x/xstream-distribution/src/content/converters.html	2013-12-03 23:49:41 UTC (rev 2176)
@@ -52,7 +52,7 @@
             </tr>
             <tr>
                 <td><a href=""
-                <td>Any kind of array</td>
+                <td>any kind of array</td>
                 <td class="example">
                     &lt;<i>string</i>-array&gt;<br/>
                     &nbsp;&nbsp;&lt;<i>string</i>&gt;apple&lt;/<i>string</i>&gt;<br/>
@@ -83,12 +83,12 @@
                 <td>byte[]</td>
                 <td class="example">&lt;byte-array&gt;AHiEFiEABQ==&lt;/byte-array&gt;</td>
                 <td>Uses Base64 encoding to store binary data in XML. Converter can be registered globally or locally.</td>
-                <td>&nbsp;</td>
+                <td>normal</td>
             </tr>
             <tr>
                 <td><a href=""
                 <td>char<br/>java.lang.Character</td>
-                <td class="example">&lt;char&gt;X&lt;/char&gt;</br>&lt;char null=&quot;true&quot;/&gt;</td>
+                <td class="example">&lt;char&gt;X&lt;/char&gt;<br/>&lt;char null=&quot;true&quot;/&gt;</td>
                 <td>The '\0' character is invalid in XML.</td>
                 <td>normal</td>
             </tr>
@@ -128,6 +128,20 @@
                 <td>normal</td>
             </tr>
             <tr>
+                <td><a href=""
+                <td>any kind of array</td>
+                <td class="example">
+                    &lt;<i>string</i>-array&gt;<br/>
+                    &nbsp;&nbsp;&lt;<i>product</i>&gt;apple&lt;/<i>product</i>&gt;<br/>
+                    &nbsp;&nbsp;&lt;<i>product</i>&gt;banana&lt;/<i>product</i>&gt;<br/>
+                    &nbsp;&nbsp;&lt;<i>product</i>&gt;cabbage&lt;/<i>product</i>&gt;<br/>
+                    &lt;<i>string</i>-array&gt;
+                </td>
+                <td>This supports arrays of primitives as well as objects. It also supports multi-dimensional arrays, even if
+                they are non-rectangular.  Should be registered locally or for an individual array type.</td>
+                <td>&nbsp;</td>
+            </tr>
+            <tr>
                 <td><a href=""
                 <td>short<br/>java.lang.Short</td>
                 <td class="example">&lt;short&gt;1445&lt;/short&gt;</td>

To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to