package org.simpleframework.xml.strategy; import java.io.StringWriter; import org.simpleframework.xml.Attribute; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementArray; import org.simpleframework.xml.Root; import org.simpleframework.xml.core.Persister; import org.simpleframework.xml.strategy.CycleStrategy; import org.simpleframework.xml.ValidationTestCase; public class ArrayCycleTest extends ValidationTestCase { private static final String SOURCE = "<?xml version=\"1.0\"?>\n"+ "<root id='main'>\n"+ " <one length='5' id='numbers'>\n\r"+ " <text value='entry one'/> \n\r"+ " <text value='entry two'/> \n\r"+ " <text value='entry three'/> \n\r"+ " <text value='entry four'/> \n\r"+ " <text value='entry five'/> \n\r"+ " </one>\n\r"+ " <two ref='numbers'/>\n"+ " <three length='3'>\n" + " <text value='tom'/> \n\r"+ " <text value='dick'/> \n\r"+ " <text value='harry'/> \n\r"+ " </three>\n"+ " <example ref='main'/>\n"+ "</root>"; private static final String NESTED = "<?xml version=\"1.0\"?>\n"+ "<root id='main'>\n"+ " <array id='array' length='2'>\n" + // NestedExample.array : Value[] " <entry> \n\r"+ " <list ref='array'/>\n"+ // Value.list : Value[] -> NestedArray.array : Value[] " </entry>\r\n"+ " <entry id='text'>\n"+ " <list length='3' id='foo'>\n"+ // Value.list : Value[] " <entry name='blah' class='org.simpleframework.xml.strategy.ArrayCycleTest$TextValue'>\n"+ // Value.list[0] : Value " <text>Some text</text>\n"+ // TextExample.text : String " <list ref='foo'/>\n"+ // TextExample.list : Value[] " </entry>\n"+ " <entry ref='text'/>\n"+ // Value.list[1] : Value " <entry class='org.simpleframework.xml.strategy.ArrayCycleTest$ElementValue'>\n"+ // Value.list[2] : Value " <element><![CDATA[Example element text]]></element>\n"+ // ElementExample.element : String " </entry>\n"+ " </list>\n"+ " </entry> \n\t\n"+ " </array>\n"+ "</root>"; private static final String PROMOTE = "<value>\n"+ " <list length='1' class='org.simpleframework.xml.strategy.ArrayCycleTest$ElementValue'>\n"+ " <entry class='org.simpleframework.xml.strategy.ArrayCycleTest$ElementValue'>\n"+ " <element>Example text</element>\n"+ " </entry>\n"+ " </list>\n"+ "</value>\n"; @Root(name="root") private static class ArrayCycleExample { @ElementArray(name="one", entry="entry") public Entry[] one; @ElementArray(name="two", entry="entry") public Entry[] two; @ElementArray(name="three", entry="entry") public Entry[] three; @Element(name="example") public ArrayCycleExample example; } @Root(name="text") private static class Entry { @Attribute(name="value") public String value; public Entry() { super(); } public Entry(String value) { this.value = value; } } @Root(name="root") private static class NestedArrayCycleExample { @ElementArray(name="array", entry="entry") public Value[] array; } @Root(name="value") private static class Value { @ElementArray(name="list", entry="entry", required=false) private Value[] list; } private static class TextValue extends Value { @Attribute(name="name") private String name; @Element(name="text") private String text; } private static class ElementValue extends Value { @Element(name="element") private String element; } private Persister persister; public void setUp() throws Exception { persister = new Persister(new CycleStrategy("id", "ref")); } public void testCycle() throws Exception { ArrayCycleExample example = persister.read(ArrayCycleExample.class, SOURCE); assertEquals(example.one.length, 5); assertEquals(example.one[0].value, "entry one"); assertEquals(example.one[1].value, "entry two"); assertEquals(example.one[2].value, "entry three"); assertEquals(example.one[3].value, "entry four"); assertEquals(example.one[4].value, "entry five"); assertEquals(example.two.length, 5); assertEquals(example.two[0].value, "entry one"); assertEquals(example.two[1].value, "entry two"); assertEquals(example.two[2].value, "entry three"); assertEquals(example.two[3].value, "entry four"); assertEquals(example.two[4].value, "entry five"); assertEquals(example.three.length, 3); assertEquals(example.three[0].value, "tom"); assertEquals(example.three[1].value, "dick"); assertEquals(example.three[2].value, "harry"); assertTrue(example.one == example.two); assertTrue(example == example.example); StringWriter out = new StringWriter(); persister.write(example, out); example = persister.read(ArrayCycleExample.class, SOURCE); assertEquals(example.one.length, 5); assertEquals(example.one[0].value, "entry one"); assertEquals(example.one[1].value, "entry two"); assertEquals(example.one[2].value, "entry three"); assertEquals(example.one[3].value, "entry four"); assertEquals(example.one[4].value, "entry five"); assertEquals(example.two.length, 5); assertEquals(example.two[0].value, "entry one"); assertEquals(example.two[1].value, "entry two"); assertEquals(example.two[2].value, "entry three"); assertEquals(example.two[3].value, "entry four"); assertEquals(example.two[4].value, "entry five"); assertEquals(example.three.length, 3); assertEquals(example.three[0].value, "tom"); assertEquals(example.three[1].value, "dick"); assertEquals(example.three[2].value, "harry"); assertTrue(example.one == example.two); assertTrue(example == example.example); validate(example, persister); } public void testNestedExample() throws Exception { NestedArrayCycleExample root = persister.read(NestedArrayCycleExample.class, NESTED); assertEquals(root.array.length, 2); assertTrue(root.array[0].list == root.array); assertTrue(root.array[1].list[0] instanceof TextValue); assertTrue(root.array[1].list == root.array[1].list[0].list); assertTrue(root.array[1] == root.array[1].list[1]); assertTrue(root.array[1].list == root.array[1].list[0].list); assertTrue(root.array[1].list[2] instanceof ElementValue); ElementValue element = (ElementValue) root.array[1].list[2]; TextValue text = (TextValue) root.array[1].list[0]; assertEquals(element.element, "Example element text"); assertEquals(text.name, "blah"); assertEquals(text.text, "Some text"); validate(root, persister); StringWriter out = new StringWriter(); persister.write(root, out); // Ensure references survive serialization root = persister.read(NestedArrayCycleExample.class, out.toString()); assertEquals(root.array.length, 2); assertTrue(root.array[0].list == root.array); assertTrue(root.array[1].list[0] instanceof TextValue); assertTrue(root.array[1].list == root.array[1].list[0].list); assertTrue(root.array[1] == root.array[1].list[1]); assertTrue(root.array[1].list == root.array[1].list[0].list); assertTrue(root.array[1].list[2] instanceof ElementValue); element = (ElementValue) root.array[1].list[2]; text = (TextValue) root.array[1].list[0]; assertEquals(element.element, "Example element text"); assertEquals(text.name, "blah"); assertEquals(text.text, "Some text"); } public void testPromotion() throws Exception { Value example = persister.read(Value.class, PROMOTE); assertEquals(example.list.length, 1); assertTrue(example.list instanceof ElementValue[]); ElementValue value = (ElementValue) example.list[0]; assertEquals(value.element, "Example text"); validate(example, persister); } }