001: /*
002: * Copyright (C) 2004, 2005 Joe Walnes.
003: * Copyright (C) 2006, 2007 XStream Committers.
004: * All rights reserved.
005: *
006: * The software in this package is published under the terms of the BSD
007: * style license a copy of which has been included with this distribution in
008: * the LICENSE.txt file.
009: *
010: * Created on 14. August 2004 by Joe Walnes
011: */
012: package com.thoughtworks.acceptance;
013:
014: import com.thoughtworks.acceptance.objects.SampleLists;
015: import com.thoughtworks.acceptance.objects.StandardObject;
016: import com.thoughtworks.xstream.InitializationException;
017:
018: import java.util.ArrayList;
019: import java.util.Collections;
020: import java.util.HashSet;
021: import java.util.LinkedList;
022: import java.util.List;
023: import java.util.Set;
024: import java.util.TreeSet;
025:
026: public class ImplicitCollectionTest extends AbstractAcceptanceTest {
027:
028: public static class Farm extends StandardObject {
029: int size;
030: List animals = new ArrayList();
031:
032: public Farm(int size) {
033: this .size = size;
034: }
035:
036: public void add(Animal animal) {
037: animals.add(animal);
038: }
039: }
040:
041: public static class Animal extends StandardObject implements
042: Comparable {
043: String name;
044:
045: public Animal(String name) {
046: this .name = name;
047: }
048:
049: public int compareTo(Object o) {
050: return name.compareTo(((Animal) o).name);
051: }
052: }
053:
054: protected void setUp() throws Exception {
055: super .setUp();
056: xstream.alias("zoo", Zoo.class);
057: xstream.alias("farm", Farm.class);
058: xstream.alias("animal", Animal.class);
059: xstream.alias("room", Room.class);
060: xstream.alias("house", House.class);
061: xstream.alias("person", Person.class);
062: xstream.alias("sample", SampleLists.class);
063: }
064:
065: public void testWithout() {
066: Farm farm = new Farm(100);
067: farm.add(new Animal("Cow"));
068: farm.add(new Animal("Sheep"));
069:
070: String expected = "" + "<farm>\n" + " <size>100</size>\n"
071: + " <animals>\n" + " <animal>\n"
072: + " <name>Cow</name>\n" + " </animal>\n"
073: + " <animal>\n" + " <name>Sheep</name>\n"
074: + " </animal>\n" + " </animals>\n" + "</farm>";
075:
076: assertBothWays(farm, expected);
077: }
078:
079: public void testWithList() {
080: Farm farm = new Farm(100);
081: farm.add(new Animal("Cow"));
082: farm.add(new Animal("Sheep"));
083:
084: String expected = "" + "<farm>\n" + " <size>100</size>\n"
085: + " <animal>\n" + " <name>Cow</name>\n"
086: + " </animal>\n" + " <animal>\n"
087: + " <name>Sheep</name>\n" + " </animal>\n"
088: + "</farm>";
089:
090: xstream.addImplicitCollection(Farm.class, "animals");
091: assertBothWays(farm, expected);
092: }
093:
094: public static class MegaFarm extends Farm {
095: public MegaFarm(int size) {
096: super (size);
097: }
098: }
099:
100: public void testInheritsImplicitCollectionFromSuperclass() {
101: xstream.alias("MEGA-farm", MegaFarm.class);
102:
103: Farm farm = new MegaFarm(100); // subclass
104: farm.add(new Animal("Cow"));
105: farm.add(new Animal("Sheep"));
106:
107: String expected = "" + "<MEGA-farm>\n" + " <size>100</size>\n"
108: + " <animal>\n" + " <name>Cow</name>\n"
109: + " </animal>\n" + " <animal>\n"
110: + " <name>Sheep</name>\n" + " </animal>\n"
111: + "</MEGA-farm>";
112:
113: xstream.addImplicitCollection(Farm.class, "animals");
114: assertBothWays(farm, expected);
115: }
116:
117: public void testAllowsSubclassToOverrideImplicitCollectionInSuperclass() {
118: xstream.alias("MEGA-farm", MegaFarm.class);
119:
120: Farm farm = new MegaFarm(100); // subclass
121: farm.add(new Animal("Cow"));
122: farm.add(new Animal("Sheep"));
123:
124: String expected = "" + "<MEGA-farm>\n" + " <size>100</size>\n"
125: + " <animal>\n" + " <name>Cow</name>\n"
126: + " </animal>\n" + " <animal>\n"
127: + " <name>Sheep</name>\n" + " </animal>\n"
128: + "</MEGA-farm>";
129:
130: xstream.addImplicitCollection(MegaFarm.class, "animals");
131: assertBothWays(farm, expected);
132: }
133:
134: public static class House extends StandardObject {
135: private List rooms = new ArrayList();
136: private List people = new ArrayList();
137:
138: public void add(Room room) {
139: rooms.add(room);
140: }
141:
142: public void add(Person person) {
143: people.add(person);
144: }
145:
146: public List getPeople() {
147: return Collections.unmodifiableList(people);
148: }
149:
150: public List getRooms() {
151: return Collections.unmodifiableList(rooms);
152: }
153: }
154:
155: public static class Room extends StandardObject {
156: private String name;
157:
158: public Room(String name) {
159: this .name = name;
160: }
161: }
162:
163: public static class Person extends StandardObject {
164: private String name;
165: private LinkedList emailAddresses = new LinkedList();
166:
167: public Person(String name) {
168: this .name = name;
169: }
170:
171: public void addEmailAddress(String email) {
172: emailAddresses.add(email);
173: }
174: }
175:
176: public void testDefaultCollectionBasedOnType() {
177: House house = new House();
178: house.add(new Room("kitchen"));
179: house.add(new Room("bathroom"));
180: Person joe = new Person("joe");
181: joe.addEmailAddress("joe@house.org");
182: joe.addEmailAddress("joe.farmer@house.org");
183: house.add(joe);
184: Person jaimie = new Person("jaimie");
185: jaimie.addEmailAddress("jaimie@house.org");
186: jaimie.addEmailAddress("jaimie.farmer@house.org");
187: jaimie.addEmailAddress("jaimie.ann.farmer@house.org");
188: house.add(jaimie);
189:
190: String expected = "" + "<house>\n" + " <room>\n"
191: + " <name>kitchen</name>\n" + " </room>\n"
192: + " <room>\n" + " <name>bathroom</name>\n"
193: + " </room>\n" + " <person>\n"
194: + " <name>joe</name>\n"
195: + " <email>joe@house.org</email>\n"
196: + " <email>joe.farmer@house.org</email>\n"
197: + " </person>\n" + " <person>\n"
198: + " <name>jaimie</name>\n"
199: + " <email>jaimie@house.org</email>\n"
200: + " <email>jaimie.farmer@house.org</email>\n"
201: + " <email>jaimie.ann.farmer@house.org</email>\n"
202: + " </person>\n" + "</house>";
203:
204: xstream.addImplicitCollection(House.class, "rooms", Room.class);
205: xstream.addImplicitCollection(House.class, "people",
206: Person.class);
207: xstream.addImplicitCollection(Person.class, "emailAddresses",
208: "email", String.class);
209:
210: House serializedHouse = (House) assertBothWays(house, expected);
211: assertEquals(house.getPeople(), serializedHouse.getPeople());
212: assertEquals(house.getRooms(), serializedHouse.getRooms());
213: }
214:
215: public static class Zoo extends StandardObject {
216: private Set animals = new HashSet();
217:
218: public void add(Animal animal) {
219: animals.add(animal);
220: }
221: }
222:
223: public void testWithSet() {
224: Zoo zoo = new Zoo();
225: zoo.add(new Animal("Lion"));
226: zoo.add(new Animal("Ape"));
227:
228: String expected = "" + "<zoo>\n" + " <animal>\n"
229: + " <name>Lion</name>\n" + " </animal>\n"
230: + " <animal>\n" + " <name>Ape</name>\n"
231: + " </animal>\n" + "</zoo>";
232:
233: xstream.addImplicitCollection(Zoo.class, "animals");
234: assertBothWaysNormalized(zoo, expected, "zoo", "animal", "name");
235: }
236:
237: public void testWithDifferentDefaultImplementation() {
238: String xml = "" + "<zoo>\n" + " <animal>\n"
239: + " <name>Lion</name>\n" + " </animal>\n"
240: + " <animal>\n" + " <name>Ape</name>\n"
241: + " </animal>\n" + "</zoo>";
242:
243: xstream.addImplicitCollection(Zoo.class, "animals");
244: xstream.addDefaultImplementation(TreeSet.class, Set.class);
245: Zoo zoo = (Zoo) xstream.fromXML(xml);
246: assertTrue("Collection was a "
247: + zoo.animals.getClass().getName(),
248: zoo.animals instanceof TreeSet);
249: }
250:
251: public static class Aquarium extends StandardObject {
252: private String name;
253: private List fish = new ArrayList();
254:
255: public Aquarium(String name) {
256: this .name = name;
257: }
258:
259: public void addFish(String fish) {
260: this .fish.add(fish);
261: }
262: }
263:
264: public void testWithExplicitItemNameMatchingTheNameOfTheFieldWithTheCollection() {
265: Aquarium aquarium = new Aquarium("hatchery");
266: aquarium.addFish("salmon");
267: aquarium.addFish("halibut");
268: aquarium.addFish("snapper");
269:
270: String expected = "" + "<aquarium>\n"
271: + " <name>hatchery</name>\n"
272: + " <fish>salmon</fish>\n"
273: + " <fish>halibut</fish>\n"
274: + " <fish>snapper</fish>\n" + "</aquarium>";
275:
276: xstream.alias("aquarium", Aquarium.class);
277: xstream.addImplicitCollection(Aquarium.class, "fish", "fish",
278: String.class);
279:
280: assertBothWays(aquarium, expected);
281: }
282:
283: public void testWithAliasedItemNameMatchingTheAliasedNameOfTheFieldWithTheCollection() {
284: Aquarium aquarium = new Aquarium("hatchery");
285: aquarium.addFish("salmon");
286: aquarium.addFish("halibut");
287: aquarium.addFish("snapper");
288:
289: String expected = "" + "<aquarium>\n"
290: + " <name>hatchery</name>\n"
291: + " <animal>salmon</animal>\n"
292: + " <animal>halibut</animal>\n"
293: + " <animal>snapper</animal>\n" + "</aquarium>";
294:
295: xstream.alias("aquarium", Aquarium.class);
296: xstream.aliasField("animal", Aquarium.class, "fish");
297: xstream.addImplicitCollection(Aquarium.class, "fish", "animal",
298: String.class);
299:
300: assertBothWays(aquarium, expected);
301: }
302:
303: public void testCanBeDeclaredOnlyForMatchingType() {
304: try {
305: xstream.addImplicitCollection(Animal.class, "name");
306: fail("Thrown " + InitializationException.class.getName()
307: + " expected");
308: } catch (final InitializationException e) {
309: assertTrue(e.getMessage().indexOf("declares no collection") >= 0);
310: }
311: }
312: }
|