fix issue 69: Serialise Iterator and Iterable as sequences
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d3a8f69..cc8f903 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="update" issue="69">

+                Serialise Iterator and Iterable as sequences (2010-06-25)

+            </action>

             <action dev="py4fun" type="update" due-to="maslovalex">

                 Change error message when 'No suitable constructor with N arguments found for class' (2010-06-23)

             </action>

diff --git a/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java b/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java
index 738689f..939bb2f 100644
--- a/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java
@@ -21,6 +21,7 @@
 import java.util.HashMap;

 import java.util.HashSet;

 import java.util.IdentityHashMap;

+import java.util.LinkedHashMap;

 import java.util.List;

 import java.util.Map;

 import java.util.Set;

@@ -51,7 +52,8 @@
      */

     protected Represent nullRepresenter;

     @SuppressWarnings("unchecked")

-    protected final Map<Class, Represent> multiRepresenters = new HashMap<Class, Represent>();

+    //the order is important (map can be also a sequence of key-values)

+    protected final Map<Class, Represent> multiRepresenters = new LinkedHashMap<Class, Represent>();

     private Character defaultStyle;

     protected Boolean defaultFlowStyle;

     protected final Map<Object, Node> representedObjects = new IdentityHashMap<Object, Node>();

@@ -125,8 +127,12 @@
         return representScalar(tag, value, null);

     }

 

-    protected Node representSequence(Tag tag, List<? extends Object> sequence, Boolean flowStyle) {

-        List<Node> value = new ArrayList<Node>(sequence.size());

+    protected Node representSequence(Tag tag, Iterable<? extends Object> sequence, Boolean flowStyle) {

+        int size = 10;// default for ArrayList

+        if (sequence instanceof List<?>) {

+            size = ((List<?>) sequence).size();

+        }

+        List<Node> value = new ArrayList<Node>(size);

         SequenceNode node = new SequenceNode(tag, value, flowStyle);

         representedObjects.put(objectToRepresent, node);

         boolean bestStyle = true;

diff --git a/src/main/java/org/yaml/snakeyaml/representer/Representer.java b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
index 80e5258..b9dfafb 100644
--- a/src/main/java/org/yaml/snakeyaml/representer/Representer.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
@@ -183,7 +183,7 @@
                 // apply map tag where class is the same
                 Class<? extends Object> t = arguments[0];
                 SequenceNode snode = (SequenceNode) node;
-                List<Object> memberList = (List<Object>) object;
+                Iterable<Object> memberList = (Iterable<Object>) object;
                 Iterator<Object> iter = memberList.iterator();
                 for (Node childNode : snode.getValue()) {
                     Object member = iter.next();
diff --git a/src/main/java/org/yaml/snakeyaml/representer/SafeRepresenter.java b/src/main/java/org/yaml/snakeyaml/representer/SafeRepresenter.java
index 3d29a81..6c5a755 100644
--- a/src/main/java/org/yaml/snakeyaml/representer/SafeRepresenter.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/SafeRepresenter.java
@@ -21,6 +21,7 @@
 import java.util.Calendar;

 import java.util.Date;

 import java.util.HashMap;

+import java.util.Iterator;

 import java.util.LinkedHashMap;

 import java.util.List;

 import java.util.Map;

@@ -47,14 +48,17 @@
         this.representers.put(Boolean.class, new RepresentBoolean());

         this.representers.put(Character.class, new RepresentString());

         this.representers.put(byte[].class, new RepresentByteArray());

-        this.multiRepresenters.put(Number.class, new RepresentNumber());

-        this.multiRepresenters.put(List.class, new RepresentList());

         this.multiRepresenters.put(Map.class, new RepresentMap());

+        this.multiRepresenters.put(Number.class, new RepresentNumber());

         this.multiRepresenters.put(Set.class, new RepresentSet());

+        // iterator must go after other collections since otherwise maps and

+        // sets will be represented as sequences

+        this.multiRepresenters.put(Iterable.class, new RepresentIterable());

+        this.multiRepresenters.put(Iterator.class, new RepresentIterator());

         this.multiRepresenters.put(new Object[0].getClass(), new RepresentArray());

         this.multiRepresenters.put(Date.class, new RepresentDate());

-        this.multiRepresenters.put(Calendar.class, new RepresentDate());

         this.multiRepresenters.put(Enum.class, new RepresentEnum());

+        this.multiRepresenters.put(Calendar.class, new RepresentDate());

         classTags = new HashMap<Class<? extends Object>, Tag>();

     }

 

@@ -165,10 +169,32 @@
         }

     }

 

-    protected class RepresentList implements Represent {

+    protected class RepresentIterable implements Represent {

         @SuppressWarnings("unchecked")

         public Node representData(Object data) {

-            return representSequence(getTag(data.getClass(), Tag.SEQ), (List<Object>) data, null);

+            return representSequence(getTag(data.getClass(), Tag.SEQ), (Iterable<Object>) data,

+                    null);

+        }

+    }

+

+    protected class RepresentIterator implements Represent {

+        @SuppressWarnings("unchecked")

+        public Node representData(Object data) {

+            Iterator<Object> iter = (Iterator<Object>) data;

+            return representSequence(getTag(data.getClass(), Tag.SEQ), new IteratorWrapper(iter),

+                    null);

+        }

+    }

+

+    private class IteratorWrapper implements Iterable<Object> {

+        private Iterator<Object> iter;

+

+        public IteratorWrapper(Iterator<Object> iter) {

+            this.iter = iter;

+        }

+

+        public Iterator<Object> iterator() {

+            return iter;

         }

     }

 

diff --git a/src/test/java/org/yaml/snakeyaml/representer/RepresentIterableTest.java b/src/test/java/org/yaml/snakeyaml/representer/RepresentIterableTest.java
new file mode 100644
index 0000000..3d60770
--- /dev/null
+++ b/src/test/java/org/yaml/snakeyaml/representer/RepresentIterableTest.java
@@ -0,0 +1,68 @@
+/**

+ * 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.representer;

+

+import java.util.Iterator;

+

+import junit.framework.TestCase;

+

+import org.yaml.snakeyaml.Yaml;

+

+/**

+ * Test {@link issue69 http://code.google.com/p/snakeyaml/issues/detail?id=69}

+ */

+public class RepresentIterableTest extends TestCase {

+

+    public void testIterable() {

+        Yaml yaml = new Yaml();

+        String output = yaml.dump(new CounterFactory());

+        assertEquals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n", output);

+    }

+

+    public void testIterator() {

+        Yaml yaml = new Yaml();

+        String output = yaml.dump(new Counter(7));

+        assertEquals("[0, 1, 2, 3, 4, 5, 6]\n", output);

+    }

+

+    private class CounterFactory implements Iterable<Integer> {

+        public Iterator<Integer> iterator() {

+            return new Counter(10);

+        }

+    }

+

+    private class Counter implements Iterator<Integer> {

+        private int max = 0;

+        private int counter = 0;

+

+        public Counter(int max) {

+            this.max = max;

+        }

+

+        public boolean hasNext() {

+            return counter < max;

+        }

+

+        public Integer next() {

+            return counter++;

+        }

+

+        public void remove() {

+            throw new UnsupportedOperationException();

+        }

+    }

+}