Deliver possibility to load immutable instances with no global tags
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 4375332..4178922 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -7,14 +7,17 @@
</properties>
<body>
<release version="1.4-SNAPSHOT" date="in Mercurial" description="development">
- <action dev="py4fun" type="update">
+ <action dev="py4fun" type="add">
+ Deliver possibility to load immutable instances with no global tags. Reflection for
+ constructor arguments is used to get the runtime classes (2009-08-04)
+ </action>
+ <action dev="py4fun" type="update">
Use more informative error message when a JavaBean property cannot
- be created (2009-08-08)
+ be created (2009-08-02)
</action>
<action dev="py4fun" type="update">
Refactor: Constructor is rewritten. Do not overwrite methods from BaseConstructor.
- Instead introduce ConstructScalar, ConstructSequence, ConstructMapping.
- Tests are not finished yet (2009-07-31)
+ Instead introduce ConstructScalar, ConstructSequence, ConstructMapping (2009-07-31)
</action>
<action dev="py4fun" type="update">
Change Maven repository path: groupId='org.yaml', artifactId='snakeyaml' (2009-07-31)
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
index e621c32..e805199 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
@@ -13,6 +13,7 @@
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -429,7 +430,34 @@
}
} else {
// create immutable object
- List<Object> argumentList = (List<Object>) constructSequence(snode);
+ List<java.lang.reflect.Constructor> possibleConstructors = new LinkedList<java.lang.reflect.Constructor>();
+ for (java.lang.reflect.Constructor constructor : node.getType().getConstructors()) {
+ if (snode.getValue().size() == constructor.getParameterTypes().length) {
+ possibleConstructors.add(constructor);
+ }
+ }
+ if (possibleConstructors.isEmpty()) {
+ throw new YAMLException("No constructors with "
+ + String.valueOf(snode.getValue().size()) + " arguments found for "
+ + node.getType());
+ }
+ List<Object> argumentList;
+ if (possibleConstructors.size() == 1) {
+ argumentList = new LinkedList<Object>();
+ java.lang.reflect.Constructor c = possibleConstructors.get(0);
+ int index = 0;
+ for (Node argumentNode : snode.getValue()) {
+ Class type = c.getParameterTypes()[index];
+ // set runtime classes for arguments
+ argumentNode.setType(type);
+ Object argumentValue = constructObject(argumentNode);
+ argumentList.add(argumentValue);
+ index++;
+ }
+ } else {
+ // use BaseConstructor
+ argumentList = (List<Object>) constructSequence(snode);
+ }
Class[] parameterTypes = new Class[argumentList.size()];
int index = 0;
for (Object parameter : argumentList) {
@@ -455,7 +483,7 @@
if (List.class.isAssignableFrom(node.getType())) {
constructSequenceStep2(snode, list);
} else {
- throw new UnsupportedOperationException("Immutable objects cannot be recursive.");
+ throw new YAMLException("Immutable objects cannot be recursive.");
}
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/JavaBeanWithNullValuesTest.java b/src/test/java/org/yaml/snakeyaml/JavaBeanWithNullValuesTest.java
index 80d469c..30948b4 100644
--- a/src/test/java/org/yaml/snakeyaml/JavaBeanWithNullValuesTest.java
+++ b/src/test/java/org/yaml/snakeyaml/JavaBeanWithNullValuesTest.java
@@ -98,7 +98,7 @@
javaBeanWithNullValues.setTimestamp(new Timestamp(System.currentTimeMillis()));
String dumpStr = yaml.dump(javaBeanWithNullValues);
- System.out.println(dumpStr);
+ // System.out.println(dumpStr);
assertFalse("No explicit root tag must be used.", dumpStr
.contains("JavaBeanWithNullValues"));
yaml = new Yaml();
diff --git a/src/test/java/org/yaml/snakeyaml/constructor/ClassTagsTest.java b/src/test/java/org/yaml/snakeyaml/constructor/ClassTagsTest.java
index e3e34cf..3648fd8 100644
--- a/src/test/java/org/yaml/snakeyaml/constructor/ClassTagsTest.java
+++ b/src/test/java/org/yaml/snakeyaml/constructor/ClassTagsTest.java
@@ -70,7 +70,6 @@
Loader loader = new Loader(constructor);
Yaml yaml = new Yaml(loader);
String source = Util.getLocalResource("constructor/car-without-tags.yaml");
- System.out.println(source);
Car car = (Car) yaml.load(source);
assertEquals("12-XP-F4", car.getPlate());
List<Wheel> wheels = car.getWheels();
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Code.java b/src/test/java/org/yaml/snakeyaml/immutable/Code.java
index d176abd..bc2ebe3 100644
--- a/src/test/java/org/yaml/snakeyaml/immutable/Code.java
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Code.java
@@ -31,6 +31,6 @@
@Override
public String toString() {
- return "Code code=" + code;
+ return "<Code code=" + code + ">";
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Code2.java b/src/test/java/org/yaml/snakeyaml/immutable/Code2.java
new file mode 100644
index 0000000..0d1e97d
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Code2.java
@@ -0,0 +1,43 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.immutable;
+
+/**
+ * Two constructors with 1 argument. These immutable objects are not supported.
+ */
+public class Code2 {
+ private final Integer code;
+
+ public Code2(Integer name) {
+ this.code = name;
+ }
+
+ public Code2(String name) {
+ this.code = Integer.parseInt(name);
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Code2) {
+ Code2 code = (Code2) obj;
+ return code.equals(code.code);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return code.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "<Code2 code=" + code + ">";
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Code3.java b/src/test/java/org/yaml/snakeyaml/immutable/Code3.java
new file mode 100644
index 0000000..e4ebf92
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Code3.java
@@ -0,0 +1,41 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.immutable;
+
+/**
+ * No constructors with 1 argument. These immutable objects are not supported.
+ */
+public class Code3 {
+ private final String name;
+ private final Integer code;
+
+ public Code3(String name, Integer code) {
+ this.code = code;
+ this.name = name;
+ }
+
+ public String getData() {
+ return name + code;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Code3) {
+ Code3 code = (Code3) obj;
+ return code.equals(code.code);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return code.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "<Code3 data=" + getData() + ">";
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Color.java b/src/test/java/org/yaml/snakeyaml/immutable/Color.java
index e5a8762..0271f5d 100644
--- a/src/test/java/org/yaml/snakeyaml/immutable/Color.java
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Color.java
@@ -31,6 +31,6 @@
@Override
public String toString() {
- return "Color id=" + name;
+ return "<Color id=" + name + ">";
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Point.java b/src/test/java/org/yaml/snakeyaml/immutable/Point.java
index 4fbe9c2..7ceb888 100644
--- a/src/test/java/org/yaml/snakeyaml/immutable/Point.java
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Point.java
@@ -20,4 +20,9 @@
this.x = x;
this.y = y;
}
+
+ @Override
+ public String toString() {
+ return "<Point x=" + String.valueOf(x) + " y=" + String.valueOf(y) + ">";
+ }
}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Point2.java b/src/test/java/org/yaml/snakeyaml/immutable/Point2.java
new file mode 100644
index 0000000..f85efad
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Point2.java
@@ -0,0 +1,35 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.immutable;
+
+/**
+ * Two public constructor with 2 argument are present
+ */
+public class Point2 {
+ private final Integer x;
+ private final Integer y;
+
+ public Integer getX() {
+ return x;
+ }
+
+ public Integer getY() {
+ return y;
+ }
+
+ public Point2(Double x, Double y) {
+ this.x = x.intValue();
+ this.y = y.intValue();
+ }
+
+ public Point2(Integer x, Integer y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ @Override
+ public String toString() {
+ return "<Point2 x=" + String.valueOf(x) + " y=" + String.valueOf(y) + ">";
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/Point3d.java b/src/test/java/org/yaml/snakeyaml/immutable/Point3d.java
index f1f9872..f98a033 100644
--- a/src/test/java/org/yaml/snakeyaml/immutable/Point3d.java
+++ b/src/test/java/org/yaml/snakeyaml/immutable/Point3d.java
@@ -19,4 +19,9 @@
public Point getPoint() {
return point;
}
+
+ @Override
+ public String toString() {
+ return "<Point3d point=" + point.toString() + " z=" + String.valueOf(z) + ">";
+ }
}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/ShapeCustomDumperTest.java b/src/test/java/org/yaml/snakeyaml/immutable/ShapeCustomDumperTest.java
deleted file mode 100644
index 0b535a8..0000000
--- a/src/test/java/org/yaml/snakeyaml/immutable/ShapeCustomDumperTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package org.yaml.snakeyaml.immutable;
-
-import junit.framework.TestCase;
-
-import org.yaml.snakeyaml.Util;
-import org.yaml.snakeyaml.Yaml;
-
-public class ShapeCustomDumperTest extends TestCase {
-
- public void testColor() {
- Yaml yaml = new Yaml();
- Color loaded = (Color) yaml.load("!!org.yaml.snakeyaml.immutable.Color BLACK");
- assertEquals("BLACK", loaded.getName());
- }
-
- public void testCode() {
- Yaml yaml = new Yaml();
- Code loaded = (Code) yaml.load("!!org.yaml.snakeyaml.immutable.Code 123");
- assertEquals(new Integer(123), loaded.getCode());
- }
-
- public void testSuperColorFail() {
- Yaml yaml = new Yaml();
- try {
- yaml.load("!!org.yaml.snakeyaml.immutable.SuperColor BLACK");
- fail("SuperColor requires Color and not a String.");
- } catch (Exception e) {
- assertEquals(
- "null; Can't construct a java object for tag:yaml.org,2002:org.yaml.snakeyaml.immutable.SuperColor; exception=Unsupported class: class org.yaml.snakeyaml.immutable.Color",
- e.getMessage());
- }
- }
-
- public void testPoint() {
- Yaml yaml = new Yaml();
- Point loaded = (Point) yaml.load("!!org.yaml.snakeyaml.immutable.Point [1.17, 3.14]");
- assertEquals(1.17, loaded.getX());
- assertEquals(3.14, loaded.getY());
- }
-
- public void testPointBlock() {
- Yaml yaml = new Yaml();
- Point loaded = (Point) yaml.load("!!org.yaml.snakeyaml.immutable.Point\n- 1.17\n- 3.14");
- assertEquals(1.17, loaded.getX());
- assertEquals(3.14, loaded.getY());
- }
-
- public void testPoint3d() {
- Yaml yaml = new Yaml();
- Point3d loaded = (Point3d) yaml
- .load("!!org.yaml.snakeyaml.immutable.Point3d [!!org.yaml.snakeyaml.immutable.Point [1.17, 3.14], 345.1]");
- assertEquals(345.1, loaded.getZ());
- }
-
- public void testShape() {
- Yaml yaml = new Yaml();
- String source = Util.getLocalResource("immutable/shape1.yaml");
- System.out.println(source);
- Shape loaded = (Shape) yaml.load(source);
- assertEquals(new Integer(123), loaded.getId());
- }
-
-}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/ShapeImmutableTest.java b/src/test/java/org/yaml/snakeyaml/immutable/ShapeImmutableTest.java
new file mode 100644
index 0000000..e3c7332
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/immutable/ShapeImmutableTest.java
@@ -0,0 +1,129 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.immutable;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.JavaBeanLoader;
+import org.yaml.snakeyaml.Util;
+import org.yaml.snakeyaml.Yaml;
+
+public class ShapeImmutableTest extends TestCase {
+
+ public void testColor() {
+ Yaml yaml = new Yaml();
+ Color loaded = (Color) yaml.load("!!org.yaml.snakeyaml.immutable.Color BLACK");
+ assertEquals("BLACK", loaded.getName());
+ }
+
+ public void testCode() {
+ Yaml yaml = new Yaml();
+ Code loaded = (Code) yaml.load("!!org.yaml.snakeyaml.immutable.Code 123");
+ assertEquals(new Integer(123), loaded.getCode());
+ }
+
+ public void testSuperColor() {
+ Yaml yaml = new Yaml();
+ SuperColor superColor = (SuperColor) yaml
+ .load("!!org.yaml.snakeyaml.immutable.SuperColor [!!org.yaml.snakeyaml.immutable.Color BLACK]");
+ assertEquals("BLACK", superColor.getColor().getName());
+ }
+
+ public void testSuperColorFail() {
+ Yaml yaml = new Yaml();
+ try {
+ yaml.load("!!org.yaml.snakeyaml.immutable.SuperColor BLACK");
+ fail("SuperColor requires Color and not a String.");
+ } catch (Exception e) {
+ assertEquals(
+ "null; Can't construct a java object for tag:yaml.org,2002:org.yaml.snakeyaml.immutable.SuperColor; exception=Unsupported class: class org.yaml.snakeyaml.immutable.Color",
+ e.getMessage());
+ }
+ }
+
+ public void testCode2() {
+ Yaml yaml = new Yaml();
+ try {
+ yaml.load("!!org.yaml.snakeyaml.immutable.Code2 555");
+ fail("There must be only 1 constructor with 1 argument for scalar.");
+ } catch (Exception e) {
+ assertEquals(
+ "null; Can't construct a java object for tag:yaml.org,2002:org.yaml.snakeyaml.immutable.Code2; exception=More then 1 constructor with 1 argument found for class org.yaml.snakeyaml.immutable.Code2",
+ e.getMessage());
+ }
+ }
+
+ public void testCode3() {
+ Yaml yaml = new Yaml();
+ try {
+ yaml.load("!!org.yaml.snakeyaml.immutable.Code3 777");
+ fail("There must be 1 constructor with 1 argument for scalar.");
+ } catch (Exception e) {
+ assertEquals(
+ "null; Can't construct a java object for tag:yaml.org,2002:org.yaml.snakeyaml.immutable.Code3; exception=No single argument constructor found for class org.yaml.snakeyaml.immutable.Code3",
+ e.getMessage());
+ }
+ }
+
+ public void testPoint() {
+ Yaml yaml = new Yaml();
+ Point loaded = (Point) yaml.load("!!org.yaml.snakeyaml.immutable.Point [1.17, 3.14]");
+ assertEquals(1.17, loaded.getX());
+ assertEquals(3.14, loaded.getY());
+ }
+
+ public void testPointBlock() {
+ Yaml yaml = new Yaml();
+ Point loaded = (Point) yaml.load("!!org.yaml.snakeyaml.immutable.Point\n- 1.17\n- 3.14");
+ assertEquals(1.17, loaded.getX());
+ assertEquals(3.14, loaded.getY());
+ }
+
+ public void testPointOnlyOneArgument() {
+ Yaml yaml = new Yaml();
+ try {
+ yaml.load("!!org.yaml.snakeyaml.immutable.Point\n- 1.17");
+ fail("Two arguments required.");
+ } catch (Exception e) {
+ assertEquals(
+ "null; Can't construct a java object for tag:yaml.org,2002:org.yaml.snakeyaml.immutable.Point; exception=No constructors with 1 arguments found for class org.yaml.snakeyaml.immutable.Point",
+ e.getMessage());
+ }
+ }
+
+ public void testPoint2() {
+ Yaml yaml = new Yaml();
+ Point2 loaded = (Point2) yaml.load("!!org.yaml.snakeyaml.immutable.Point2\n- 1\n- 3");
+ assertEquals(new Integer(1), loaded.getX());
+ assertEquals(new Integer(3), loaded.getY());
+ }
+
+ public void testPoint3d() {
+ Yaml yaml = new Yaml();
+ Point3d loaded = (Point3d) yaml
+ .load("!!org.yaml.snakeyaml.immutable.Point3d [!!org.yaml.snakeyaml.immutable.Point [1.17, 3.14], 345.1]");
+ assertEquals(345.1, loaded.getZ());
+ }
+
+ public void testShape() {
+ Yaml yaml = new Yaml();
+ String source = Util.getLocalResource("immutable/shape1.yaml");
+ Shape loaded = (Shape) yaml.load(source);
+ assertEquals(new Integer(123), loaded.getId());
+ }
+
+ public void testShapeNoTags() {
+ String source = Util.getLocalResource("immutable/shapeNoTags.yaml");
+ JavaBeanLoader<Shape> beanLoader = new JavaBeanLoader<Shape>(Shape.class);
+ Shape loaded = beanLoader.load(source);
+ assertEquals(new Integer(123), loaded.getId());
+ assertEquals("BLACK", loaded.getColor().getName());
+ assertEquals(1.17, loaded.getPoint().getX());
+ assertEquals(3.14, loaded.getPoint().getY());
+ assertEquals(345.1, loaded.getPoint3d().getZ());
+ assertEquals(1.96, loaded.getPoint3d().getPoint().getX());
+ assertEquals(1.78, loaded.getPoint3d().getPoint().getY());
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/immutable/SuperColor.java b/src/test/java/org/yaml/snakeyaml/immutable/SuperColor.java
index 2acec50..0df6a4b 100644
--- a/src/test/java/org/yaml/snakeyaml/immutable/SuperColor.java
+++ b/src/test/java/org/yaml/snakeyaml/immutable/SuperColor.java
@@ -33,4 +33,8 @@
public String toString() {
return "SuperColor color=" + color;
}
+
+ public Color getColor() {
+ return color;
+ }
}
diff --git a/src/test/java/org/yaml/snakeyaml/javabeans/TriangleBeanTest.java b/src/test/java/org/yaml/snakeyaml/javabeans/TriangleBeanTest.java
index 66f616f..e4a7bdf 100644
--- a/src/test/java/org/yaml/snakeyaml/javabeans/TriangleBeanTest.java
+++ b/src/test/java/org/yaml/snakeyaml/javabeans/TriangleBeanTest.java
@@ -18,7 +18,6 @@
bean.setName("Bean25");
JavaBeanDumper beanDumper = new JavaBeanDumper();
String output = beanDumper.dump(bean);
- System.out.println(output);
assertEquals(
"name: Bean25\nshape: !!org.yaml.snakeyaml.javabeans.Triangle\n name: Triangle25\n",
output);
diff --git a/src/test/resources/immutable/shapeNoTags.yaml b/src/test/resources/immutable/shapeNoTags.yaml
new file mode 100644
index 0000000..3ae087a
--- /dev/null
+++ b/src/test/resources/immutable/shapeNoTags.yaml
@@ -0,0 +1,8 @@
+color: BLACK
+point:
+- 1.17
+- 3.14
+point3d:
+ - [1.96, 1.78]
+ - 345.1
+id: 123
\ No newline at end of file