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