1 /** 2 * Copyright (c) 2008, 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 } 659