View Javadoc

1   /**
2    * Copyright (c) 2008-2011, http://www.snakeyaml.org
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.yaml.snakeyaml.recursive;
18  
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.Date;
22  import java.util.HashMap;
23  import java.util.LinkedHashMap;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Map.Entry;
28  import java.util.Set;
29  
30  import junit.framework.TestCase;
31  
32  import org.yaml.snakeyaml.DumperOptions;
33  import org.yaml.snakeyaml.DumperOptions.FlowStyle;
34  import org.yaml.snakeyaml.TypeDescription;
35  import org.yaml.snakeyaml.Util;
36  import org.yaml.snakeyaml.Yaml;
37  import org.yaml.snakeyaml.constructor.Constructor;
38  
39  public class HumanTest extends TestCase {
40  
41      public void testNoChildren() throws IOException {
42          Human father = new Human();
43          father.setName("Father");
44          father.setBirthday(new Date(1000000000));
45          father.setBirthPlace("Leningrad");
46          father.setBankAccountOwner(father);
47          Human mother = new Human();
48          mother.setName("Mother");
49          mother.setBirthday(new Date(100000000000L));
50          mother.setBirthPlace("Saint-Petersburg");
51          father.setPartner(mother);
52          mother.setPartner(father);
53          mother.setBankAccountOwner(father);
54          Yaml yaml = new Yaml();
55          String output = yaml.dump(father);
56          String etalon = Util.getLocalResource("recursive/no-children-1.yaml");
57          assertEquals(etalon, output);
58          //
59          Human father2 = (Human) yaml.load(output);
60          assertNotNull(father2);
61          assertEquals("Father", father2.getName());
62          assertEquals("Mother", father2.getPartner().getName());
63          assertEquals("Father", father2.getBankAccountOwner().getName());
64          assertSame(father2, father2.getBankAccountOwner());
65      }
66  
67      public void testNoChildrenPretty() throws IOException {
68          Human father = new Human();
69          father.setName("Father");
70          father.setBirthday(new Date(1000000000));
71          father.setBirthPlace("Leningrad");
72          father.setBankAccountOwner(father);
73          Human mother = new Human();
74          mother.setName("Mother");
75          mother.setBirthday(new Date(100000000000L));
76          mother.setBirthPlace("Saint-Petersburg");
77          father.setPartner(mother);
78          mother.setPartner(father);
79          mother.setBankAccountOwner(father);
80          DumperOptions options = new DumperOptions();
81          options.setPrettyFlow(true);
82          options.setDefaultFlowStyle(FlowStyle.FLOW);
83          Yaml yaml = new Yaml(options);
84          String output = yaml.dump(father);
85          String etalon = Util.getLocalResource("recursive/no-children-1-pretty.yaml");
86          assertEquals(etalon, output);
87          //
88          Human father2 = (Human) yaml.load(output);
89          assertNotNull(father2);
90          assertEquals("Father", father2.getName());
91          assertEquals("Mother", father2.getPartner().getName());
92          assertEquals("Father", father2.getBankAccountOwner().getName());
93          assertSame(father2, father2.getBankAccountOwner());
94      }
95  
96      public void testChildren() throws IOException {
97          Human father = new Human();
98          father.setName("Father");
99          father.setBirthday(new Date(1000000000));
100         father.setBirthPlace("Leningrad");
101         father.setBankAccountOwner(father);
102         //
103         Human mother = new Human();
104         mother.setName("Mother");
105         mother.setBirthday(new Date(100000000000L));
106         mother.setBirthPlace("Saint-Petersburg");
107         father.setPartner(mother);
108         mother.setPartner(father);
109         mother.setBankAccountOwner(father);
110         //
111         Human son = new Human();
112         son.setName("Son");
113         son.setBirthday(new Date(310000000000L));
114         son.setBirthPlace("Munich");
115         son.setBankAccountOwner(father);
116         son.setFather(father);
117         son.setMother(mother);
118         //
119         Human daughter = new Human();
120         daughter.setName("Daughter");
121         daughter.setBirthday(new Date(420000000000L));
122         daughter.setBirthPlace("New York");
123         daughter.setBankAccountOwner(father);
124         daughter.setFather(father);
125         daughter.setMother(mother);
126         //
127         Set<Human> children = new LinkedHashSet<Human>(2);
128         children.add(son);
129         children.add(daughter);
130         father.setChildren(children);
131         mother.setChildren(children);
132         //
133         Yaml beanDumper = new Yaml();
134         String output = beanDumper.dumpAsMap(son);
135         // System.out.println(output);
136         String etalon = Util.getLocalResource("recursive/with-children.yaml");
137         assertEquals(etalon, output);
138         TypeDescription humanDescription = new TypeDescription(Human.class);
139         humanDescription.putMapPropertyType("children", Human.class, Object.class);
140         Yaml beanLoader = new Yaml(new Constructor(humanDescription));
141         //
142         Human son2 = beanLoader.loadAs(output, Human.class);
143         assertNotNull(son2);
144         assertEquals("Son", son.getName());
145 
146         Human father2 = son2.getFather();
147         assertEquals("Father", father2.getName());
148         assertEquals("Mother", son2.getMother().getName());
149         assertSame(father2, father2.getBankAccountOwner());
150         assertSame(father2.getPartner(), son2.getMother());
151         assertSame(father2, son2.getMother().getPartner());
152 
153         Set<Human> children2 = father2.getChildren();
154         assertEquals(2, children2.size());
155         assertSame(father2.getPartner().getChildren(), children2);
156 
157         for (Object child : children2) {
158             // check if type descriptor was correct
159             assertSame(Human.class, child.getClass());
160         }
161 
162         // check if hashCode is correct
163         validateSet(children2);
164     }
165 
166     public void testChildrenPretty() throws IOException {
167         Human father = new Human();
168         father.setName("Father");
169         father.setBirthday(new Date(1000000000));
170         father.setBirthPlace("Leningrad");
171         father.setBankAccountOwner(father);
172         //
173         Human mother = new Human();
174         mother.setName("Mother");
175         mother.setBirthday(new Date(100000000000L));
176         mother.setBirthPlace("Saint-Petersburg");
177         father.setPartner(mother);
178         mother.setPartner(father);
179         mother.setBankAccountOwner(father);
180         //
181         Human son = new Human();
182         son.setName("Son");
183         son.setBirthday(new Date(310000000000L));
184         son.setBirthPlace("Munich");
185         son.setBankAccountOwner(father);
186         son.setFather(father);
187         son.setMother(mother);
188         //
189         Human daughter = new Human();
190         daughter.setName("Daughter");
191         daughter.setBirthday(new Date(420000000000L));
192         daughter.setBirthPlace("New York");
193         daughter.setBankAccountOwner(father);
194         daughter.setFather(father);
195         daughter.setMother(mother);
196         //
197         Set<Human> children = new LinkedHashSet<Human>(2);
198         children.add(son);
199         children.add(daughter);
200         father.setChildren(children);
201         mother.setChildren(children);
202         //
203         DumperOptions options = new DumperOptions();
204         options.setDefaultFlowStyle(FlowStyle.FLOW);
205         options.setPrettyFlow(true);
206         Yaml beanDumper = new Yaml(options);
207         String output = beanDumper.dump(son);
208         // System.out.println(output);
209         String etalon = Util.getLocalResource("recursive/with-children-pretty.yaml");
210         assertEquals(etalon, output);
211         TypeDescription humanDescription = new TypeDescription(Human.class);
212         humanDescription.putMapPropertyType("children", Human.class, Object.class);
213         Yaml beanLoader = new Yaml(new Constructor(humanDescription));
214         //
215         Human son2 = beanLoader.loadAs(output, Human.class);
216         assertNotNull(son2);
217         assertEquals("Son", son.getName());
218 
219         Human father2 = son2.getFather();
220         assertEquals("Father", father2.getName());
221         assertEquals("Mother", son2.getMother().getName());
222         assertSame(father2, father2.getBankAccountOwner());
223         assertSame(father2.getPartner(), son2.getMother());
224         assertSame(father2, son2.getMother().getPartner());
225 
226         Set<Human> children2 = father2.getChildren();
227         assertEquals(2, children2.size());
228         assertSame(father2.getPartner().getChildren(), children2);
229 
230         for (Object child : children2) {
231             // check if type descriptor was correct
232             assertSame(Human.class, child.getClass());
233         }
234 
235         // check if hashCode is correct
236         validateSet(children2);
237     }
238 
239     public void testChildren2() throws IOException {
240         Human2 father = new Human2();
241         father.setName("Father");
242         father.setBirthday(new Date(1000000000));
243         father.setBirthPlace("Leningrad");
244         father.setBankAccountOwner(father);
245         //
246         Human2 mother = new Human2();
247         mother.setName("Mother");
248         mother.setBirthday(new Date(100000000000L));
249         mother.setBirthPlace("Saint-Petersburg");
250         father.setPartner(mother);
251         mother.setPartner(father);
252         mother.setBankAccountOwner(father);
253         //
254         Human2 son = new Human2();
255         son.setName("Son");
256         son.setBirthday(new Date(310000000000L));
257         son.setBirthPlace("Munich");
258         son.setBankAccountOwner(father);
259         son.setFather(father);
260         son.setMother(mother);
261         //
262         Human2 daughter = new Human2();
263         daughter.setName("Daughter");
264         daughter.setBirthday(new Date(420000000000L));
265         daughter.setBirthPlace("New York");
266         daughter.setBankAccountOwner(father);
267         daughter.setFather(father);
268         daughter.setMother(mother);
269         //
270         HashMap<Human2, String> children = new LinkedHashMap<Human2, String>(2);
271         children.put(son, "son");
272         children.put(daughter, "daughter");
273         father.setChildren(children);
274         mother.setChildren(children);
275         //
276 
277         Constructor constructor = new Constructor(Human2.class);
278         TypeDescription humanDescription = new TypeDescription(Human2.class);
279         humanDescription.putMapPropertyType("children", Human2.class, String.class);
280         constructor.addTypeDescription(humanDescription);
281 
282         Yaml yaml = new Yaml(constructor);
283         String output = yaml.dump(son);
284         // System.out.println(output);
285         String etalon = Util.getLocalResource("recursive/with-children-2.yaml");
286         assertEquals(etalon, output);
287         //
288         Human2 son2 = (Human2) yaml.load(output);
289         assertNotNull(son2);
290         assertEquals("Son", son.getName());
291 
292         Human2 father2 = son2.getFather();
293         assertEquals("Father", father2.getName());
294         assertEquals("Mother", son2.getMother().getName());
295         assertSame(father2, father2.getBankAccountOwner());
296         assertSame(father2.getPartner(), son2.getMother());
297         assertSame(father2, son2.getMother().getPartner());
298 
299         Map<Human2, String> children2 = father2.getChildren();
300         assertEquals(2, children2.size());
301         assertSame(father2.getPartner().getChildren(), children2);
302 
303         validateMapKeys(children2);
304     }
305 
306     public void testChildren3() throws IOException {
307         Human3 father = new Human3();
308         father.setName("Father");
309         father.setBirthday(new Date(1000000000));
310         father.setBirthPlace("Leningrad");
311         father.setBankAccountOwner(father);
312         //
313         Human3 mother = new Human3();
314         mother.setName("Mother");
315         mother.setBirthday(new Date(100000000000L));
316         mother.setBirthPlace("Saint-Petersburg");
317         father.setPartner(mother);
318         mother.setPartner(father);
319         mother.setBankAccountOwner(father);
320         //
321         Human3 son = new Human3();
322         son.setName("Son");
323         son.setBirthday(new Date(310000000000L));
324         son.setBirthPlace("Munich");
325         son.setBankAccountOwner(father);
326         son.setFather(father);
327         son.setMother(mother);
328         //
329         Human3 daughter = new Human3();
330         daughter.setName("Daughter");
331         daughter.setBirthday(new Date(420000000000L));
332         daughter.setBirthPlace("New York");
333         daughter.setBankAccountOwner(father);
334         daughter.setFather(father);
335         daughter.setMother(mother);
336         //
337         ArrayList<Human3> children = new ArrayList<Human3>();
338         children.add(son);
339         children.add(daughter);
340         father.setChildren(children);
341         mother.setChildren(children);
342         //
343 
344         Constructor constructor = new Constructor(Human3.class);
345         TypeDescription Human3Description = new TypeDescription(Human3.class);
346         Human3Description.putListPropertyType("children", Human3.class);
347         constructor.addTypeDescription(Human3Description);
348 
349         Yaml yaml = new Yaml(constructor);
350         String output = yaml.dump(son);
351         // System.out.println(output);
352         String etalon = Util.getLocalResource("recursive/with-children-3.yaml");
353         assertEquals(etalon, output);
354         //
355         Human3 son2 = (Human3) yaml.load(output);
356         assertNotNull(son2);
357         assertEquals("Son", son.getName());
358 
359         Human3 father2 = son2.getFather();
360         assertEquals("Father", father2.getName());
361         assertEquals("Mother", son2.getMother().getName());
362         assertSame(father2, father2.getBankAccountOwner());
363         assertSame(father2.getPartner(), son2.getMother());
364         assertSame(father2, son2.getMother().getPartner());
365 
366         List<Human3> children2 = father2.getChildren();
367         assertEquals(2, children2.size());
368         assertSame(father2.getPartner().getChildren(), children2);
369 
370         for (Object child : children2) {
371             // check if type descriptor was correct
372             assertSame(Human3.class, child.getClass());
373         }
374     }
375 
376     /*
377      * Loads same structure as created in testChildren. But root object is set
378      * of children
379      */
380     @SuppressWarnings("unchecked")
381     public void testChildrenSetAsRoot() throws IOException {
382         String etalon = Util.getLocalResource("recursive/with-children-as-set.yaml");
383 
384         Constructor constructor = new Constructor();
385         TypeDescription humanDescription = new TypeDescription(Human.class);
386         humanDescription.putMapPropertyType("children", Human.class, Object.class);
387         constructor.addTypeDescription(humanDescription);
388 
389         Yaml yaml = new Yaml(constructor);
390         Set<Human> children2 = (Set<Human>) yaml.load(etalon);
391         assertNotNull(children2);
392         assertEquals(2, children2.size());
393 
394         Human firstChild = children2.iterator().next();
395 
396         Human father2 = firstChild.getFather();
397         assertEquals("Father", father2.getName());
398         assertEquals("Mother", firstChild.getMother().getName());
399         assertSame(father2, father2.getBankAccountOwner());
400         assertSame(father2.getPartner(), firstChild.getMother());
401         assertSame(father2, firstChild.getMother().getPartner());
402 
403         assertSame(father2.getPartner().getChildren(), children2);
404 
405         for (Object child : children2) {
406             // check if type descriptor was correct
407             assertSame(Human.class, child.getClass());
408         }
409 
410         validateSet(children2);
411     }
412 
413     /*
414      * Loads same structure as created in testChildren. But root object is map
415      * of children
416      */
417     @SuppressWarnings("unchecked")
418     public void testChildrenMapAsRoot() throws IOException {
419         String etalon = Util.getLocalResource("recursive/with-children-as-map.yaml");
420 
421         Constructor constructor = new Constructor();
422         TypeDescription Human2Description = new TypeDescription(Human2.class);
423         Human2Description.putMapPropertyType("children", Human2.class, String.class);
424         constructor.addTypeDescription(Human2Description);
425 
426         Yaml yaml = new Yaml(constructor);
427         Map<Human2, String> children2 = (Map<Human2, String>) yaml.load(etalon);
428         assertNotNull(children2);
429         assertEquals(2, children2.size());
430 
431         Entry<Human2, String> firstEntry = children2.entrySet().iterator().next();
432         Human2 firstChild = firstEntry.getKey();
433 
434         Human2 father2 = firstChild.getFather();
435         assertEquals("Father", father2.getName());
436         assertEquals("Mother", firstChild.getMother().getName());
437         assertSame(father2, father2.getBankAccountOwner());
438         assertSame(father2.getPartner(), firstChild.getMother());
439         assertSame(father2, firstChild.getMother().getPartner());
440 
441         assertSame(father2.getPartner().getChildren(), children2);
442 
443         validateMapKeys(children2);
444     }
445 
446     /*
447      * Loads same structure as created in testChildren. But root object is list
448      * of children
449      */
450     @SuppressWarnings("unchecked")
451     public void testChildrenListRoot() throws IOException {
452         Human3 father = new Human3();
453         father.setName("Father");
454         father.setBirthday(new Date(1000000000));
455         father.setBirthPlace("Leningrad");
456         father.setBankAccountOwner(father);
457         //
458         Human3 mother = new Human3();
459         mother.setName("Mother");
460         mother.setBirthday(new Date(100000000000L));
461         mother.setBirthPlace("Saint-Petersburg");
462         father.setPartner(mother);
463         mother.setPartner(father);
464         mother.setBankAccountOwner(father);
465         //
466         Human3 son = new Human3();
467         son.setName("Son");
468         son.setBirthday(new Date(310000000000L));
469         son.setBirthPlace("Munich");
470         son.setBankAccountOwner(father);
471         son.setFather(father);
472         son.setMother(mother);
473         //
474         Human3 daughter = new Human3();
475         daughter.setName("Daughter");
476         daughter.setBirthday(new Date(420000000000L));
477         daughter.setBirthPlace("New York");
478         daughter.setBankAccountOwner(father);
479         daughter.setFather(father);
480         daughter.setMother(mother);
481         //
482         ArrayList<Human3> children = new ArrayList<Human3>();
483         children.add(son);
484         children.add(daughter);
485         father.setChildren(children);
486         mother.setChildren(children);
487         //
488 
489         Constructor constructor = new Constructor();
490         TypeDescription Human3Description = new TypeDescription(Human3.class);
491         Human3Description.putListPropertyType("children", Human3.class);
492         constructor.addTypeDescription(Human3Description);
493 
494         Yaml yaml = new Yaml(constructor);
495         String output = yaml.dump(father.getChildren());
496         // System.out.println(output);
497         String etalon = Util.getLocalResource("recursive/with-children-as-list.yaml");
498         assertEquals(etalon, output);
499         //
500         List<Human3> children2 = (List<Human3>) yaml.load(output);
501         assertNotNull(children2);
502         Human3 son2 = children2.iterator().next();
503         assertEquals(2, children2.size());
504 
505         Human3 father2 = son2.getFather();
506         assertEquals("Father", father2.getName());
507         assertEquals("Mother", son2.getMother().getName());
508         assertSame(father2, father2.getBankAccountOwner());
509         assertSame(father2.getPartner(), son2.getMother());
510         assertSame(father2, son2.getMother().getPartner());
511 
512         assertSame(father2.getPartner().getChildren(), children2);
513 
514         for (Object child : children2) {
515             // check if type descriptor was correct
516             assertSame(Human3.class, child.getClass());
517         }
518     }
519 
520     public void testBeanRing() throws IOException {
521         Human man1 = new Human();
522         man1.setName("Man 1");
523         Human man2 = new Human();
524         man2.setName("Man 2");
525         Human man3 = new Human();
526         man3.setName("Man 3");
527         man1.setBankAccountOwner(man2);
528         man2.setBankAccountOwner(man3);
529         man3.setBankAccountOwner(man1);
530         //
531         Yaml yaml = new Yaml();
532         String output = yaml.dump(man1);
533         // System.out.println(output);
534         String etalon = Util.getLocalResource("recursive/beanring-3.yaml");
535         assertEquals(etalon, output);
536         //
537         Human loadedMan1 = (Human) yaml.load(output);
538         assertNotNull(loadedMan1);
539         assertEquals("Man 1", loadedMan1.getName());
540         Human loadedMan2 = loadedMan1.getBankAccountOwner();
541         Human loadedMan3 = loadedMan2.getBankAccountOwner();
542         assertSame(loadedMan1, loadedMan3.getBankAccountOwner());
543     }
544 
545     public void qtestCollectionRing() throws IOException {
546         // Set<Object> set = new HashSet<Object>();
547         // List<Object> list = new ArrayList<Object>();
548         // Map<Object, Object> map = new HashMap<Object, Object>();
549         // set.add(list);
550         // list.add(map);
551         // map.put("1", set);
552         // //
553         // try {
554         // Yaml yaml = new Yaml();
555         // String output = yaml.dump(set);
556         // // String etalon = Util.getLocalResource("recursive/???.yaml");
557         // // assertEquals(etalon, output);
558         // //
559         // // Set<Object> loadedSet = (Set<Object>) yaml.load(output);
560         // } catch (StackOverflowError e) {
561         // fail("Cannot dump recursive collections.");
562         // }
563     }
564 
565     /**
566      * Checks if object was put into the set after full construction. So the
567      * hashCode was calculated correctly (if it depends on internal object's
568      * state).
569      * 
570      * @param set
571      */
572     private void validateSet(Set<?> set) {
573         for (Object object : set) {
574             assertTrue(set.contains(object));
575         }
576     }
577 
578     /**
579      * Checks if object was put into the map as key after full construction. So
580      * the hashCode was calculated correctly (if it depends on internal object's
581      * state).
582      * 
583      * @param map
584      */
585     private void validateMapKeys(Map<?, ?> map) {
586         for (Map.Entry<?, ?> entry : map.entrySet()) {
587             assertTrue(map.containsKey(entry.getKey()));
588         }
589     }
590 
591     public void testChildrenWithoutRootTag() throws IOException {
592         Human father = new Human();
593         father.setName("Father");
594         father.setBirthday(new Date(1000000000));
595         father.setBirthPlace("Leningrad");
596         father.setBankAccountOwner(father);
597         //
598         Human mother = new Human();
599         mother.setName("Mother");
600         mother.setBirthday(new Date(100000000000L));
601         mother.setBirthPlace("Saint-Petersburg");
602         father.setPartner(mother);
603         mother.setPartner(father);
604         mother.setBankAccountOwner(father);
605         //
606         Human son = new Human();
607         son.setName("Son");
608         son.setBirthday(new Date(310000000000L));
609         son.setBirthPlace("Munich");
610         son.setBankAccountOwner(father);
611         son.setFather(father);
612         son.setMother(mother);
613         //
614         Human daughter = new Human();
615         daughter.setName("Daughter");
616         daughter.setBirthday(new Date(420000000000L));
617         daughter.setBirthPlace("New York");
618         daughter.setBankAccountOwner(father);
619         daughter.setFather(father);
620         daughter.setMother(mother);
621         //
622         Set<Human> children = new LinkedHashSet<Human>(2);
623         children.add(son);
624         children.add(daughter);
625         father.setChildren(children);
626         mother.setChildren(children);
627         //
628         Yaml beanDumper = new Yaml();
629         String output = beanDumper.dumpAsMap(son);
630         // System.out.println(output);
631         String etalon = Util.getLocalResource("recursive/with-children-no-root-tag.yaml");
632         assertEquals(etalon, output);
633         TypeDescription humanDescription = new TypeDescription(Human.class);
634         humanDescription.putMapPropertyType("children", Human.class, Object.class);
635         Yaml beanLoader = new Yaml(new Constructor(humanDescription));
636         //
637         Human son2 = beanLoader.loadAs(output, Human.class);
638         assertNotNull(son2);
639         assertEquals("Son", son.getName());
640 
641         Human father2 = son2.getFather();
642         assertEquals("Father", father2.getName());
643         assertEquals("Mother", son2.getMother().getName());
644         assertSame(father2, father2.getBankAccountOwner());
645         assertSame(father2.getPartner(), son2.getMother());
646         assertSame(father2, son2.getMother().getPartner());
647 
648         Set<Human> children2 = father2.getChildren();
649         assertEquals(2, children2.size());
650         assertSame(father2.getPartner().getChildren(), children2);
651 
652         for (Object child : children2) {
653             // check if type descriptor was correct
654             assertSame(Human.class, child.getClass());
655         }
656 
657         // check if hashCode is correct
658         validateSet(children2);
659     }
660 }