/******************************************************************************* * Copyright (c) 2010-2014 SAP AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * SAP AG - initial API and implementation *******************************************************************************/ package org.eclipse.skalli.core.rest; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; import org.eclipse.skalli.commons.FormatUtils; import org.eclipse.skalli.services.rest.RestWriter; import org.eclipse.skalli.testutil.TestUUIDs; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * */ @SuppressWarnings("nls") public class XMLRestWriterTest { private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"; //$NON-NLS-1$ private StringWriter writer; private RestWriter restWriter; @Before public void setup() throws Exception { writer = new StringWriter(); restWriter = new XMLRestWriter(writer, "http://example.org", JSONRestWriter.NAMED_ROOT); } @Test public void testAnonymousArray() throws Exception { restWriter .array() .value("x") .value(4711) .value(1.0) .value(true) .end() .flush(); assertEquals("<item>x</item><item>4711</item><item>1.0</item><item>true</item>"); } @Test public void testArrayVariousNumbers() throws Exception { restWriter .array() .value((byte)42) .value((short)-1) .value((int)4711) .value(4711L) .value((float)1.0) .value(1.0d) .value(new BigInteger("4711")) .value(new BigDecimal(1.0d)) .value(1.0) .end() .flush(); assertEquals("<item>42</item><item>-1</item><item>4711</item><item>4711</item><item>1.0</item>" + "<item>1.0</item><item>4711</item><item>1</item><item>1.0</item>"); } @Test public void testArrayWithKey() throws Exception { restWriter .key("k").array() .value("x") .value(4711) .value(1.0) .value(false) .end() .flush(); assertEquals("<k><item>x</item><item>4711</item><item>1.0</item><item>false</item></k>"); } @Test public void testCollection() throws Exception { restWriter .collection("k", "i", Arrays.asList("a", "b")) .flush(); assertEquals("<k><i>a</i><i>b</i></k>"); } @Test public void testArrayWithItemKeys() throws Exception { restWriter .array("e") .value("x") .value(4711) .value(1.0) .value(true) .end() .flush(); assertEquals("<e>x</e><e>4711</e><e>1.0</e><e>true</e>"); } @Test public void testNamedArrayWithItemKeys() throws Exception { restWriter .array("k", "e") .value("x") .value(4711) .value(1.0) .value(true) .end() .flush(); assertEquals("<k><e>x</e><e>4711</e><e>1.0</e><e>true</e></k>"); } @Test public void testArrayWithKeyAndItemKeys() throws Exception { restWriter .key("k").array("e") .value("x") .value(4711) .value(1.0) .value(true) .end() .flush(); assertEquals("<k><e>x</e><e>4711</e><e>1.0</e><e>true</e></k>"); } @Test public void testArrayWithKeyAndNullItemKey() throws Exception { restWriter .array("k", null) .value("x") .value(4711) .value(1.0) .value(false) .end() .flush(); assertEquals("<k><item>x</item><item>4711</item><item>1.0</item><item>false</item></k>"); } @Test public void testArrayNullKeyAndNullItemKey() throws Exception { restWriter .array(null, null) .value("x") .value(4711) .value(1.0) .value(false) .end() .flush(); assertEquals("<item>x</item><item>4711</item><item>1.0</item><item>false</item>"); } @Test(expected=IllegalStateException.class) public void testArrayInvalidNamedValues() throws Exception { restWriter .array() .pair("foo", "bar"); } @Test public void testArrayWithUnnamedItems() throws Exception { restWriter .array() .item().value("x").end() .item().value(4711).end() .item().value(1.0).end() .item().value(true).end() .end() .flush(); assertEquals("<item>x</item><item>4711</item><item>1.0</item><item>true</item>"); } @Test public void testArrayWithNamedItems() throws Exception { restWriter .array() .item("a").value("x").end() .item("b").value(4711).end() .item("c").value(1.0).end() .end() .flush(); assertEquals("<a>x</a><b>4711</b><c>1.0</c>"); } @Test public void testArrayWithPartiallyNamedItems() throws Exception { restWriter .array("a") .item().value("x").end() .item("b").value(4711).end() .item().value(1.0).end() .end() .flush(); assertEquals("<a>x</a><b>4711</b><b>1.0</b>"); } @Test public void testArrayOverrideGlobalItemKey() throws Exception { restWriter .array("a") .item("b").value("x").end() .end() .flush(); assertEquals("<b>x</b>"); } @Test public void testArrayWithInnerUnnamedObject() throws Exception { restWriter .array() .object() .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .pair("b", true) .end() .end() .flush(); assertEquals("<item><x>foo</x><y>4711</y><z>1.0</z><b>true</b></item>"); } @Test public void testArrayWithMultipleUnnamedObjects() throws Exception { restWriter .array() .object().pair("x", "foo").end() .object().pair("y", 4711).end() .object().pair("z", 1.0).end() .object().pair("b", false).end() .end() .flush(); assertEquals("<item><x>foo</x></item><item><y>4711</y></item><item><z>1.0</z></item><item><b>false</b></item>"); } @Test public void testArrayWithMultipleNamedObjects() throws Exception { restWriter .array() .object("a").pair("x", "foo").end() .object("b").pair("y", 4711).end() .object("c").pair("z", 1.0).end() .end() .flush(); assertEquals("<a><x>foo</x></a><b><y>4711</y></b><c><z>1.0</z></c>"); } @Test public void testArrayWithInnerObjectNamedByItemKey() throws Exception { restWriter .array() .item("e") .object() .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .end() .end() .flush(); assertEquals("<e><x>foo</x><y>4711</y><z>1.0</z></e>"); } @Test public void testArrayWithInnerUnnamedArray() throws Exception { restWriter .array() .array() .value("x") .value(4711) .value(1.0) .end() .end() .flush(); assertEquals("<item><item>x</item><item>4711</item><item>1.0</item></item>"); } @Test public void testArrayWithInnerNamedObject() throws Exception { restWriter .array() //define itemKey="item" .object("inner") // key "inner" overwrites itemKey! .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .key("other").object() // key "other" overwrites itemKey! .pair("x", "foo") .end() .object() // itemKey is still "other" .pair("y", "bar") .end() .array() // itemKey is still "other", but for the array values it is "item" .value("1") .value("2") .end() .array("w") // itemKey is still "other", but for the array values it is "w" .value("1") .value("2") .end() .array("k", "w") // key "k" overwrites itemKey , but for the array values it is "w" .value("1") .value("2") .end() .end() .flush(); assertEquals("<inner><x>foo</x><y>4711</y><z>1.0</z></inner>" + "<other><x>foo</x></other><other><y>bar</y></other>" + "<other><item>1</item><item>2</item></other>" + "<other><w>1</w><w>2</w></other>" + "<k><w>1</w><w>2</w></k>"); } @Test public void testArrayInnerNamedObjectIgnoreItemKey() throws Exception { restWriter .array("outter", "item") //define itemKey="item" .object("inner") // object key "inner" overrules itemKey! .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .object() // no object key => use itemKey .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .end() .flush(); assertEquals("<outter><inner><x>foo</x><y>4711</y><z>1.0</z></inner>" + "<inner><x>foo</x><y>4711</y><z>1.0</z></inner></outter>"); } @Test public void testArrayInnerObjectWithItemKey() throws Exception { restWriter .array("outter", "inner") .object() .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .end() .flush(); assertEquals("<outter><inner><x>foo</x><y>4711</y><z>1.0</z></inner></outter>"); } @Test public void testNamedArrayWithAttributeNoItems() throws Exception { restWriter .array("k", "e") .attribute("a", "b") .end() .flush(); assertEquals("<k a=\"b\"/>"); } @Test public void testNamedArrayWithAttributeAndItems() throws Exception { restWriter .array("k", "e") .attribute("a", "b") .attribute("c", "d") .value("x") .value(4711) .value(1.0) .end() .flush(); assertEquals("<k a=\"b\" c=\"d\"><e>x</e><e>4711</e><e>1.0</e></k>"); } @Test public void testNestedArraysDifferentItemNames() throws Exception { restWriter .array("k", "a") //renders <k> and itemKey:="a" .array("b") //renders <a> and itemKey:= "b" .array() // renders <b> and itemKey:="item" .array("c") //renders <item> and itemKey:="c" .value("x") //renders <c>x</c> .end() //renders </item> .array("d") //renders <item> and itemKey:="d" .value("y") //renders <d>y</d> .end() //renders </item> .end() //renders </b> .array() //renders <b> and itemKey:="item" .value("z") //renders <item>z</item> .end() //renders </b> .end() //renders </a> .array("e") //renders <a> and itemKey:="e" .value("w") //renders <e>w</e> .end() //renders </a> .end() //renders </k> .flush(); assertEquals("<k><a><b><item><c>x</c></item><item><d>y</d></item></b><b><item>z</item></b></a><a><e>w</e></a></k>"); } @Test public void testNestedAnyonmousInnerArray() throws Exception { restWriter .object("o") //renders <o> .attribute("a", 4711) .array("p") //itemKey:="p" .object() //renders <p> .pair("x", "1") //renders <x>1</x> .array() .link("rel", "href") .end() .end() .object() .pair("y", "2") .end() .end() .end() //renders </o> .flush(); assertEquals("<o a=\"4711\"><p><x>1</x><link rel=\"rel\" href=\"href\"/></p><p><y>2</y></p></o>"); } @Test public void testUnnamedArrayWithAttributes() throws Exception { restWriter .array() .attribute("a", "b") .attribute("x", "y") .end() .flush(); assertEquals("<item a=\"b\"/><item x=\"y\"/>"); } @Test public void testUnnamedArrayWithItemKeyAndAttributes() throws Exception { restWriter .array("foo") .attribute("a", "b") .attribute("x", "y") .end() .flush(); assertEquals("<foo a=\"b\"/><foo x=\"y\"/>"); } @Test public void testUnnamedArrayWithAttributeAndItems() throws Exception { restWriter .array("e") .attribute("a", "b") .attribute("c", "d") .value("x") .value(4711) .value(1.0) .end() .flush(); assertEquals("<e a=\"b\"/><e c=\"d\"/><e>x</e><e>4711</e><e>1.0</e>"); } @Test public void testAttributeAfterItem() throws Exception { restWriter .array() .value("x") .attribute("a", "b") .end() .flush(); assertEquals("<item>x</item><item a=\"b\"/>"); } @Test public void testAttributeAfterNamedItem() throws Exception { restWriter .array("k", "e") .value("x") .attribute("a", "b") .end() .flush(); assertEquals("<k><e>x</e><e a=\"b\"/></k>"); } @Test public void testAttributeAfterItemOverwriteNames() throws Exception { restWriter .array("k", "overwritten") .item("x").value("x").end() .item("y").attribute("a", "b").end() .end() .flush(); assertEquals("<k><x>x</x><y a=\"b\"/></k>"); } @Test public void testAnonymousObject() throws Exception { restWriter .object() .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .flush(); assertEquals("<x>foo</x><y>4711</y><z>1.0</z>"); } @Test public void testObjectVariousNumbers() throws Exception { restWriter .object() .pair("a", (byte)42) .pair("b", (short)-1) .pair("c", (int)4711) .pair("d", 4711L) .pair("e", (float)1.0) .pair("f", 1.0d) .pair("g", new BigInteger("4711")) .pair("h", new BigDecimal(1.0d)) .pair("i", 1.0) .end() .flush(); assertEquals("<a>42</a><b>-1</b><c>4711</c><d>4711</d><e>1.0</e><f>1.0</f><g>4711</g><h>1</h><i>1.0</i>"); } @Test public void testEmptyAnonymousObject() throws Exception { restWriter .object() .end() .flush(); assertEquals(""); } @Test public void testNamedObject() throws Exception { restWriter .object("k") .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .flush(); assertEquals("<k><x>foo</x><y>4711</y><z>1.0</z></k>"); } @Test public void testEmptyNamedObject() throws Exception { restWriter .object("k") .end() .flush(); assertEquals("<k/>"); } @Test public void testObjectWithKey() throws Exception { restWriter .key("k").object() .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .flush(); assertEquals("<k><x>foo</x><y>4711</y><z>1.0</z></k>"); } @Test public void testObjectOverrideKey() throws Exception { restWriter .key("foo").object("bar") .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .flush(); assertEquals("<bar><x>foo</x><y>4711</y><z>1.0</z></bar>"); } @Test public void testObjectWithInnerObject() throws Exception { restWriter .key("outter").object() .key("inner").object() .pair("x", "foo") .pair("y", 4711) .pair("z", 1.0) .end() .end() .flush(); assertEquals("<outter><inner><x>foo</x><y>4711</y><z>1.0</z></inner></outter>"); } @Test public void testObjectWithAttributeAndValue() throws Exception { restWriter .object("k") .attribute("a", "b") .attribute("c", 4711) .attribute("d", 1.0) .attribute("e", true) .attribute("f", TestUUIDs.TEST_UUIDS[0]) .pair("g", "b") .pair("h", 4711) .pair("i", 1.0) .pair("j", true) .pair("k", TestUUIDs.TEST_UUIDS[0]) .value("foobar") .end() .flush(); assertEquals("<k a=\"b\" c=\"4711\" d=\"1.0\" e=\"true\" f=\"" + TestUUIDs.TEST_UUIDS[0].toString() + "\">" + "<g>b</g><h>4711</h><i>1.0</i><j>true</j><k>" + TestUUIDs.TEST_UUIDS[0].toString() + "</k>foobar</k>"); } @Test public void testObjectWithNumberAttributes() throws Exception { restWriter .object("k") .attribute("a", (byte)42) .attribute("b", (short)-1) .attribute("c", (int)4711) .attribute("d", 4711L) .attribute("e", (float)1.0) .attribute("f", 1.0d) .attribute("g", new BigInteger("4711")) .attribute("h", new BigDecimal(1.0d)) .attribute("i", 1.0) .end() .flush(); assertEquals("<k a=\"42\" b=\"-1\" c=\"4711\" d=\"4711\" e=\"1.0\" f=\"1.0\" g=\"4711\" h=\"1\" i=\"1.0\"/>"); } public void testUnnamedObjectWithValue() throws Exception { restWriter .object() .value("x") .end() .flush(); assertEquals("<value>x</value>"); } @Test(expected=IllegalStateException.class) public void testObjectWithSecondValue() throws Exception { restWriter .object() .value("x") .value("y"); } @Test(expected=IllegalStateException.class) public void testNamedObjectWithSecondValue() throws Exception { restWriter .object("k") .value("x") .value("y"); } @Test public void testUnnamedObjectWithAttributes() throws Exception { restWriter .object() .attribute("a", "b") .attribute("x", "y") .end() .flush(); assertEquals("<a>b</a><x>y</x>"); } @Test(expected=IllegalStateException.class) public void testUnnamedObjectWithAttributeFollowingValue() throws Exception { restWriter .object() .value("foobar") .attribute("a", "b"); } @Test(expected=IllegalStateException.class) public void testObjectWithAttributeFollowingValue() throws Exception { restWriter .object("k") .value("foobar") .attribute("a", "b"); } @Test(expected=IllegalStateException.class) public void testObjectFollowingValue() throws Exception { restWriter .object() .value("x") .object(); } @Test(expected=IllegalStateException.class) public void testArrayFollowingValue() throws Exception { restWriter .object() .value("x") .array(); } @Test(expected=IllegalStateException.class) public void testItemFollowingValue() throws Exception { restWriter .object() .value("x") .item(); } @Test public void testObjectWithLinks() throws Exception { restWriter .object() .link("a", "b") .link("c", "d") .end() .flush(); assertEquals("<link rel=\"a\" href=\"b\"/><link rel=\"c\" href=\"d\"/>"); } @Test public void testArrayWithLinks() throws Exception { restWriter .array() .link("a", "b") .link("c", "d") .end() .flush(); assertEquals("<link rel=\"a\" href=\"b\"/><link rel=\"c\" href=\"d\"/>"); } @Test public void testLinks() throws Exception { restWriter .links() .link("a", "b") .link("c", "d") .link("e", "1", "2") .link("f", restWriter.hrefOf("1", "2")) .set(RestWriter.RELATIVE_LINKS) .link("g", "1", "2") .link("h", restWriter.hrefOf("1", "2")) .end() .flush(); assertEquals("<link rel=\"a\" href=\"b\"/><link rel=\"c\" href=\"d\"/>" + "<link rel=\"e\" href=\"http://example.org/1/2\"/>" + "<link rel=\"f\" href=\"http://example.org/1/2\"/>" + "<link rel=\"g\" href=\"1/2\"/>" + "<link rel=\"h\" href=\"1/2\"/>"); } @Test public void testTimestamp() throws Exception { long now = System.currentTimeMillis(); String timestamp = FormatUtils.formatUTC(now); restWriter .timestamp("timestamp", now) .flush(); assertEquals("<timestamp millis=\"" + now + "\">" + timestamp + "</timestamp>"); } @Test public void testArrayWithItemKeyInnerLinks() throws Exception { restWriter .array("a") .link("a", "b") .link("c", "d") .end() .flush(); assertEquals("<link rel=\"a\" href=\"b\"/><link rel=\"c\" href=\"d\"/>"); } @Test public void testNamedArrayWithLinks() throws Exception { restWriter .key("k").array() .link("a", "b") .link("c", "d") .end() .flush(); assertEquals("<k><link rel=\"a\" href=\"b\"/><link rel=\"c\" href=\"d\"/></k>"); } @Test public void testObjectWithInnerArray() throws Exception { restWriter .key("outter").object() .key("inner").array() .value("x") .value(4711) .value(1.0) .end() .end() .flush(); assertEquals("<outter><inner><item>x</item><item>4711</item><item>1.0</item></inner></outter>"); } @Test public void testObjectWithInnerArrayWithNamedItems() throws Exception { restWriter .key("outter").object() .key("inner").array("e") .value("x") .value(4711) .value(1.0) .end() .end() .flush(); assertEquals("<outter><inner><e>x</e><e>4711</e><e>1.0</e></inner></outter>"); } @Test public void testObjectWithAnonymousInnerArray() throws Exception { restWriter .key("outter").object() .array() .value("x") .value(4711) .value(1.0) .end() .end() .flush(); assertEquals("<outter><item>x</item><item>4711</item><item>1.0</item></outter>"); } @Test(expected=IllegalStateException.class) public void testValueWithNullKey() throws Exception { restWriter .object("k") .pair(null, "x"); } @Test public void testSurpressNullValue() throws Exception { restWriter .object("k") .pair("x", (String)null) .end() .flush(); assertEquals("<k></k>"); } @Test public void testValueWithNullValue() throws Exception { restWriter .set(RestWriter.ALL_MEMBERS) .object("k") .pair("x", (String)null) .end() .flush(); assertEquals("<k><x/></k>"); } @Test public void testSurpressBlankValue() throws Exception { restWriter .object("k") .pair("x", "") .end() .flush(); assertEquals("<k></k>"); } @Test public void testValueWithBlankValue() throws Exception { restWriter .set(RestWriter.ALL_MEMBERS) .object("k") .pair("x", "") .end() .flush(); assertEquals("<k><x></x></k>"); } @Test(expected=IllegalStateException.class) public void testObjectMissingEnd() throws Exception { restWriter .object("k") .pair("x", "y") .flush(); } @Test(expected=IllegalStateException.class) public void testArrayMissingEnd() throws Exception { restWriter .array("k", "e") .value("x") .flush(); } @Test(expected=IllegalStateException.class) public void testItemMissingEnd() throws Exception { restWriter .array("k") .item().value("x") .end() .flush(); } @Test(expected=IllegalStateException.class) public void testInvalidObjectFollowingFinalState() throws Exception { restWriter .object("k") .end() .object("k"); } @Test(expected=IllegalStateException.class) public void testInvalidArrayFollowingFinalState() throws Exception { restWriter .object("k") .end() .array("k", "e"); } @Test(expected=IllegalStateException.class) public void testInvalidNamedValueFollowingFinalState() throws Exception { restWriter .object("k") .end() .pair("x", "y"); } @Test(expected=IllegalStateException.class) public void testInvalidValueFollowingFinalState() throws Exception { restWriter .object("k") .end() .value("x"); } @Test(expected=IllegalStateException.class) public void testInvalidAttributeFollowingFinalState() throws Exception { restWriter .object("k") .end() .attribute("x", "y"); } @Test(expected=IllegalStateException.class) public void testRedundantEnd() throws Exception { restWriter .object("k") .end() .end(); } @Test(expected=IllegalStateException.class) public void testEndInInitialState() throws Exception { restWriter .end(); } @Test(expected=IllegalStateException.class) public void testUnnamedValueInitialState() throws Exception { restWriter .value("x"); } @Test(expected=IllegalStateException.class) public void testNamedValueInitialState() throws Exception { restWriter .pair("x", "y"); } @Test public void testComplexArray() throws Exception { restWriter .array("links", "link") .item() .object() .attribute("rel", "browse") .attribute("href", "A") .value("foobar") .end() .end() .key("inner") .array() .item().value("a").end() .key("ignore").value(4711) .value(1.0d) .item("e").value("b").end() .object().pair("foo", "bar").end() .value("hugo") .end() .object("ooo") .namespace("xmlns:xsi", "something") .attribute("a", "b") .attribute("c", "d") .pair("x", "y") .end() .end() .flush(); assertEquals("<links>" + "<link rel=\"browse\" href=\"A\">foobar</link>" + "<inner><item>a</item><item>4711</item><item>1.0</item><e>b</e>" + "<e><foo>bar</foo></e><e>hugo</e></inner>" + "<ooo xmlns:xsi=\"something\" a=\"b\" c=\"d\"><x>y</x></ooo>" + "</links>"); } private void assertEquals(String expected) throws Exception { Assert.assertEquals(XML_HEADER + expected, writer.toString()); } }