/*** * Copyright (c) 2009 Caelum - www.caelum.com.br/opensource All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package br.com.caelum.vraptor.serialization.xstream; import static br.com.caelum.vraptor.serialization.XMLSerialization.ENVIRONMENT_INDENTED_KEY; import static br.com.caelum.vraptor.serialization.xstream.XStreamBuilderImpl.cleanInstance; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; import javax.servlet.http.HttpServletResponse; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import br.com.caelum.vraptor.environment.Environment; import com.google.common.collect.Lists; import com.thoughtworks.xstream.annotations.XStreamAlias; public class XStreamXMLSerializationTest { @Rule public ExpectedException exception = ExpectedException.none(); protected XStreamXMLSerialization serialization; protected ByteArrayOutputStream stream; protected Environment environment; @Before public void setup() throws Exception { stream = new ByteArrayOutputStream(); environment = mock(Environment.class); HttpServletResponse response = mock(HttpServletResponse.class); when(response.getWriter()).thenReturn(new PrintWriter(stream)); serialization = new XStreamXMLSerialization(response, cleanInstance(new CalendarConverter()), environment); } public static class Address { String street; public Address(String street) { this.street = street; } } public static class Client { String name; Address address; Calendar creation; public Client(String name) { this.name = name; } public Client(String name, Address address) { this.name = name; this.address = address; } public Client(String name, Address address, Calendar creation) { this.name = name; this.address = address; this.creation = creation; } } public static class Item { String name; double price; public Item(String name, double price) { this.name = name; this.price = price; } } public static class Order { Client client; double price; String comments; List<Item> items; public Order(Client client, double price, String comments, Item... items) { this.client = client; this.price = price; this.comments = comments; this.items = Lists.newArrayList(items); } public String nice() { return "nice output"; } } public static class Properties { Map<String, String> map; public Properties(String key, String value) { map = new HashMap<>(Collections.singletonMap(key, value)); } } public static class AdvancedOrder extends Order{ @SuppressWarnings("unused") private final String notes; public AdvancedOrder(Client client, double price, String comments, String notes) { super(client, price, comments); this.notes = notes; } } public static class GenericWrapper<T> { Collection<T> entityList; Integer total; public GenericWrapper(Collection<T> entityList, Integer total) { this.entityList = entityList; this.total = total; } } @Test public void shouldSerializeGenericClass() { String expectedResult = "<genericWrapper><entityList class=\"list\"><client><name>washington botelho</name></client><client><name>washington botelho</name></client></entityList><total>2</total></genericWrapper>"; Collection<Client> entityList = new ArrayList<>(); entityList.add(new Client("washington botelho")); entityList.add(new Client("washington botelho")); GenericWrapper<Client> wrapper = new GenericWrapper<>(entityList, entityList.size()); serialization.from(wrapper).include("entityList").serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldSerializeCalendarAsISO8601() { String expectedResult = "<client><name>Otto</name><creation>2013-09-12T22:09:13-03:00</creation></client>"; Calendar calendar = Calendar.getInstance(); calendar.set(2013, 8, 12, 22, 9, 13); calendar.set(Calendar.MILLISECOND, 0); calendar.setTimeZone(TimeZone.getTimeZone("America/Sao_Paulo")); Client otto = new Client("Otto", null, calendar); serialization.from(otto).serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldSerializeMaps() { String expectedResult = "<properties><map><entry><string>test</string><string>true</string></entry></map></properties>"; serialization.from(new Properties("test", "true")).include("map").serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldSerializeAllBasicFields() { String expectedResult = "<order><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(order).serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldSerializeAllBasicFieldsIndented() { when(environment.get(anyString(), anyString())).thenReturn("true"); String expectedResult = "<order>\n" + " <price>15.0</price>\n" + " <comments>pack it nicely, please</comments>\n" + "</order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.indented().from(order).serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldIndentedWhenEnvironmentReturnsTrue() { when(environment.supports(ENVIRONMENT_INDENTED_KEY)).thenReturn(true); serialization.init(); String expectedResult = "<order>\n <price>15.0</price>\n <comments>pack it nicely, please</comments>\n</order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(order).serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldNotIndentedWhenEnvironmentReturnsFalse() { when(environment.supports(anyString())).thenReturn(false); serialization.init(); String expectedResult = "<order><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(order).serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldUseAlias() { String expectedResult = "<customOrder><price>15.0</price><comments>pack it nicely, please</comments></customOrder>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(order, "customOrder").serialize(); assertThat(result(), is(equalTo(expectedResult))); } public static enum Type { basic, advanced } class BasicOrder extends Order { public BasicOrder(Client client, double price, String comments, Type type) { super(client, price, comments); this.type = type; } @SuppressWarnings("unused") private final Type type; } @Test public void shouldSerializeEnumFields() { Order order = new BasicOrder(new Client("guilherme silveira"), 15.0, "pack it nicely, please", Type.basic); serialization.from(order).serialize(); String result = result(); assertThat(result, containsString("<type>basic</type>")); } @Test public void shouldSerializeCollection() { String expectedResult = "<order><price>15.0</price><comments>pack it nicely, please</comments></order>"; expectedResult += expectedResult; expectedResult = "<list>" + expectedResult + "</list>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(Arrays.asList(order, order)).serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldSerializeCollectionWithPrefixTag() { String expectedResult = "<order><price>15.0</price><comments>pack it nicely, please</comments></order>"; expectedResult += expectedResult; expectedResult = "<orders>" + expectedResult + "</orders>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(Arrays.asList(order, order), "orders").serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldIncludeFieldsFromACollection() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(Arrays.asList(order, order), "orders").include("items").serialize(); assertThat(result(), containsString("<items>")); assertThat(result(), containsString("<name>name</name>")); assertThat(result(), containsString("<price>12.99</price>")); assertThat(result(), containsString("</items>")); } @Test public void shouldWorkWithEmptyCollections() { serialization.from(new ArrayList<Order>(), "orders").serialize(); assertThat(result(), containsString("<orders/>")); } @Test public void shouldIncludeAllFieldsWhenRecursive() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).recursive().serialize(); assertThat(result(), containsString("<items>")); assertThat(result(), containsString("<name>name</name>")); assertThat(result(), containsString("<price>12.99</price>")); } @Test public void shouldExcludeFieldsFromACollection() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(Arrays.asList(order, order), "orders").exclude("price").serialize(); assertThat(result(), not(containsString("<price>"))); } @Test public void shouldThrowAnExceptionWhenYouIncludeANonExistantField() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Field path 'wrongFieldName' doesn't exists in class"); Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("wrongFieldName").serialize(); } @Test public void shouldThrowAnExceptionWhenYouIncludeANonExistantFieldInsideOther() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Field path 'wrongFieldName.client' doesn't exists in class"); Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("wrongFieldName.client").serialize(); } @Test public void shouldThrowAnExceptionWhenYouIncludeANonExistantFieldInsideOtherNonExistantField() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Field path 'wrongFieldName.another' doesn't exists in class"); Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("wrongFieldName.another").serialize(); assertThat(result(), not(containsString("<order><price>15.0</price><comments>pack it nicely, please</comments></order>"))); } @Test public void shouldIgnoreWhenIncludeANonExistantField() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("?wrongFieldName").serialize(); assertThat(result(), containsString("<order><price>15.0</price><comments>pack it nicely, please</comments></order>")); } @Test public void shouldIgnoreWhenYouIncludeAOptionalNonExistantFieldInsideOther() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("?wrongFieldName.another").serialize(); assertThat(result(), containsString("<order><price>15.0</price><comments>pack it nicely, please</comments></order>")); } @Test public void shouldIgnoreWhenYouIncludeANonExistantFieldInsideOther() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("?wrongFieldName.?another").serialize(); assertThat(result(), containsString("<order><price>15.0</price><comments>pack it nicely, please</comments></order>")); } @Test public void shouldIncludeWhenYouIncludeAOptionsExistantFieldInsideOther() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("?client").serialize(); assertThat(result(), containsString("<client>")); } @Test public void shouldIgnoreWhenYouIncludeANonExistantFieldInsideOtherNonExistantField() { Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("name", 12.99)); serialization.from(order).include("?wrongFieldName.?another").serialize(); assertThat(result(), containsString("<order><price>15.0</price><comments>pack it nicely, please</comments></order>")); } @Test public void shouldSerializeParentFields() { Order order = new AdvancedOrder(null, 15.0, "pack it nicely, please", "complex package"); serialization.from(order).serialize(); assertThat(result(), containsString("<notes>complex package</notes>")); } @Test public void shouldOptionallyExcludeFields() { String expectedResult = "<order><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(order).exclude("price").serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldOptionallyIncludeFieldAndNotItsNonPrimitiveFields() { // String expectedResult = "<order><client><name>guilherme silveira</name>\n </client><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira", new Address("R. Vergueiro")), 15.0, "pack it nicely, please"); serialization.from(order).include("client").serialize(); assertThat(result(), containsString("<name>guilherme silveira</name>")); assertThat(result(), not(containsString("R. Vergueiro"))); } @Test public void shouldOptionallyIncludeChildField() { // String expectedResult = "<order><client><name>guilherme silveira</name>\n </client><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira", new Address("R. Vergueiro")), 15.0, "pack it nicely, please"); serialization.from(order).include("client", "client.address").serialize(); assertThat(result(), containsString("<street>R. Vergueiro</street>")); } @Test public void shouldOptionallyExcludeChildField() { // String expectedResult = "<order><client></client><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please"); serialization.from(order).include("client").exclude("client.name").serialize(); assertThat(result(), containsString("<client/>")); assertThat(result(), not(containsString("<name>guilherme silveira</name>"))); } @Test public void shouldOptionallyIncludeListChildFields() { // String expectedResult = "<order><client></client><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("any item", 12.99)); serialization.from(order).include("items").serialize(); assertThat(result(), containsString("<items>")); assertThat(result(), containsString("<name>any item</name>")); assertThat(result(), containsString("<price>12.99</price>")); assertThat(result(), containsString("</items>")); } @Test public void shouldOptionallyExcludeFieldsFromIncludedListChildFields() { // String expectedResult = "<order><client></client><price>15.0</price><comments>pack it nicely, please</comments></order>"; Order order = new Order(new Client("guilherme silveira"), 15.0, "pack it nicely, please", new Item("any item", 12.99)); serialization.from(order).include("items").exclude("items.price").serialize(); assertThat(result(), containsString("<items>")); assertThat(result(), containsString("<name>any item</name>")); assertThat(result(), not(containsString("12.99"))); assertThat(result(), containsString("</items>")); } @Test public void shouldExcludeAllPrimitiveFields() { String expectedResult = "<order/>"; Order order = new Order(new Client("nykolas lima"), 15.0, "gift bags, please"); serialization.from(order).excludeAll().serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldExcludeAllPrimitiveParentFields() { String expectedResult = "<advancedOrder/>"; Order order = new AdvancedOrder(null, 15.0, "pack it nicely, please", "complex package"); serialization.from(order).excludeAll().serialize(); assertThat(result(), is(equalTo(expectedResult))); } @Test public void shouldExcludeAllThanIncludeAndSerialize() { Order order = new Order(new Client("nykolas lima"), 15.0, "gift bags, please"); serialization.from(order).excludeAll().include("price").serialize(); assertThat(result(), containsString("<order>")); assertThat(result(), containsString("<price>")); assertThat(result(), containsString("15.0")); assertThat(result(), containsString("</price>")); assertThat(result(), containsString("</order>")); } static class WithAlias { @XStreamAlias("def") private String abc; } static class WithAliasedAttribute { @SuppressWarnings("unused") private WithAlias aliased; } @Test public void shouldAutomaticallyReadXStreamAnnotations() { WithAlias alias = new WithAlias(); alias.abc = "Duh!"; serialization.from(alias).serialize(); assertThat(result(), is("<withAlias><def>Duh!</def></withAlias>")); } @Test public void shouldAutomaticallyReadXStreamAnnotationsForIncludedAttributes() { WithAlias alias = new WithAlias(); alias.abc = "Duh!"; WithAliasedAttribute attribute = new WithAliasedAttribute(); attribute.aliased = alias; serialization.from(attribute).include("aliased").serialize(); assertThat(result(), is("<withAliasedAttribute><aliased><def>Duh!</def></aliased></withAliasedAttribute>")); } private String result() { return new String(stream.toByteArray()); } /** * @bug #400 */ class A { C field1 = new C(); } class B extends A { C field2 = new C(); } class C { } @Test public void shouldBeAbleToIncludeSubclassesFields() throws Exception { serialization.from(new B()).include("field2").serialize(); assertThat(result(), is("<b><field2/></b>")); } }