apply recursive_4.patch.txt from Alexander Maslov (issue 1)
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
index 1460610..c72531b 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
@@ -6,6 +6,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -154,6 +155,17 @@
return new LinkedHashMap<Object, Object>();
}
+ protected Set<Object> createDefaultSet() {
+ // respect order from YAML document
+ return new LinkedHashSet<Object>();
+ }
+
+ protected Set<Object> constructSet(MappingNode node) {
+ Set<Object> set = createDefaultSet();
+ constructSet2ndStep(node, set);
+ return set;
+ }
+
protected Map<Object, Object> constructMapping(MappingNode node) {
Map<Object, Object> mapping = createDefaultMap();
constructMapping2ndStep(node, mapping);
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
index cfe9878..180b3dc 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
@@ -96,27 +96,16 @@
@SuppressWarnings("unchecked")
public Object construct(Node node) {
Object result = null;
- Class<? extends Object> customTag = typeTags.get(node.getTag());
try {
- Class cl;
- if (customTag == null) {
- if (node.getTag().length() < "tag:yaml.org,2002:".length()) {
- throw new YAMLException("Unknown tag: " + node.getTag());
- }
- String name = node.getTag().substring("tag:yaml.org,2002:".length());
- cl = Class.forName(name);
- } else {
- cl = customTag;
- }
+ Class cl = getClassForNode(node);
java.lang.reflect.Constructor javaConstructor;
switch (node.getNodeId()) {
case mapping:
- MappingNode mnode = (MappingNode) node;
- mnode.setType(cl);
+ node.setType(cl);
if (node.isTwoStepsConstruction()) {
- result = createMappingNode(cl);
+ result = createMappingNode(node);
} else {
- result = constructMappingNode(mnode);
+ result = constructMappingNode((MappingNode) node);
}
break;
case sequence:
@@ -167,14 +156,29 @@
result = constructScalarNode((ScalarNode) node);
break;
case sequence:
- result = constructSequence((SequenceNode) node);
+ SequenceNode snode = (SequenceNode) node;
+ if (node.isTwoStepsConstruction()) {
+ result = createDefaultList(snode.getValue().size());
+ } else {
+ result = constructSequence(snode);
+ }
break;
default:// mapping
if (Map.class.isAssignableFrom(node.getType())) {
- result = super.constructMapping((MappingNode) node);
+ if (node.isTwoStepsConstruction()) {
+ result = createDefaultMap();
+ } else {
+ result = constructMapping((MappingNode) node);
+ }
+ } else if (Set.class.isAssignableFrom(node.getType())) {
+ if (node.isTwoStepsConstruction()) {
+ result = createDefaultSet();
+ } else {
+ result = constructSet((MappingNode) node);
+ }
} else {
if (node.isTwoStepsConstruction()) {
- result = createMappingNode(node.getType());
+ result = createMappingNode(node);
} else {
result = constructMappingNode((MappingNode) node);
}
@@ -204,7 +208,7 @@
} else if (Set.class.isAssignableFrom(node.getType())) {
constructSet2ndStep((MappingNode) node, (Set<Object>) object);
} else {
- constructMappingNode2ndStep((MappingNode) node, object, node.getType());
+ constructMappingNode2ndStep((MappingNode) node, object);
}
}
}
@@ -295,8 +299,12 @@
return result;
}
- private Object createMappingNode(Class<?> beanType) {
+ private Object createMappingNode(Node node) {
try {
+ Class<? extends Object> type = node.getType();
+ if (Modifier.isAbstract(type.getModifiers())) {
+ node.setType(getClassForNode(node));
+ }
/**
* Using only default constructor. Everything else will be
* initialized on 2nd step. If we do here some partial
@@ -304,11 +312,13 @@
* step? I think it is better to get only object here (to have it as
* reference for recursion) and do all other thing on 2nd step.
*/
- return beanType.newInstance();
+ return node.getType().newInstance();
} catch (InstantiationException e) {
throw new YAMLException(e);
} catch (IllegalAccessException e) {
throw new YAMLException(e);
+ } catch (ClassNotFoundException e) {
+ throw new YAMLException(e);
}
}
@@ -322,13 +332,12 @@
* @return constructed JavaBean
*/
private Object constructMappingNode(MappingNode node) {
- Class<? extends Object> beanType = node.getType();
- return constructMappingNode2ndStep(node, createMappingNode(beanType), beanType);
+ return constructMappingNode2ndStep(node, createMappingNode(node));
}
@SuppressWarnings("unchecked")
- private Object constructMappingNode2ndStep(MappingNode node, Object object,
- Class<? extends Object> beanType) {
+ private Object constructMappingNode2ndStep(MappingNode node, Object object) {
+ Class<? extends Object> beanType = node.getType();
List<Node[]> nodeValue = (List<Node[]>) node.getValue();
for (Node[] tuple : nodeValue) {
ScalarNode keyNode;
@@ -406,9 +415,25 @@
}
if (field.getName().equals(name)) {
return new FieldProperty(field);
- }
+ }
}
throw new YAMLException("Unable to find property '" + name + "' on class: "
+ type.getName());
}
+
+ protected Class<?> getClassForNode(Node node) throws ClassNotFoundException {
+ Class<? extends Object> customTag = typeTags.get(node.getTag());
+ if (customTag == null) {
+ if (node.getTag().length() < "tag:yaml.org,2002:".length()) {
+ throw new YAMLException("Unknown tag: " + node.getTag());
+ }
+ String name = node.getTag().substring("tag:yaml.org,2002:".length());
+ Class<?> cl = Class.forName(name);
+ typeTags.put(node.getTag(), cl);
+ return cl;
+ } else {
+ return customTag;
+ }
+ }
+
}
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
index 7ea30c4..6a0de9a 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
@@ -99,11 +99,6 @@
}
}
- protected Map<Object, Object> constructMapping(MappingNode node) {
- flattenMapping(node);
- return super.constructMapping(node);
- }
-
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
flattenMapping(node);
super.constructMapping2ndStep(node, mapping);
@@ -378,9 +373,9 @@
private class ConstuctYamlSet extends AbstractConstruct {
public Object construct(Node node) {
if (node.isTwoStepsConstruction()) {
- return createDefaultMap().keySet();
+ return createDefaultSet();
} else {
- return constructMapping((MappingNode) node).keySet();
+ return constructSet((MappingNode) node);
}
}
@@ -405,10 +400,8 @@
@SuppressWarnings("unchecked")
public Object construct(Node node) {
if (node.isTwoStepsConstruction()) {
- List<Node> nodeValue = (List<Node>) node.getValue();
- return createDefaultList(nodeValue.size());
+ return createDefaultList(((List<Node>) node.getValue()).size());
} else {
- // TODO is it ever called ???
return constructSequence((SequenceNode) node);
}
}
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/Tuple.java b/src/main/java/org/yaml/snakeyaml/constructor/Tuple.java
index e7c77a8..1a8599f 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/Tuple.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/Tuple.java
@@ -9,9 +9,6 @@
private final K _2;
public Tuple(T _1, K _2) {
- if (_1 == null || _2 == null) {
- throw new NullPointerException("Tuple does not accept NULL.");
- }
this._1 = _1;
this._2 = _2;
}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/AbstractHuman.java b/src/test/java/org/yaml/snakeyaml/recursive/AbstractHuman.java
new file mode 100644
index 0000000..6d9cc3e
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/AbstractHuman.java
@@ -0,0 +1,37 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive;
+
+import java.util.Date;
+
+public abstract class AbstractHuman {
+ private String name;
+ private Date birthday;
+ private String birthPlace;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Date getBirthday() {
+ return birthday;
+ }
+
+ public void setBirthday(Date birthday) {
+ this.birthday = birthday;
+ }
+
+ public String getBirthPlace() {
+ return birthPlace;
+ }
+
+ public void setBirthPlace(String birthPlace) {
+ this.birthPlace = birthPlace;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/Human.java b/src/test/java/org/yaml/snakeyaml/recursive/Human.java
index 8df0e54..bd6fe99 100644
--- a/src/test/java/org/yaml/snakeyaml/recursive/Human.java
+++ b/src/test/java/org/yaml/snakeyaml/recursive/Human.java
@@ -3,44 +3,21 @@
*/
package org.yaml.snakeyaml.recursive;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.LinkedHashSet;
+import java.util.Set;
-public class Human {
- private String name;
- private Date birthday;
- private String birthPlace;
+public class Human extends AbstractHuman {
+
private Human father;
private Human mother;
private Human parner;
private Human bankAccountOwner;
- private List<Human> children;
-
+ protected Set<Human> children;
+
public Human() {
- children = new LinkedList<Human>();
+ children = new LinkedHashSet<Human>();
}
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Date getBirthday() {
- return birthday;
- }
-
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
-
- public String getBirthPlace() {
- return birthPlace;
- }
-
+
public Human getFather() {
return father;
}
@@ -57,18 +34,6 @@
this.mother = mother;
}
- public void setBirthPlace(String birthPlace) {
- this.birthPlace = birthPlace;
- }
-
- public List<Human> getChildren() {
- return children;
- }
-
- public void setChildren(List<Human> children) {
- this.children = children;
- }
-
public Human getParner() {
return parner;
}
@@ -84,4 +49,13 @@
public void setBankAccountOwner(Human bankAccountOwner) {
this.bankAccountOwner = bankAccountOwner;
}
+
+ public Set<Human> getChildren() {
+ return children;
+ }
+
+ public void setChildren(Set<Human> children) {
+ this.children = children;
+ }
+
}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/Human2.java b/src/test/java/org/yaml/snakeyaml/recursive/Human2.java
new file mode 100644
index 0000000..4319f94
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/Human2.java
@@ -0,0 +1,61 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Human2 extends AbstractHuman {
+
+ private Human2 father;
+ private Human2 mother;
+ private Human2 parner;
+ private Human2 bankAccountOwner;
+ protected Map<Human2, String> children;
+
+ public Human2() {
+ children = new HashMap<Human2, String>();
+ }
+
+ public Human2 getFather() {
+ return father;
+ }
+
+ public void setFather(Human2 father) {
+ this.father = father;
+ }
+
+ public Human2 getMother() {
+ return mother;
+ }
+
+ public void setMother(Human2 mother) {
+ this.mother = mother;
+ }
+
+ public Human2 getParner() {
+ return parner;
+ }
+
+ public void setParner(Human2 parner) {
+ this.parner = parner;
+ }
+
+ public Human2 getBankAccountOwner() {
+ return bankAccountOwner;
+ }
+
+ public void setBankAccountOwner(Human2 bankAccountOwner) {
+ this.bankAccountOwner = bankAccountOwner;
+ }
+
+ public Map<Human2, String> getChildren() {
+ return children;
+ }
+
+ public void setChildren(Map<Human2, String> children) {
+ this.children = children;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/Human3.java b/src/test/java/org/yaml/snakeyaml/recursive/Human3.java
new file mode 100644
index 0000000..2d87698
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/Human3.java
@@ -0,0 +1,61 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class Human3 extends AbstractHuman {
+
+ private Human3 father;
+ private Human3 mother;
+ private Human3 parner;
+ private Human3 bankAccountOwner;
+ protected List<Human3> children;
+
+ public Human3() {
+ children = new LinkedList<Human3>();
+ }
+
+ public Human3 getFather() {
+ return father;
+ }
+
+ public void setFather(Human3 father) {
+ this.father = father;
+ }
+
+ public Human3 getMother() {
+ return mother;
+ }
+
+ public void setMother(Human3 mother) {
+ this.mother = mother;
+ }
+
+ public Human3 getParner() {
+ return parner;
+ }
+
+ public void setParner(Human3 parner) {
+ this.parner = parner;
+ }
+
+ public Human3 getBankAccountOwner() {
+ return bankAccountOwner;
+ }
+
+ public void setBankAccountOwner(Human3 bankAccountOwner) {
+ this.bankAccountOwner = bankAccountOwner;
+ }
+
+ public List<Human3> getChildren() {
+ return children;
+ }
+
+ public void setChildren(List<Human3> children) {
+ this.children = children;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/HumanTest.java b/src/test/java/org/yaml/snakeyaml/recursive/HumanTest.java
index a7e6b92..8356f93 100644
--- a/src/test/java/org/yaml/snakeyaml/recursive/HumanTest.java
+++ b/src/test/java/org/yaml/snakeyaml/recursive/HumanTest.java
@@ -4,13 +4,15 @@
package org.yaml.snakeyaml.recursive;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
import junit.framework.TestCase;
@@ -79,7 +81,7 @@
daughter.setFather(father);
daughter.setMother(mother);
//
- List<Human> children = new ArrayList<Human>(2);
+ Set<Human> children = new LinkedHashSet<Human>(2);
children.add(son);
children.add(daughter);
father.setChildren(children);
@@ -88,21 +90,312 @@
Constructor constructor = new Constructor();
TypeDescription humanDescription = new TypeDescription(Human.class);
- humanDescription.putListPropertyType("children", Human.class);
+ humanDescription.putMapPropertyType("children", Human.class, Object.class);
constructor.addTypeDescription(humanDescription);
Yaml yaml = new Yaml(new Loader(constructor));
- String output = yaml.dump(father);
- System.out.println(output);
+ String output = yaml.dump(son);
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/with-children.yaml");
+ assertEquals(etalon, output);
+ //
+ Human son2 = (Human) yaml.load(output);
+ assertNotNull(son2);
+ assertEquals("Son", son.getName());
+
+ Human father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ Set<Human> children2 = father2.getChildren();
+ assertEquals(2, children2.size());
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human.class, child.getClass()); // check if type
+ // descriptor was correct
+ }
+ }
+
+ public void testChildren2() throws IOException {
+ Human2 father = new Human2();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human2 mother = new Human2();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human2 son = new Human2();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human2 daughter = new Human2();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ HashMap<Human2, String> children = new LinkedHashMap<Human2, String>(2);
+ children.put(son, "son");
+ children.put(daughter, "daughter");
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription humanDescription = new TypeDescription(Human2.class);
+ humanDescription.putMapPropertyType("children", Human2.class, String.class);
+ constructor.addTypeDescription(humanDescription);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(son);
+ // System.out.println(output);
String etalon = Util.getLocalResource("recursive/with-children-2.yaml");
assertEquals(etalon, output);
//
- Human father2 = (Human) yaml.load(output);
- assertNotNull(father2);
+ Human2 son2 = (Human2) yaml.load(output);
+ assertNotNull(son2);
+ assertEquals("Son", son.getName());
+
+ Human2 father2 = son2.getFather();
assertEquals("Father", father2.getName());
- assertEquals("Mother", father2.getParner().getName());
- assertEquals("Father", father2.getBankAccountOwner().getName());
+ assertEquals("Mother", son2.getMother().getName());
assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ Map<Human2, String> children2 = father2.getChildren();
+ assertEquals(2, children2.size());
+ assertSame(father2.getParner().getChildren(), children2);
+
+ }
+
+ public void testChildren3() throws IOException {
+ Human3 father = new Human3();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human3 mother = new Human3();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human3 son = new Human3();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human3 daughter = new Human3();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ LinkedList<Human3> children = new LinkedList<Human3>();
+ children.add(son);
+ children.add(daughter);
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription Human3Description = new TypeDescription(Human3.class);
+ Human3Description.putListPropertyType("children", Human3.class);
+ constructor.addTypeDescription(Human3Description);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(son);
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/with-children-3.yaml");
+ assertEquals(etalon, output);
+ //
+ Human3 son2 = (Human3) yaml.load(output);
+ assertNotNull(son2);
+ assertEquals("Son", son.getName());
+
+ Human3 father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ List<Human3> children2 = father2.getChildren();
+ assertEquals(2, children2.size());
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human3.class, child.getClass()); // check if type
+ // descriptor was
+ // correct
+ }
+ }
+
+ /*
+ * Loads same structure as created in testChildren. But root object is set
+ * of children
+ */
+ @SuppressWarnings("unchecked")
+ public void testChildrenSetAsRoot() throws IOException {
+ String etalon = Util.getLocalResource("recursive/with-children-as-set.yaml");
+
+ Constructor constructor = new Constructor();
+ TypeDescription humanDescription = new TypeDescription(Human.class);
+ humanDescription.putMapPropertyType("children", Human.class, Object.class);
+ constructor.addTypeDescription(humanDescription);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ Set<Human> children2 = (Set<Human>) yaml.load(etalon);
+ assertNotNull(children2);
+ assertEquals(2, children2.size());
+
+ Human firstChild = children2.iterator().next();
+
+ Human father2 = firstChild.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", firstChild.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), firstChild.getMother());
+ assertSame(father2, firstChild.getMother().getParner());
+
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human.class, child.getClass()); // check if type
+ // descriptor was correct
+ }
+ }
+
+ /*
+ * Loads same structure as created in testChildren. But root object is map
+ * of children
+ */
+ @SuppressWarnings("unchecked")
+ public void testChildrenMapAsRoot() throws IOException {
+ String etalon = Util.getLocalResource("recursive/with-children-as-map.yaml");
+
+ Constructor constructor = new Constructor();
+ TypeDescription Human2Description = new TypeDescription(Human2.class);
+ Human2Description.putMapPropertyType("children", Human2.class, String.class);
+ constructor.addTypeDescription(Human2Description);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ Map<Human2, String> children2 = (Map<Human2, String>) yaml.load(etalon);
+ assertNotNull(children2);
+ assertEquals(2, children2.size());
+
+ Entry<Human2, String> firstEntry = children2.entrySet().iterator().next();
+ Human2 firstChild = firstEntry.getKey();
+
+ Human2 father2 = firstChild.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", firstChild.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), firstChild.getMother());
+ assertSame(father2, firstChild.getMother().getParner());
+
+ assertSame(father2.getParner().getChildren(), children2);
+ }
+
+ /*
+ * Loads same structure as created in testChildren. But root object is list
+ * of children
+ */
+ @SuppressWarnings("unchecked")
+ public void testChildrenListRoot() throws IOException {
+ Human3 father = new Human3();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human3 mother = new Human3();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human3 son = new Human3();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human3 daughter = new Human3();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ LinkedList<Human3> children = new LinkedList<Human3>();
+ children.add(son);
+ children.add(daughter);
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription Human3Description = new TypeDescription(Human3.class);
+ Human3Description.putListPropertyType("children", Human3.class);
+ constructor.addTypeDescription(Human3Description);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(father.getChildren());
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/with-children-as-list.yaml");
+ assertEquals(etalon, output);
+ //
+ List<Human3> children2 = (List<Human3>) yaml.load(output);
+ assertNotNull(children2);
+ Human3 son2 = children2.iterator().next();
+ assertEquals(2, children2.size());
+
+ Human3 father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human3.class, child.getClass()); // check if type
+ // descriptor was
+ // correct
+ }
}
public void testBeanRing() throws IOException {
@@ -118,7 +411,7 @@
//
Yaml yaml = new Yaml();
String output = yaml.dump(man1);
- System.out.println(output);
+ // System.out.println(output);
String etalon = Util.getLocalResource("recursive/beanring-3.yaml");
assertEquals(etalon, output);
//
@@ -132,22 +425,22 @@
// TODO Java's hashcode leaves much to be desired
public void qtestCollectionRing() throws IOException {
- Set<Object> set = new HashSet<Object>();
- List<Object> list = new ArrayList<Object>();
- Map<Object, Object> map = new HashMap<Object, Object>();
- set.add(list);
- list.add(map);
- map.put("1", set);
- //
- try {
- Yaml yaml = new Yaml();
- String output = yaml.dump(set);
- // String etalon = Util.getLocalResource("recursive/???.yaml");
- // assertEquals(etalon, output);
- //
- // Set<Object> loadedSet = (Set<Object>) yaml.load(output);
- } catch (StackOverflowError e) {
- fail("Cannot dump recursive collections.");
- }
+ // Set<Object> set = new HashSet<Object>();
+ // List<Object> list = new ArrayList<Object>();
+ // Map<Object, Object> map = new HashMap<Object, Object>();
+ // set.add(list);
+ // list.add(map);
+ // map.put("1", set);
+ // //
+ // try {
+ // Yaml yaml = new Yaml();
+ // String output = yaml.dump(set);
+ // // String etalon = Util.getLocalResource("recursive/???.yaml");
+ // // assertEquals(etalon, output);
+ // //
+ // // Set<Object> loadedSet = (Set<Object>) yaml.load(output);
+ // } catch (StackOverflowError e) {
+ // fail("Cannot dump recursive collections.");
+ // }
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/generics/AbstractHuman.java b/src/test/java/org/yaml/snakeyaml/recursive/generics/AbstractHuman.java
new file mode 100644
index 0000000..d244591
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/generics/AbstractHuman.java
@@ -0,0 +1,82 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive.generics;
+
+import java.util.Date;
+
+public abstract class AbstractHuman<T, K extends AbstractHuman<T, ?>> {
+ private String name;
+ private Date birthday;
+ private String birthPlace;
+ private K father;
+ private K mother;
+ private K parner;
+ private K bankAccountOwner;
+ protected T children;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Date getBirthday() {
+ return birthday;
+ }
+
+ public void setBirthday(Date birthday) {
+ this.birthday = birthday;
+ }
+
+ public String getBirthPlace() {
+ return birthPlace;
+ }
+
+ public K getFather() {
+ return father;
+ }
+
+ public void setFather(K father) {
+ this.father = father;
+ }
+
+ public K getMother() {
+ return mother;
+ }
+
+ public void setMother(K mother) {
+ this.mother = mother;
+ }
+
+ public void setBirthPlace(String birthPlace) {
+ this.birthPlace = birthPlace;
+ }
+
+ public T getChildren() {
+ return children;
+ }
+
+ public void setChildren(T children) {
+ this.children = children;
+ }
+
+ public K getParner() {
+ return parner;
+ }
+
+ public void setParner(K parner) {
+ this.parner = parner;
+ }
+
+ public K getBankAccountOwner() {
+ return bankAccountOwner;
+ }
+
+ public void setBankAccountOwner(K bankAccountOwner) {
+ this.bankAccountOwner = bankAccountOwner;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/generics/Human.java b/src/test/java/org/yaml/snakeyaml/recursive/generics/Human.java
new file mode 100644
index 0000000..339acab
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/generics/Human.java
@@ -0,0 +1,13 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive.generics;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class Human extends AbstractHuman<Set<Human>, Human>{
+ public Human() {
+ children = new LinkedHashSet<Human>();
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/generics/Human2.java b/src/test/java/org/yaml/snakeyaml/recursive/generics/Human2.java
new file mode 100644
index 0000000..4c8b38f
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/generics/Human2.java
@@ -0,0 +1,14 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive.generics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Human2 extends AbstractHuman<Map<Human2, String>, Human2>{
+
+ public Human2() {
+ children = new HashMap<Human2, String>();
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/generics/Human3.java b/src/test/java/org/yaml/snakeyaml/recursive/generics/Human3.java
new file mode 100644
index 0000000..a5bf905
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/generics/Human3.java
@@ -0,0 +1,14 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive.generics;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class Human3 extends AbstractHuman<List<Human3>, Human3>{
+
+ public Human3() {
+ children = new LinkedList<Human3>();
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/recursive/generics/HumanGenericsTest.java b/src/test/java/org/yaml/snakeyaml/recursive/generics/HumanGenericsTest.java
new file mode 100644
index 0000000..91b6452
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/recursive/generics/HumanGenericsTest.java
@@ -0,0 +1,426 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.recursive.generics;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.Loader;
+import org.yaml.snakeyaml.TypeDescription;
+import org.yaml.snakeyaml.Util;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.constructor.Constructor;
+
+public class HumanGenericsTest extends TestCase {
+
+ public void testNoChildren() throws IOException {
+ Human father = new Human();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ Human mother = new Human();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ Yaml yaml = new Yaml();
+ String output = yaml.dump(father);
+ String etalon = Util.getLocalResource("recursive/generics/no-children-1.yaml");
+ assertEquals(etalon, output);
+ //
+ Human father2 = (Human) yaml.load(output);
+ assertNotNull(father2);
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", father2.getParner().getName());
+ assertEquals("Father", father2.getBankAccountOwner().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ }
+
+ public void testChildren() throws IOException {
+ Human father = new Human();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human mother = new Human();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human son = new Human();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human daughter = new Human();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ Set<Human> children = new LinkedHashSet<Human>(2);
+ children.add(son);
+ children.add(daughter);
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription humanDescription = new TypeDescription(Human.class);
+ humanDescription.putMapPropertyType("children", Human.class, Object.class);
+ constructor.addTypeDescription(humanDescription);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(son);
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/generics/with-children.yaml");
+ assertEquals(etalon, output);
+ //
+ Human son2 = (Human) yaml.load(output);
+ assertNotNull(son2);
+ assertEquals("Son", son.getName());
+
+ Human father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ Set<Human> children2 = father2.getChildren();
+ assertEquals(2, children2.size());
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human.class, child.getClass()); // check if type
+ // descriptor was correct
+ }
+ }
+
+ public void testChildren2() throws IOException {
+ Human2 father = new Human2();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human2 mother = new Human2();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human2 son = new Human2();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human2 daughter = new Human2();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ HashMap<Human2, String> children = new LinkedHashMap<Human2, String>(2);
+ children.put(son, "son");
+ children.put(daughter, "daughter");
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription humanDescription = new TypeDescription(Human2.class);
+ humanDescription.putMapPropertyType("children", Human2.class, String.class);
+ constructor.addTypeDescription(humanDescription);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(son);
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/generics/with-children-2.yaml");
+ assertEquals(etalon, output);
+ //
+ Human2 son2 = (Human2) yaml.load(output);
+ assertNotNull(son2);
+ assertEquals("Son", son.getName());
+
+ Human2 father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ Map<Human2, String> children2 = father2.getChildren();
+ assertEquals(2, children2.size());
+ assertSame(father2.getParner().getChildren(), children2);
+
+ }
+
+ public void testChildren3() throws IOException {
+ Human3 father = new Human3();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human3 mother = new Human3();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human3 son = new Human3();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human3 daughter = new Human3();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ LinkedList<Human3> children = new LinkedList<Human3>();
+ children.add(son);
+ children.add(daughter);
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription Human3Description = new TypeDescription(Human3.class);
+ Human3Description.putListPropertyType("children", Human3.class);
+ constructor.addTypeDescription(Human3Description);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(son);
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/generics/with-children-3.yaml");
+ assertEquals(etalon, output);
+ //
+ Human3 son2 = (Human3) yaml.load(output);
+ assertNotNull(son2);
+ assertEquals("Son", son.getName());
+
+ Human3 father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ List<Human3> children2 = father2.getChildren();
+ assertEquals(2, children2.size());
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human3.class, child.getClass()); // check if type
+ // descriptor was
+ // correct
+ }
+ }
+
+ /*
+ * Loads same structure as created in testChildren. But root object is set
+ * of children
+ */
+ @SuppressWarnings("unchecked")
+ public void testChildrenSetAsRoot() throws IOException {
+ String etalon = Util.getLocalResource("recursive/generics/with-children-as-set.yaml");
+
+ Constructor constructor = new Constructor();
+ TypeDescription humanDescription = new TypeDescription(Human.class);
+ humanDescription.putMapPropertyType("children", Human.class, Object.class);
+ constructor.addTypeDescription(humanDescription);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ Set<Human> children2 = (Set<Human>) yaml.load(etalon);
+ assertNotNull(children2);
+ assertEquals(2, children2.size());
+
+ Human firstChild = children2.iterator().next();
+
+ Human father2 = firstChild.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", firstChild.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), firstChild.getMother());
+ assertSame(father2, firstChild.getMother().getParner());
+
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human.class, child.getClass()); // check if type
+ // descriptor was correct
+ }
+ }
+
+ /*
+ * Loads same structure as created in testChildren. But root object is map
+ * of children
+ */
+ @SuppressWarnings("unchecked")
+ public void testChildrenMapAsRoot() throws IOException {
+ String etalon = Util.getLocalResource("recursive/generics/with-children-as-map.yaml");
+
+ Constructor constructor = new Constructor();
+ TypeDescription Human2Description = new TypeDescription(Human2.class);
+ Human2Description.putMapPropertyType("children", Human2.class, String.class);
+ constructor.addTypeDescription(Human2Description);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ Map<Human2, String> children2 = (Map<Human2, String>) yaml.load(etalon);
+ assertNotNull(children2);
+ assertEquals(2, children2.size());
+
+ Entry<Human2, String> firstEntry = children2.entrySet().iterator().next();
+ Human2 firstChild = firstEntry.getKey();
+
+ Human2 father2 = firstChild.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", firstChild.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), firstChild.getMother());
+ assertSame(father2, firstChild.getMother().getParner());
+
+ assertSame(father2.getParner().getChildren(), children2);
+ }
+
+ /*
+ * Loads same structure as created in testChildren. But root object is list
+ * of children
+ */
+ @SuppressWarnings("unchecked")
+ public void testChildrenListRoot() throws IOException {
+ Human3 father = new Human3();
+ father.setName("Father");
+ father.setBirthday(new Date(1000000000));
+ father.setBirthPlace("Leningrad");
+ father.setBankAccountOwner(father);
+ //
+ Human3 mother = new Human3();
+ mother.setName("Mother");
+ mother.setBirthday(new Date(100000000000L));
+ mother.setBirthPlace("Saint-Petersburg");
+ father.setParner(mother);
+ mother.setParner(father);
+ mother.setBankAccountOwner(father);
+ //
+ Human3 son = new Human3();
+ son.setName("Son");
+ son.setBirthday(new Date(310000000000L));
+ son.setBirthPlace("Munich");
+ son.setBankAccountOwner(father);
+ son.setFather(father);
+ son.setMother(mother);
+ //
+ Human3 daughter = new Human3();
+ daughter.setName("Daughter");
+ daughter.setBirthday(new Date(420000000000L));
+ daughter.setBirthPlace("New York");
+ daughter.setBankAccountOwner(father);
+ daughter.setFather(father);
+ daughter.setMother(mother);
+ //
+ LinkedList<Human3> children = new LinkedList<Human3>();
+ children.add(son);
+ children.add(daughter);
+ father.setChildren(children);
+ mother.setChildren(children);
+ //
+
+ Constructor constructor = new Constructor();
+ TypeDescription Human3Description = new TypeDescription(Human3.class);
+ Human3Description.putListPropertyType("children", Human3.class);
+ constructor.addTypeDescription(Human3Description);
+
+ Yaml yaml = new Yaml(new Loader(constructor));
+ String output = yaml.dump(father.getChildren());
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/generics/with-children-as-list.yaml");
+ assertEquals(etalon, output);
+ //
+ List<Human3> children2 = (List<Human3>) yaml.load(output);
+ assertNotNull(children2);
+ Human3 son2 = children2.iterator().next();
+ assertEquals(2, children2.size());
+
+ Human3 father2 = son2.getFather();
+ assertEquals("Father", father2.getName());
+ assertEquals("Mother", son2.getMother().getName());
+ assertSame(father2, father2.getBankAccountOwner());
+ assertSame(father2.getParner(), son2.getMother());
+ assertSame(father2, son2.getMother().getParner());
+
+ assertSame(father2.getParner().getChildren(), children2);
+
+ for (Object child : children2) {
+ assertSame(Human3.class, child.getClass()); // check if type
+ // descriptor was
+ // correct
+ }
+ }
+
+ public void testBeanRing() throws IOException {
+ Human man1 = new Human();
+ man1.setName("Man 1");
+ Human man2 = new Human();
+ man2.setName("Man 2");
+ Human man3 = new Human();
+ man3.setName("Man 3");
+ man1.setBankAccountOwner(man2);
+ man2.setBankAccountOwner(man3);
+ man3.setBankAccountOwner(man1);
+ //
+ Yaml yaml = new Yaml();
+ String output = yaml.dump(man1);
+ // System.out.println(output);
+ String etalon = Util.getLocalResource("recursive/generics/beanring-3.yaml");
+ assertEquals(etalon, output);
+ //
+ Human loadedMan1 = (Human) yaml.load(output);
+ assertNotNull(loadedMan1);
+ assertEquals("Man 1", loadedMan1.getName());
+ Human loadedMan2 = loadedMan1.getBankAccountOwner();
+ Human loadedMan3 = loadedMan2.getBankAccountOwner();
+ assertSame(loadedMan1, loadedMan3.getBankAccountOwner());
+ }
+
+}
diff --git a/src/test/resources/recursive/beanring-3.yaml b/src/test/resources/recursive/beanring-3.yaml
index 01167ee..52c52b3 100644
--- a/src/test/resources/recursive/beanring-3.yaml
+++ b/src/test/resources/recursive/beanring-3.yaml
@@ -4,21 +4,21 @@
bankAccountOwner: *id001
birthPlace: null
birthday: null
- children: []
+ children: !!java.util.LinkedHashSet {}
father: null
mother: null
name: Man 3
parner: null
birthPlace: null
birthday: null
- children: []
+ children: !!java.util.LinkedHashSet {}
father: null
mother: null
name: Man 2
parner: null
birthPlace: null
birthday: null
-children: []
+children: !!java.util.LinkedHashSet {}
father: null
mother: null
name: Man 1
diff --git a/src/test/resources/recursive/generics/beanring-3.yaml b/src/test/resources/recursive/generics/beanring-3.yaml
new file mode 100644
index 0000000..a4df683
--- /dev/null
+++ b/src/test/resources/recursive/generics/beanring-3.yaml
@@ -0,0 +1,25 @@
+&id001 !!org.yaml.snakeyaml.recursive.generics.Human
+bankAccountOwner: !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: null
+ birthday: null
+ children: !!java.util.LinkedHashSet {}
+ father: null
+ mother: null
+ name: Man 3
+ parner: null
+ birthPlace: null
+ birthday: null
+ children: !!java.util.LinkedHashSet {}
+ father: null
+ mother: null
+ name: Man 2
+ parner: null
+birthPlace: null
+birthday: null
+children: !!java.util.LinkedHashSet {}
+father: null
+mother: null
+name: Man 1
+parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/no-children-1.yaml b/src/test/resources/recursive/generics/no-children-1.yaml
new file mode 100644
index 0000000..cb7c4d9
--- /dev/null
+++ b/src/test/resources/recursive/generics/no-children-1.yaml
@@ -0,0 +1,17 @@
+&id001 !!org.yaml.snakeyaml.recursive.generics.Human
+bankAccountOwner: *id001
+birthPlace: Leningrad
+birthday: 1970-01-12T13:46:40Z
+children: !!java.util.LinkedHashSet {}
+father: null
+mother: null
+name: Father
+parner: !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: !!java.util.LinkedHashSet {}
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/with-children-2.yaml b/src/test/resources/recursive/generics/with-children-2.yaml
new file mode 100644
index 0000000..7460bbd
--- /dev/null
+++ b/src/test/resources/recursive/generics/with-children-2.yaml
@@ -0,0 +1,35 @@
+&id002 !!org.yaml.snakeyaml.recursive.generics.Human2
+bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.generics.Human2
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: &id003
+ *id002: son
+ ? bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: {}
+ father: *id001
+ mother: &id004 !!org.yaml.snakeyaml.recursive.generics.Human2
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id003
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ name: Daughter
+ parner: null
+ : daughter
+ father: null
+ mother: null
+ name: Father
+ parner: *id004
+birthPlace: Munich
+birthday: 1979-10-28T23:06:40Z
+children: {}
+father: *id001
+mother: *id004
+name: Son
+parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/with-children-3.yaml b/src/test/resources/recursive/generics/with-children-3.yaml
new file mode 100644
index 0000000..f81f2ee
--- /dev/null
+++ b/src/test/resources/recursive/generics/with-children-3.yaml
@@ -0,0 +1,34 @@
+&id002 !!org.yaml.snakeyaml.recursive.generics.Human3
+bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.generics.Human3
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: &id003
+ - *id002
+ - bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: []
+ father: *id001
+ mother: &id004 !!org.yaml.snakeyaml.recursive.generics.Human3
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id003
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ name: Daughter
+ parner: null
+ father: null
+ mother: null
+ name: Father
+ parner: *id004
+birthPlace: Munich
+birthday: 1979-10-28T23:06:40Z
+children: []
+father: *id001
+mother: *id004
+name: Son
+parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/with-children-as-list.yaml b/src/test/resources/recursive/generics/with-children-as-list.yaml
new file mode 100644
index 0000000..eb04f93
--- /dev/null
+++ b/src/test/resources/recursive/generics/with-children-as-list.yaml
@@ -0,0 +1,35 @@
+&id002
+- !!org.yaml.snakeyaml.recursive.generics.Human3
+ bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.generics.Human3
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Father
+ parner: &id003 !!org.yaml.snakeyaml.recursive.generics.Human3
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ birthPlace: Munich
+ birthday: 1979-10-28T23:06:40Z
+ children: []
+ father: *id001
+ mother: *id003
+ name: Son
+ parner: null
+- !!org.yaml.snakeyaml.recursive.generics.Human3
+ bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: []
+ father: *id001
+ mother: *id003
+ name: Daughter
+ parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/with-children-as-map.yaml b/src/test/resources/recursive/generics/with-children-as-map.yaml
new file mode 100644
index 0000000..501c843
--- /dev/null
+++ b/src/test/resources/recursive/generics/with-children-as-map.yaml
@@ -0,0 +1,37 @@
+&id002 !!java.util.LinkedHashMap
+? !!org.yaml.snakeyaml.recursive.generics.Human2
+ bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.generics.Human2
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Father
+ parner: &id003 !!org.yaml.snakeyaml.recursive.generics.Human2
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ birthPlace: Munich
+ birthday: 1979-10-28T23:06:40Z
+ children: !!java.util.LinkedHashMap {}
+ father: *id001
+ mother: *id003
+ name: Son
+ parner: null
+: This is My Son
+? !!org.yaml.snakeyaml.recursive.generics.Human2
+ bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: !!java.util.LinkedHashMap {}
+ father: *id001
+ mother: *id003
+ name: Daughter
+ parner: null
+: This Is My Daughter
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/with-children-as-set.yaml b/src/test/resources/recursive/generics/with-children-as-set.yaml
new file mode 100644
index 0000000..2299b3b
--- /dev/null
+++ b/src/test/resources/recursive/generics/with-children-as-set.yaml
@@ -0,0 +1,37 @@
+&id002 !!set
+? !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Father
+ parner: &id003 !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ birthPlace: Munich
+ birthday: 1979-10-28T23:06:40Z
+ children: !!java.util.LinkedHashSet {}
+ father: *id001
+ mother: *id003
+ name: Son
+ parner: null
+: null
+? !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: !!java.util.LinkedHashSet {}
+ father: *id001
+ mother: *id003
+ name: Daughter
+ parner: null
+: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/generics/with-children.yaml b/src/test/resources/recursive/generics/with-children.yaml
new file mode 100644
index 0000000..0e9bf48
--- /dev/null
+++ b/src/test/resources/recursive/generics/with-children.yaml
@@ -0,0 +1,35 @@
+&id002 !!org.yaml.snakeyaml.recursive.generics.Human
+bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: &id003 !!java.util.LinkedHashSet
+ *id002: null
+ ? bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: !!java.util.LinkedHashSet {}
+ father: *id001
+ mother: &id004 !!org.yaml.snakeyaml.recursive.generics.Human
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id003
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ name: Daughter
+ parner: null
+ : null
+ father: null
+ mother: null
+ name: Father
+ parner: *id004
+birthPlace: Munich
+birthday: 1979-10-28T23:06:40Z
+children: !!java.util.LinkedHashSet {}
+father: *id001
+mother: *id004
+name: Son
+parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/no-children-1.yaml b/src/test/resources/recursive/no-children-1.yaml
index d86035c..449473c 100644
--- a/src/test/resources/recursive/no-children-1.yaml
+++ b/src/test/resources/recursive/no-children-1.yaml
@@ -2,7 +2,7 @@
bankAccountOwner: *id001
birthPlace: Leningrad
birthday: 1970-01-12T13:46:40Z
-children: []
+children: !!java.util.LinkedHashSet {}
father: null
mother: null
name: Father
@@ -10,7 +10,7 @@
bankAccountOwner: *id001
birthPlace: Saint-Petersburg
birthday: 1973-03-03T09:46:40Z
- children: []
+ children: !!java.util.LinkedHashSet {}
father: null
mother: null
name: Mother
diff --git a/src/test/resources/recursive/with-children-2.yaml b/src/test/resources/recursive/with-children-2.yaml
index aad8af8..4ed2047 100644
--- a/src/test/resources/recursive/with-children-2.yaml
+++ b/src/test/resources/recursive/with-children-2.yaml
@@ -1,33 +1,35 @@
-&id001 !!org.yaml.snakeyaml.recursive.Human
-bankAccountOwner: *id001
-birthPlace: Leningrad
-birthday: 1970-01-12T13:46:40Z
-children: &id002
-- bankAccountOwner: *id001
- birthPlace: Munich
- birthday: 1979-10-28T23:06:40Z
- children: []
- father: *id001
- mother: &id003
- bankAccountOwner: *id001
- birthPlace: Saint-Petersburg
- birthday: 1973-03-03T09:46:40Z
- children: *id002
- father: null
- mother: null
- name: Mother
- parner: *id001
- name: Son
- parner: null
-- bankAccountOwner: *id001
- birthPlace: New York
- birthday: 1983-04-24T02:40:00Z
- children: []
- father: *id001
- mother: *id003
- name: Daughter
- parner: null
-father: null
-mother: null
-name: Father
-parner: *id003
+&id002 !!org.yaml.snakeyaml.recursive.Human2
+bankAccountOwner: &id001
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: &id003
+ *id002: son
+ ? bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: {}
+ father: *id001
+ mother: &id004
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id003
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ name: Daughter
+ parner: null
+ : daughter
+ father: null
+ mother: null
+ name: Father
+ parner: *id004
+birthPlace: Munich
+birthday: 1979-10-28T23:06:40Z
+children: {}
+father: *id001
+mother: *id004
+name: Son
+parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/with-children-3.yaml b/src/test/resources/recursive/with-children-3.yaml
new file mode 100644
index 0000000..abca3b5
--- /dev/null
+++ b/src/test/resources/recursive/with-children-3.yaml
@@ -0,0 +1,34 @@
+&id002 !!org.yaml.snakeyaml.recursive.Human3
+bankAccountOwner: &id001
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: &id003
+ - *id002
+ - bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: []
+ father: *id001
+ mother: &id004
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id003
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ name: Daughter
+ parner: null
+ father: null
+ mother: null
+ name: Father
+ parner: *id004
+birthPlace: Munich
+birthday: 1979-10-28T23:06:40Z
+children: []
+father: *id001
+mother: *id004
+name: Son
+parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/with-children-as-list.yaml b/src/test/resources/recursive/with-children-as-list.yaml
new file mode 100644
index 0000000..faf28cd
--- /dev/null
+++ b/src/test/resources/recursive/with-children-as-list.yaml
@@ -0,0 +1,35 @@
+&id002
+- !!org.yaml.snakeyaml.recursive.Human3
+ bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.Human3
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Father
+ parner: &id003 !!org.yaml.snakeyaml.recursive.Human3
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ birthPlace: Munich
+ birthday: 1979-10-28T23:06:40Z
+ children: []
+ father: *id001
+ mother: *id003
+ name: Son
+ parner: null
+- !!org.yaml.snakeyaml.recursive.Human3
+ bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: []
+ father: *id001
+ mother: *id003
+ name: Daughter
+ parner: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/with-children-as-map.yaml b/src/test/resources/recursive/with-children-as-map.yaml
new file mode 100644
index 0000000..ebce1a4
--- /dev/null
+++ b/src/test/resources/recursive/with-children-as-map.yaml
@@ -0,0 +1,37 @@
+&id002 !!java.util.LinkedHashMap
+? !!org.yaml.snakeyaml.recursive.Human2
+ bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.Human2
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Father
+ parner: &id003 !!org.yaml.snakeyaml.recursive.Human2
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ birthPlace: Munich
+ birthday: 1979-10-28T23:06:40Z
+ children: !!java.util.LinkedHashMap {}
+ father: *id001
+ mother: *id003
+ name: Son
+ parner: null
+: This is My Son
+? !!org.yaml.snakeyaml.recursive.Human2
+ bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: !!java.util.LinkedHashMap {}
+ father: *id001
+ mother: *id003
+ name: Daughter
+ parner: null
+: This Is My Daughter
\ No newline at end of file
diff --git a/src/test/resources/recursive/with-children-as-set.yaml b/src/test/resources/recursive/with-children-as-set.yaml
new file mode 100644
index 0000000..d3ef5ed
--- /dev/null
+++ b/src/test/resources/recursive/with-children-as-set.yaml
@@ -0,0 +1,37 @@
+&id002 !!set
+? !!org.yaml.snakeyaml.recursive.Human
+ bankAccountOwner: &id001 !!org.yaml.snakeyaml.recursive.Human
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Father
+ parner: &id003 !!org.yaml.snakeyaml.recursive.Human
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id002
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ birthPlace: Munich
+ birthday: 1979-10-28T23:06:40Z
+ children: !!java.util.LinkedHashSet {}
+ father: *id001
+ mother: *id003
+ name: Son
+ parner: null
+: null
+? !!org.yaml.snakeyaml.recursive.Human
+ bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: !!java.util.LinkedHashSet {}
+ father: *id001
+ mother: *id003
+ name: Daughter
+ parner: null
+: null
\ No newline at end of file
diff --git a/src/test/resources/recursive/with-children.yaml b/src/test/resources/recursive/with-children.yaml
new file mode 100644
index 0000000..0d98bb9
--- /dev/null
+++ b/src/test/resources/recursive/with-children.yaml
@@ -0,0 +1,35 @@
+&id002 !!org.yaml.snakeyaml.recursive.Human
+bankAccountOwner: &id001
+ bankAccountOwner: *id001
+ birthPlace: Leningrad
+ birthday: 1970-01-12T13:46:40Z
+ children: &id003 !!java.util.LinkedHashSet
+ *id002: null
+ ? bankAccountOwner: *id001
+ birthPlace: New York
+ birthday: 1983-04-24T02:40:00Z
+ children: !!java.util.LinkedHashSet {}
+ father: *id001
+ mother: &id004
+ bankAccountOwner: *id001
+ birthPlace: Saint-Petersburg
+ birthday: 1973-03-03T09:46:40Z
+ children: *id003
+ father: null
+ mother: null
+ name: Mother
+ parner: *id001
+ name: Daughter
+ parner: null
+ : null
+ father: null
+ mother: null
+ name: Father
+ parner: *id004
+birthPlace: Munich
+birthday: 1979-10-28T23:06:40Z
+children: !!java.util.LinkedHashSet {}
+father: *id001
+mother: *id004
+name: Son
+parner: null
\ No newline at end of file