View Javadoc

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