Finish issue73; do not omit !!set tag for JavaBean properties
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index e36ac20..c6441f1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -7,6 +7,9 @@
</properties>
<body>
<release version="1.7" date="in Mercurial" description="development">
+ <action dev="py4fun" type="add" issue="73" due-to="birnbuazn">
+ Provide sequence support for loading java.util.Set (2010-07-19)
+ </action>
<action dev="py4fun" type="add" issue="72" due-to="birnbuazn">
Support java.util.Collection as a parent for List and Set (2010-07-09)
</action>
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
index a2bbc77..6e01224 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
@@ -252,8 +252,8 @@
@SuppressWarnings("unchecked")
protected Set<? extends Object> constructSet(SequenceNode node) {
Set<Object> result;
- if (Set.class.isAssignableFrom(node.getType()) && !node.getType().isInterface()) {
- // the root class may be defined (Vector for instance)
+ if (!node.getType().isInterface()) {
+ // the root class may be defined
try {
result = (Set<Object>) node.getType().newInstance();
} catch (Exception e) {
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
index 40787e6..755245c 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
@@ -161,9 +161,8 @@
}
} else if (SortedSet.class.isAssignableFrom(node.getType())) {
SortedSet<Object> set = new TreeSet<Object>();
- if (!node.isTwoStepsConstruction()) {
- constructSet2ndStep(mnode, set);
- }
+ // set cannot be recursive
+ constructSet2ndStep(mnode, set);
return set;
} else if (Collection.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
@@ -491,7 +490,7 @@
SequenceNode snode = (SequenceNode) node;
if (Set.class.isAssignableFrom(node.getType())) {
if (node.isTwoStepsConstruction()) {
- return createDefaultSet(snode.getValue().size());
+ throw new YAMLException("Set cannot be recursive.");
} else {
return constructSet(snode);
}
diff --git a/src/main/java/org/yaml/snakeyaml/representer/Representer.java b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
index 6c0d147..89ec57d 100644
--- a/src/main/java/org/yaml/snakeyaml/representer/Representer.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
@@ -126,8 +126,8 @@
// the node is a map, set or JavaBean
if (!Map.class.isAssignableFrom(propertyValue.getClass())) {
// the node is set or JavaBean
- if (customTag == null) {
- // custom tag is not defined
+ if (customTag == null && !nodeValue.getTag().equals(Tag.SET)) {
+ // custom tag is not defined, set must keep the '!!set' tag
if (property.getType() == propertyValue.getClass()) {
// we do not need global tag because the property
// Class is the same as the runtime class
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue73/ArrayListTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue73/ArrayListTest.java
new file mode 100644
index 0000000..34ed71e
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue73/ArrayListTest.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2008-2010, http://code.google.com/p/snakeyaml/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.yaml.snakeyaml.issues.issue73;
+
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * Test bean when the implementation is defined: ArrayList instead of just the
+ * interface List
+ */
+public class ArrayListTest extends TestCase {
+ public void testListImplementation() {
+ Bean1 bean = new Bean1();
+ bean.setId("ID123");
+ ArrayList<String> list = new ArrayList<String>(3);
+ list.add("zzz");
+ list.add("xxx");
+ list.add("ccc");
+ bean.setList(list);
+ Yaml yaml = new Yaml();
+ String doc = yaml.dump(bean);
+ // System.out.println(doc);
+ Bean1 loaded = (Bean1) yaml.load(doc);
+ assertEquals(3, loaded.getList().size());
+ assertEquals(ArrayList.class, loaded.getList().getClass());
+ }
+
+ public static class Bean1 {
+ private ArrayList<String> list;
+ private String id;
+
+ public ArrayList<String> getList() {
+ return list;
+ }
+
+ public void setList(ArrayList<String> list) {
+ this.list = list;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue73/Blog.java b/src/test/java/org/yaml/snakeyaml/issues/issue73/Blog.java
index 2ae3ee6..55474ac 100644
--- a/src/test/java/org/yaml/snakeyaml/issues/issue73/Blog.java
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue73/Blog.java
@@ -25,6 +25,7 @@
private String name;
private Set<Post> posts = new TreeSet<Post>();
public Set<Integer> numbers = new LinkedHashSet<Integer>();
+ private TreeSet<String> labels = new TreeSet<String>();
public Blog() {
name = "SuperBlog";
@@ -54,6 +55,14 @@
this.posts = posts;
}
+ public TreeSet<String> getLabels() {
+ return labels;
+ }
+
+ public void setLabels(TreeSet<String> labels) {
+ this.labels = labels;
+ }
+
@Override
public boolean equals(Object obj) {
return name.equals(obj.toString());
@@ -68,5 +77,4 @@
public String toString() {
return "Blog '" + name + "'";
}
-
}
\ No newline at end of file
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue73/Post.java b/src/test/java/org/yaml/snakeyaml/issues/issue73/Post.java
index 85f85e7..259c528 100644
--- a/src/test/java/org/yaml/snakeyaml/issues/issue73/Post.java
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue73/Post.java
@@ -41,4 +41,24 @@
public int compareTo(Post o) {
return title.compareTo(o.title);
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Post) {
+ return toString().equals(obj.toString());
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Post " + title + " " + text;
+ }
+
}
\ No newline at end of file
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue73/RecursiveSetTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue73/RecursiveSetTest.java
new file mode 100644
index 0000000..1a35727
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue73/RecursiveSetTest.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2008-2010, http://code.google.com/p/snakeyaml/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.yaml.snakeyaml.issues.issue73;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.Util;
+import org.yaml.snakeyaml.Yaml;
+
+public class RecursiveSetTest extends TestCase {
+ @SuppressWarnings("unchecked")
+ public void testDumpException() {
+ Set set1 = new HashSet();
+ Set set2 = new HashSet();
+ set1.add(set2);
+ set2.add(set1);
+ Yaml yaml = new Yaml();
+ try {
+ yaml.dump(set1);
+ } catch (StackOverflowError e) {
+ assertEquals(null, e.getMessage());
+ }
+ }
+
+ public void testLoadException() {
+ String doc = Util.getLocalResource("issues/issue73-recursive4.txt");
+ // System.out.println(doc);
+ Yaml yaml = new Yaml();
+ try {
+ yaml.load(doc);
+ } catch (Exception e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("Set cannot be recursive."));
+ }
+ }
+
+ public void testLoadException2() {
+ String doc = Util.getLocalResource("issues/issue73-recursive5.txt");
+ // System.out.println(doc);
+ Yaml yaml = new Yaml();
+ try {
+ yaml.load(doc);
+ } catch (Exception e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("Set cannot be recursive."));
+ }
+ }
+
+ public static class Bean1 {
+ private Set<Object> set;
+ private String id;
+
+ public Set<Object> getSet() {
+ return set;
+ }
+
+ public void setSet(Set<Object> set) {
+ this.set = set;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue73/SetAsSequenceTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue73/SetAsSequenceTest.java
index de2ed00..9c8d720 100644
--- a/src/test/java/org/yaml/snakeyaml/issues/issue73/SetAsSequenceTest.java
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue73/SetAsSequenceTest.java
@@ -17,6 +17,7 @@
package org.yaml.snakeyaml.issues.issue73;
import java.util.Set;
+import java.util.TreeSet;
import junit.framework.TestCase;
@@ -36,6 +37,11 @@
blog.addPost(new Post("Title2", "text text 2"));
blog.numbers.add(19);
blog.numbers.add(17);
+ TreeSet<String> labels = new TreeSet<String>();
+ labels.add("Java");
+ labels.add("YAML");
+ labels.add("SnakeYAML");
+ blog.setLabels(labels);
DumperOptions options = new DumperOptions();
options.setAllowReadOnlyProperties(true);
Yaml yaml = new Yaml(new Dumper(options));
@@ -71,10 +77,22 @@
protected void checkTestBlog(Blog blog) {
Set<Post> posts = blog.getPosts();
assertEquals("Blog contains 2 posts", 2, posts.size());
- for (Post post : posts) {
- assertEquals(Post.class, post.getClass());
- }
+ assertTrue(posts.contains(new Post("Test", "Dummy")));
+ assertTrue(posts.contains(new Post("Highly", "Creative")));
assertEquals("No tags!", blog.getName());
assertEquals(0, blog.numbers.size());
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testLoadRootSet() {
+ Yaml yaml = new Yaml();
+ String doc = Util.getLocalResource("issues/issue73-3.txt");
+ Set<String> strings = (Set<String>) yaml.load(doc);
+ // System.out.println(strings);
+ assertEquals(3, strings.size());
+ assertTrue(strings.contains("aaa"));
+ assertTrue(strings.contains("bbb"));
+ assertTrue(strings.contains("ccc"));
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue73/TreeSetTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue73/TreeSetTest.java
new file mode 100644
index 0000000..308e730
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue73/TreeSetTest.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2008-2010, http://code.google.com/p/snakeyaml/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.yaml.snakeyaml.issues.issue73;
+
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * Test bean when the implementation is defined: TreeSet instead of just the
+ * interface Set
+ */
+public class TreeSetTest extends TestCase {
+ public void testSetImplementation() {
+ Bean1 bean = new Bean1();
+ bean.setId("ID123");
+ TreeSet<String> list = new TreeSet<String>();
+ list.add("zzz");
+ list.add("xxx");
+ list.add("ccc");
+ bean.setSet(list);
+ Yaml yaml = new Yaml();
+ String doc = yaml.dump(bean);
+ // System.out.println(doc);
+ //
+ Bean1 loaded = (Bean1) yaml.load(doc);
+ assertEquals(3, loaded.getSet().size());
+ assertEquals(TreeSet.class, loaded.getSet().getClass());
+ assertTrue(loaded.getSet().contains("zzz"));
+ assertTrue(loaded.getSet().contains("xxx"));
+ assertTrue(loaded.getSet().contains("ccc"));
+ }
+
+ public static class Bean1 {
+ private TreeSet<String> set;
+ private String id;
+
+ public TreeSet<String> getSet() {
+ return set;
+ }
+
+ public void setSet(TreeSet<String> set) {
+ this.set = set;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+ }
+}
diff --git a/src/test/resources/issues/issue73-1.txt b/src/test/resources/issues/issue73-1.txt
index 67be3af..78f262a 100644
--- a/src/test/resources/issues/issue73-1.txt
+++ b/src/test/resources/issues/issue73-1.txt
@@ -1,4 +1,5 @@
!!org.yaml.snakeyaml.issues.issue73.Blog
+labels: !!set {Java: null, SnakeYAML: null, YAML: null}
name: Test Me!
numbers: !!set {19: null, 17: null}
posts: !!set
diff --git a/src/test/resources/issues/issue73-3.txt b/src/test/resources/issues/issue73-3.txt
new file mode 100644
index 0000000..c188fe0
--- /dev/null
+++ b/src/test/resources/issues/issue73-3.txt
@@ -0,0 +1,5 @@
+!!java.util.HashSet
+- aaa
+- bbb
+- ccc
+
diff --git a/src/test/resources/issues/issue73-recursive4.txt b/src/test/resources/issues/issue73-recursive4.txt
new file mode 100644
index 0000000..5141208
--- /dev/null
+++ b/src/test/resources/issues/issue73-recursive4.txt
@@ -0,0 +1,5 @@
+&id001 !!java.util.HashSet
+- aaa
+- !!set { 1, *id001 }
+- ccc
+
diff --git a/src/test/resources/issues/issue73-recursive5.txt b/src/test/resources/issues/issue73-recursive5.txt
new file mode 100644
index 0000000..ddb7c42
--- /dev/null
+++ b/src/test/resources/issues/issue73-recursive5.txt
@@ -0,0 +1,4 @@
+!!org.yaml.snakeyaml.issues.issue73.RecursiveSetTest$Bean1
+id: ID123
+set: &id001 !!set {ccc: null, *id001: null, zzz: null}
+