Extends JavaBeanDumper to allow skipping global tags inside type-safe collections
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 36044b2..c9a4ea2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -8,6 +8,10 @@
<body>
<release version="1.4-SNAPSHOT" date="in Mercurial" description="development">
<action dev="py4fun" type="add">
+ Extends JavaBeanDumper to allow skipping global tags inside type-safe collections.
+ Introduce method setMapTagForBean() (2009-07-22)
+ </action>
+ <action dev="py4fun" type="add">
Add ConstructEmptyBeanTest to test JavaBean construction with no
properties in the YAML document(2009-07-22)
</action>
diff --git a/src/main/java/org/yaml/snakeyaml/JavaBeanDumper.java b/src/main/java/org/yaml/snakeyaml/JavaBeanDumper.java
index 1286dca..fe18406 100644
--- a/src/main/java/org/yaml/snakeyaml/JavaBeanDumper.java
+++ b/src/main/java/org/yaml/snakeyaml/JavaBeanDumper.java
@@ -6,9 +6,12 @@
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
+import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;
/**
@@ -17,6 +20,7 @@
public class JavaBeanDumper {
private boolean useGlobalTag;
private FlowStyle flowStyle;
+ private Set<Class<? extends Object>> classTags;
/**
* Create Dumper for JavaBeans
@@ -27,6 +31,7 @@
public JavaBeanDumper(boolean useGlobalTag) {
this.useGlobalTag = useGlobalTag;
this.flowStyle = FlowStyle.BLOCK;
+ classTags = new HashSet<Class<? extends Object>>();
}
/**
@@ -50,7 +55,11 @@
options.setExplicitRoot("tag:yaml.org,2002:map");
}
options.setDefaultFlowStyle(flowStyle);
- Dumper dumper = new Dumper(options);
+ Representer representer = new Representer();
+ for (Class<? extends Object> clazz : classTags) {
+ representer.addClassTag(clazz, "tag:yaml.org,2002:map");
+ }
+ Dumper dumper = new Dumper(representer, options);
List<Object> list = new ArrayList<Object>(1);
list.add(data);
dumper.dump(list.iterator(), output, new Resolver());
@@ -85,4 +94,13 @@
this.flowStyle = flowStyle;
}
+ /**
+ * Skip global tag with the specified class in a type-safe collection
+ *
+ * @param clazz
+ * JavaBean <code>Class</code> to represent as Map
+ */
+ public void setMapTagForBean(Class<? extends Object> clazz) {
+ classTags.add(clazz);
+ }
}
diff --git a/src/test/java/org/pyyaml/PyImportTest.java b/src/test/java/org/pyyaml/PyImportTest.java
index e3a8e06..8ae788d 100644
--- a/src/test/java/org/pyyaml/PyImportTest.java
+++ b/src/test/java/org/pyyaml/PyImportTest.java
@@ -50,13 +50,9 @@
}
protected String getResource(String theName) {
- try {
- String content;
- content = Util.getLocalResource(PATH + File.separator + theName);
- return content;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ String content;
+ content = Util.getLocalResource(PATH + File.separator + theName);
+ return content;
}
protected File[] getStreamsByExtension(String extention) {
diff --git a/src/test/java/org/yaml/snakeyaml/Util.java b/src/test/java/org/yaml/snakeyaml/Util.java
index 00aa857..7ac8530 100644
--- a/src/test/java/org/yaml/snakeyaml/Util.java
+++ b/src/test/java/org/yaml/snakeyaml/Util.java
@@ -9,30 +9,34 @@
public class Util {
- public static String getLocalResource(String theName) throws IOException {
- InputStream input;
- input = YamlDocument.class.getClassLoader().getResourceAsStream(theName);
- if (input == null) {
- throw new RuntimeException("Can not find " + theName);
- }
- BufferedInputStream is = new BufferedInputStream(input);
- StringBuffer buf = new StringBuffer(3000);
- int i;
+ public static String getLocalResource(String theName) {
try {
- while ((i = is.read()) != -1) {
- buf.append((char) i);
+ InputStream input;
+ input = YamlDocument.class.getClassLoader().getResourceAsStream(theName);
+ if (input == null) {
+ throw new RuntimeException("Can not find " + theName);
}
- } finally {
- is.close();
+ BufferedInputStream is = new BufferedInputStream(input);
+ StringBuffer buf = new StringBuffer(3000);
+ int i;
+ try {
+ while ((i = is.read()) != -1) {
+ buf.append((char) i);
+ }
+ } finally {
+ is.close();
+ }
+ String resource = buf.toString();
+ // convert EOLs
+ String[] lines = resource.split("\\r?\\n");
+ StringBuffer buffer = new StringBuffer();
+ for (int j = 0; j < lines.length; j++) {
+ buffer.append(lines[j]);
+ buffer.append("\n");
+ }
+ return buffer.toString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
- String resource = buf.toString();
- // convert EOLs
- String[] lines = resource.split("\\r?\\n");
- StringBuffer buffer = new StringBuffer();
- for (int j = 0; j < lines.length; j++) {
- buffer.append(lines[j]);
- buffer.append("\n");
- }
- return buffer.toString();
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/javabeans/Door.java b/src/test/java/org/yaml/snakeyaml/javabeans/Door.java
new file mode 100644
index 0000000..2ca4b1f
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/javabeans/Door.java
@@ -0,0 +1,55 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.javabeans;
+
+public class Door {
+ private String id;
+ private int height;
+
+ public Door(String id, int height) {
+ this.id = id;
+ this.height = height;
+ }
+
+ public Door() {
+ this.height = 3;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Door) {
+ Door door = (Door) obj;
+ return id.equals(door.id);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ return "Door id=" + id;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/javabeans/FrontDoor.java b/src/test/java/org/yaml/snakeyaml/javabeans/FrontDoor.java
new file mode 100644
index 0000000..339036f
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/javabeans/FrontDoor.java
@@ -0,0 +1,25 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.javabeans;
+
+public class FrontDoor extends Door {
+ private String keytype;
+
+ public FrontDoor() {
+ super();
+ }
+
+ public FrontDoor(String id, int height) {
+ super(id, height);
+ }
+
+ public String getKeytype() {
+ return keytype;
+ }
+
+ public void setKeytype(String keytype) {
+ this.keytype = keytype;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/javabeans/House.java b/src/test/java/org/yaml/snakeyaml/javabeans/House.java
new file mode 100644
index 0000000..39641c6
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/javabeans/House.java
@@ -0,0 +1,56 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.javabeans;
+
+import java.util.List;
+import java.util.Map;
+
+public class House {
+ private String street;
+ private int number;
+ private List<Room> rooms;
+ private FrontDoor frontDoor;
+ private Map<String, String> reminders;
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public void setNumber(int number) {
+ this.number = number;
+ }
+
+ public List<Room> getRooms() {
+ return rooms;
+ }
+
+ public void setRooms(List<Room> rooms) {
+ this.rooms = rooms;
+ }
+
+ public FrontDoor getFrontDoor() {
+ return frontDoor;
+ }
+
+ public void setFrontDoor(FrontDoor frontDoor) {
+ this.frontDoor = frontDoor;
+ }
+
+ public Map<String, String> getReminders() {
+ return reminders;
+ }
+
+ public void setReminders(Map<String, String> reminders) {
+ this.reminders = reminders;
+ }
+
+}
diff --git a/src/test/java/org/yaml/snakeyaml/javabeans/HouseTest.java b/src/test/java/org/yaml/snakeyaml/javabeans/HouseTest.java
new file mode 100644
index 0000000..c2fbf13
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/javabeans/HouseTest.java
@@ -0,0 +1,128 @@
+package org.yaml.snakeyaml.javabeans;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import junit.framework.TestCase;
+
+import org.yaml.snakeyaml.JavaBeanDumper;
+import org.yaml.snakeyaml.JavaBeanLoader;
+import org.yaml.snakeyaml.TypeDescription;
+import org.yaml.snakeyaml.Util;
+
+public class HouseTest extends TestCase {
+ /**
+ * with global root class tag (global tag should be avoided)
+ */
+ public void testDump3() {
+ House house = new House();
+ FrontDoor frontDoor = new FrontDoor("qaz1", 5);
+ frontDoor.setKeytype("qwerty123");
+ house.setFrontDoor(frontDoor);
+ List<Room> rooms = new LinkedList<Room>();
+ rooms.add(new Room("Hall"));
+ rooms.add(new Room("Kitchen"));
+ house.setRooms(rooms);
+ Map<String, String> reminders = new TreeMap<String, String>();
+ reminders.put("today", "do nothig");
+ reminders.put("tomorrow", "go shoping");
+ house.setReminders(reminders);
+ house.setNumber(1);
+ house.setStreet("Wall Street");
+ JavaBeanDumper beanDumper = new JavaBeanDumper();
+ beanDumper.setMapTagForBean(Room.class);
+ String yaml = beanDumper.dump(house);
+ System.out.println(yaml);
+ String etalon = Util.getLocalResource("javabeans/house-dump3.yaml");
+ assertEquals(etalon, yaml);
+ // load
+ TypeDescription description = new TypeDescription(House.class);
+ description.putListPropertyType("rooms", Room.class);
+ JavaBeanLoader<House> beanLoader = new JavaBeanLoader<House>(description);
+ House loadedHouse = beanLoader.load(yaml);
+ assertNotNull(loadedHouse);
+ assertEquals("Wall Street", loadedHouse.getStreet());
+ assertEquals(1, loadedHouse.getNumber());
+ FrontDoor fdoor = loadedHouse.getFrontDoor();
+ assertEquals(frontDoor.getId(), fdoor.getId());
+ assertEquals(frontDoor.getHeight(), fdoor.getHeight());
+ assertEquals(frontDoor.getKeytype(), fdoor.getKeytype());
+ assertEquals(frontDoor, fdoor);
+ assertEquals(reminders, loadedHouse.getReminders());
+ List<Room> loadedRooms = loadedHouse.getRooms();
+ assertEquals(rooms, loadedRooms);
+ // dump again
+ String yaml3 = beanDumper.dump(loadedHouse);
+ assertEquals(yaml, yaml3);
+ }
+
+ /**
+ * no root global tag
+ */
+ public void testDump1() {
+ House house = new House();
+ FrontDoor frontDoor = new FrontDoor("qaz1", 5);
+ frontDoor.setKeytype("qwerty123");
+ house.setFrontDoor(frontDoor);
+ List<Room> rooms = new LinkedList<Room>();
+ rooms.add(new Room("Hall"));
+ rooms.add(new Room("Kitchen"));
+ house.setRooms(rooms);
+ Map<String, String> reminders = new TreeMap<String, String>();
+ reminders.put("today", "do nothig");
+ reminders.put("tomorrow", "go shoping");
+ house.setReminders(reminders);
+ house.setNumber(1);
+ house.setStreet("Wall Street");
+ JavaBeanDumper beanDumper = new JavaBeanDumper();
+ String yaml = beanDumper.dump(house);
+ String etalon = Util.getLocalResource("javabeans/house-dump1.yaml");
+ assertEquals(etalon, yaml);
+ // false is default
+ beanDumper = new JavaBeanDumper(false);
+ String output2 = beanDumper.dump(house);
+ assertEquals(etalon, output2);
+ // load
+ JavaBeanLoader<House> beanLoader = new JavaBeanLoader<House>(House.class);
+ House loadedHouse = beanLoader.load(yaml);
+ assertNotNull(loadedHouse);
+ assertEquals("Wall Street", loadedHouse.getStreet());
+ // dump again
+ String yaml3 = beanDumper.dump(loadedHouse);
+ assertEquals(yaml, yaml3);
+ }
+
+ /**
+ * with global root class tag (global tag should be avoided)
+ */
+ public void testDump2() {
+ House house = new House();
+ FrontDoor frontDoor = new FrontDoor("qaz1", 5);
+ frontDoor.setKeytype("qwerty123");
+ house.setFrontDoor(frontDoor);
+ List<Room> rooms = new LinkedList<Room>();
+ rooms.add(new Room("Hall"));
+ rooms.add(new Room("Kitchen"));
+ house.setRooms(rooms);
+ Map<String, String> reminders = new TreeMap<String, String>();
+ reminders.put("today", "do nothig");
+ reminders.put("tomorrow", "go shoping");
+ house.setReminders(reminders);
+ house.setNumber(1);
+ house.setStreet("Wall Street");
+ JavaBeanDumper beanDumper = new JavaBeanDumper(true);
+ String yaml = beanDumper.dump(house);
+ String etalon = Util.getLocalResource("javabeans/house-dump2.yaml");
+ assertEquals(etalon, yaml);
+ // load
+ JavaBeanLoader<House> beanLoader = new JavaBeanLoader<House>(House.class);
+ House loadedHouse = beanLoader.load(yaml);
+ assertNotNull(loadedHouse);
+ assertEquals("Wall Street", loadedHouse.getStreet());
+ // dump again
+ String yaml3 = beanDumper.dump(loadedHouse);
+ assertEquals(yaml, yaml3);
+ }
+}
diff --git a/src/test/java/org/yaml/snakeyaml/javabeans/Room.java b/src/test/java/org/yaml/snakeyaml/javabeans/Room.java
new file mode 100644
index 0000000..6999c07
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/javabeans/Room.java
@@ -0,0 +1,45 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.javabeans;
+
+public class Room {
+ private String name;
+
+ public Room() {
+ this.name = "Bedroom";
+ }
+
+ public Room(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Room) {
+ Room room = (Room) obj;
+ return name.equals(room.name);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Room name=" + name;
+ }
+
+}
diff --git a/src/test/resources/javabeans/house-dump1.yaml b/src/test/resources/javabeans/house-dump1.yaml
new file mode 100644
index 0000000..3b11db1
--- /dev/null
+++ b/src/test/resources/javabeans/house-dump1.yaml
@@ -0,0 +1,14 @@
+frontDoor:
+ height: 5
+ id: qaz1
+ keytype: qwerty123
+number: 1
+reminders:
+ today: do nothig
+ tomorrow: go shoping
+rooms:
+- !!org.yaml.snakeyaml.javabeans.Room
+ name: Hall
+- !!org.yaml.snakeyaml.javabeans.Room
+ name: Kitchen
+street: Wall Street
\ No newline at end of file
diff --git a/src/test/resources/javabeans/house-dump2.yaml b/src/test/resources/javabeans/house-dump2.yaml
new file mode 100644
index 0000000..d466c65
--- /dev/null
+++ b/src/test/resources/javabeans/house-dump2.yaml
@@ -0,0 +1,15 @@
+!!org.yaml.snakeyaml.javabeans.House
+frontDoor:
+ height: 5
+ id: qaz1
+ keytype: qwerty123
+number: 1
+reminders:
+ today: do nothig
+ tomorrow: go shoping
+rooms:
+- !!org.yaml.snakeyaml.javabeans.Room
+ name: Hall
+- !!org.yaml.snakeyaml.javabeans.Room
+ name: Kitchen
+street: Wall Street
\ No newline at end of file
diff --git a/src/test/resources/javabeans/house-dump3.yaml b/src/test/resources/javabeans/house-dump3.yaml
new file mode 100644
index 0000000..448ce8b
--- /dev/null
+++ b/src/test/resources/javabeans/house-dump3.yaml
@@ -0,0 +1,12 @@
+frontDoor:
+ height: 5
+ id: qaz1
+ keytype: qwerty123
+number: 1
+reminders:
+ today: do nothig
+ tomorrow: go shoping
+rooms:
+- name: Hall
+- name: Kitchen
+street: Wall Street