Use NodeTuple instead of Node[] for mappings
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 146c6dc..85f59ee 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -7,6 +7,9 @@
 	</properties>

 	<body>

 	     <release version="1.4-SNAPSHOT" date="in Mercurial" description="development">

+            <action dev="py4fun" type="update">

+                Use NodeTuple instead of Node[] for mappings (2009-07-21)

+            </action>

             <action dev="py4fun" type="add">

                 Introduce JavaBeanLoader and JavaBeanDumper. Deprecate JavaBeanParser (2009-07-21)

             </action>

diff --git a/src/main/java/org/yaml/snakeyaml/composer/Composer.java b/src/main/java/org/yaml/snakeyaml/composer/Composer.java
index c28cd42..e9e7c4f 100644
--- a/src/main/java/org/yaml/snakeyaml/composer/Composer.java
+++ b/src/main/java/org/yaml/snakeyaml/composer/Composer.java
@@ -24,6 +24,7 @@
 import org.yaml.snakeyaml.nodes.MappingNode;
 import org.yaml.snakeyaml.nodes.Node;
 import org.yaml.snakeyaml.nodes.NodeId;
+import org.yaml.snakeyaml.nodes.NodeTuple;
 import org.yaml.snakeyaml.nodes.ScalarNode;
 import org.yaml.snakeyaml.nodes.SequenceNode;
 import org.yaml.snakeyaml.parser.Parser;
@@ -37,7 +38,7 @@
     private final Resolver resolver;
     private final Map<String, Node> anchors;
     private final Set<Node> recursiveNodes;
-    
+
     public Composer(Parser parser, Resolver resolver) {
         this.parser = parser;
         this.resolver = resolver;
@@ -104,7 +105,7 @@
                         .getStartMark());
             }
             Node result = (Node) anchors.get(anchor);
-            if(recursiveNodes.remove(result)) {
+            if (recursiveNodes.remove(result)) {
                 result.setTwoStepsConstruction(true);
             }
             return result;
@@ -173,15 +174,15 @@
         if (tag == null || tag.equals("!")) {
             tag = resolver.resolve(NodeId.mapping, null, startEvent.getImplicit());
         }
-        MappingNode node = new MappingNode(tag, new LinkedList<Node[]>(),
-                startEvent.getStartMark(), null, startEvent.getFlowStyle());
+        MappingNode node = new MappingNode(tag, new LinkedList<NodeTuple>(), startEvent
+                .getStartMark(), null, startEvent.getFlowStyle());
         if (anchor != null) {
             anchors.put(anchor, node);
         }
         while (!parser.checkEvent(MappingEndEvent.class)) {
             Node itemKey = composeNode(node, null);
             Node itemValue = composeNode(node, itemKey);
-            node.getValue().add(new Node[] { itemKey, itemValue });// 
+            node.getValue().add(new NodeTuple(itemKey, itemValue)); 
         }
         Event endEvent = parser.getEvent();
         node.setEndMark(endEvent.getEndMark());
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
index 9eab129..ea80d69 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/BaseConstructor.java
@@ -16,6 +16,7 @@
 import org.yaml.snakeyaml.composer.Composer;
 import org.yaml.snakeyaml.nodes.MappingNode;
 import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.NodeTuple;
 import org.yaml.snakeyaml.nodes.ScalarNode;
 import org.yaml.snakeyaml.nodes.SequenceNode;
 
@@ -172,17 +173,17 @@
     }
 
     protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
-        List<Node[]> nodeValue = (List<Node[]>) node.getValue();
-        for (Node[] tuple : nodeValue) {
-            Node keyNode = tuple[0];
-            Node valueNode = tuple[1];
+        List<NodeTuple> nodeValue = (List<NodeTuple>) node.getValue();
+        for (NodeTuple tuple : nodeValue) {
+            Node keyNode = tuple.getKeyNode();
+            Node valueNode = tuple.getValueNode();
             Object key = constructObject(keyNode);
             if (key != null) {
                 try {
                     key.hashCode();// check circular dependencies
                 } catch (Exception e) {
                     throw new ConstructorException("while constructing a mapping", node
-                            .getStartMark(), "found unacceptable key " + key, tuple[0]
+                            .getStartMark(), "found unacceptable key " + key, tuple.getKeyNode()
                             .getStartMark(), e);
                 }
             }
@@ -203,16 +204,16 @@
     }
 
     protected void constructSet2ndStep(MappingNode node, Set<Object> set) {
-        List<Node[]> nodeValue = (List<Node[]>) node.getValue();
-        for (Node[] tuple : nodeValue) {
-            Node keyNode = tuple[0];
+        List<NodeTuple> nodeValue = (List<NodeTuple>) node.getValue();
+        for (NodeTuple tuple : nodeValue) {
+            Node keyNode = tuple.getKeyNode();
             Object key = constructObject(keyNode);
             if (key != null) {
                 try {
                     key.hashCode();// check circular dependencies
                 } catch (Exception e) {
                     throw new ConstructorException("while constructing a Set", node.getStartMark(),
-                            "found unacceptable key " + key, tuple[0].getStartMark(), e);
+                            "found unacceptable key " + key, tuple.getKeyNode().getStartMark(), e);
                 }
             }
             if (keyNode.isTwoStepsConstruction()) {
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
index 0359b59..e561066 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/Constructor.java
@@ -24,6 +24,7 @@
 import org.yaml.snakeyaml.introspector.Property;
 import org.yaml.snakeyaml.nodes.MappingNode;
 import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.NodeTuple;
 import org.yaml.snakeyaml.nodes.ScalarNode;
 import org.yaml.snakeyaml.nodes.SequenceNode;
 
@@ -338,15 +339,16 @@
     @SuppressWarnings("unchecked")
     private Object constructJavaBeanNode2ndStep(MappingNode node, Object object) {
         Class<? extends Object> beanType = node.getType();
-        List<Node[]> nodeValue = (List<Node[]>) node.getValue();
-        for (Node[] tuple : nodeValue) {
+        List<NodeTuple> nodeValue = (List<NodeTuple>) node.getValue();
+        for (NodeTuple tuple : nodeValue) {
             ScalarNode keyNode;
-            if (tuple[0] instanceof ScalarNode) {
-                keyNode = (ScalarNode) tuple[0];// key must be scalar
+            if (tuple.getKeyNode() instanceof ScalarNode) {
+                // key must be scalar
+                keyNode = (ScalarNode) tuple.getKeyNode();
             } else {
-                throw new YAMLException("Keys must be scalars but found: " + tuple[0]);
+                throw new YAMLException("Keys must be scalars but found: " + tuple.getKeyNode());
             }
-            Node valueNode = tuple[1];
+            Node valueNode = tuple.getValueNode();
             // keys can only be Strings
             keyNode.setType(String.class);
             String key = (String) constructObject(keyNode);
diff --git a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
index 6b22f2c..35d4926 100644
--- a/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
+++ b/src/main/java/org/yaml/snakeyaml/constructor/SafeConstructor.java
@@ -19,6 +19,7 @@
 import org.yaml.snakeyaml.error.YAMLException;

 import org.yaml.snakeyaml.nodes.MappingNode;

 import org.yaml.snakeyaml.nodes.Node;

+import org.yaml.snakeyaml.nodes.NodeTuple;

 import org.yaml.snakeyaml.nodes.ScalarNode;

 import org.yaml.snakeyaml.nodes.SequenceNode;

 import org.yaml.snakeyaml.util.Base64Coder;

@@ -47,12 +48,12 @@
     }

 

     private void flattenMapping(MappingNode node) {

-        List<Node[]> merge = new LinkedList<Node[]>();

+        List<NodeTuple> merge = new LinkedList<NodeTuple>();

         int index = 0;

-        List<Node[]> nodeValue = (List<Node[]>) node.getValue();

+        List<NodeTuple> nodeValue = (List<NodeTuple>) node.getValue();

         while (index < nodeValue.size()) {

-            Node keyNode = nodeValue.get(index)[0];

-            Node valueNode = nodeValue.get(index)[1];

+            Node keyNode = nodeValue.get(index).getKeyNode();

+            Node valueNode = nodeValue.get(index).getValueNode();

             if (keyNode.getTag().equals("tag:yaml.org,2002:merge")) {

                 nodeValue.remove(index);

                 switch (valueNode.getNodeId()) {

@@ -62,7 +63,7 @@
                     merge.addAll(mn.getValue());

                     break;

                 case sequence:

-                    List<List<Node[]>> submerge = new LinkedList<List<Node[]>>();

+                    List<List<NodeTuple>> submerge = new LinkedList<List<NodeTuple>>();

                     SequenceNode sn = (SequenceNode) valueNode;

                     List<Node> vals = sn.getValue();

                     for (Node subnode : vals) {

@@ -76,7 +77,7 @@
                         submerge.add(mnode.getValue());

                     }

                     Collections.reverse(submerge);

-                    for (List<Node[]> value : submerge) {

+                    for (List<NodeTuple> value : submerge) {

                         merge.addAll(value);

                     }

                     break;

@@ -327,8 +328,8 @@
                             .getStartMark(), "expected a single mapping item, but found "

                             + mnode.getValue().size() + " items", mnode.getStartMark());

                 }

-                Node keyNode = mnode.getValue().get(0)[0];

-                Node valueNode = mnode.getValue().get(0)[1];

+                Node keyNode = mnode.getValue().get(0).getKeyNode();

+                Node valueNode = mnode.getValue().get(0).getValueNode();

                 Object key = constructObject(keyNode);

                 Object value = constructObject(valueNode);

                 omap.put(key, value);

@@ -360,8 +361,8 @@
                             "expected a single mapping item, but found " + mnode.getValue().size()

                                     + " items", mnode.getStartMark());

                 }

-                Node keyNode = mnode.getValue().get(0)[0];

-                Node valueNode = mnode.getValue().get(0)[1];

+                Node keyNode = mnode.getValue().get(0).getKeyNode();

+                Node valueNode = mnode.getValue().get(0).getValueNode();

                 Object key = constructObject(keyNode);

                 Object value = constructObject(valueNode);

                 pairs.add(new Object[] { key, value });

diff --git a/src/main/java/org/yaml/snakeyaml/nodes/MappingNode.java b/src/main/java/org/yaml/snakeyaml/nodes/MappingNode.java
index 9304b42..1e5a6b5 100644
--- a/src/main/java/org/yaml/snakeyaml/nodes/MappingNode.java
+++ b/src/main/java/org/yaml/snakeyaml/nodes/MappingNode.java
@@ -14,14 +14,14 @@
     private Class<? extends Object> keyType;
     private Class<? extends Object> valueType;
 
-    public MappingNode(String tag, List<Node[]> value, Mark startMark, Mark endMark,
+    public MappingNode(String tag, List<NodeTuple> value, Mark startMark, Mark endMark,
             Boolean flowStyle) {
         super(tag, value, startMark, endMark, flowStyle);
         keyType = Object.class;
         valueType = Object.class;
     }
 
-    public MappingNode(String tag, List<Node[]> value, Boolean flowStyle) {
+    public MappingNode(String tag, List<NodeTuple> value, Boolean flowStyle) {
         super(tag, value, null, null, flowStyle);
     }
 
@@ -32,17 +32,16 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    // TODO should we return Tuple instead of array ?
-    public List<Node[]> getValue() {
-        List<Node[]> mapping = (List<Node[]>) super.getValue();
-        for (Node[] nodes : mapping) {
-            nodes[0].setType(keyType);
-            nodes[1].setType(valueType);
+    public List<NodeTuple> getValue() {
+        List<NodeTuple> mapping = (List<NodeTuple>) super.getValue();
+        for (NodeTuple nodes : mapping) {
+            nodes.getKeyNode().setType(keyType);
+            nodes.getValueNode().setType(valueType);
         }
         return mapping;
     }
 
-    public void setValue(List<Node[]> merge) {
+    public void setValue(List<NodeTuple> merge) {
         value = merge;
     }
 
@@ -58,12 +57,12 @@
     public String toString() {
         String values;
         StringBuffer buf = new StringBuffer();
-        for (Node[] node : getValue()) {
+        for (NodeTuple node : getValue()) {
             buf.append("{ key=");
-            buf.append(node[0]);
+            buf.append(node.getKeyNode());
             buf.append("; value=Node<");
             // to avoid overflow in case of recursive structures
-            buf.append(System.identityHashCode(node[1]));
+            buf.append(System.identityHashCode(node.getValueNode()));
             buf.append("> }");
         }
         values = buf.toString();
diff --git a/src/main/java/org/yaml/snakeyaml/nodes/NodeTuple.java b/src/main/java/org/yaml/snakeyaml/nodes/NodeTuple.java
new file mode 100644
index 0000000..4fcb03a
--- /dev/null
+++ b/src/main/java/org/yaml/snakeyaml/nodes/NodeTuple.java
@@ -0,0 +1,23 @@
+/*
+ * See LICENSE file in distribution for copyright and licensing information.
+ */
+package org.yaml.snakeyaml.nodes;
+
+public class NodeTuple {
+
+    private final Node keyNode;
+    private final Node valueNode;
+
+    public NodeTuple(Node keyNode, Node valueNode) {
+        this.keyNode = keyNode;
+        this.valueNode = valueNode;
+    }
+
+    public Node getKeyNode() {
+        return keyNode;
+    }
+
+    public Node getValueNode() {
+        return valueNode;
+    }
+}
diff --git a/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java b/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java
index 278d5e3..8297e4e 100644
--- a/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/BaseRepresenter.java
@@ -17,6 +17,7 @@
 import org.yaml.snakeyaml.error.YAMLException;

 import org.yaml.snakeyaml.nodes.MappingNode;

 import org.yaml.snakeyaml.nodes.Node;

+import org.yaml.snakeyaml.nodes.NodeTuple;

 import org.yaml.snakeyaml.nodes.ScalarNode;

 import org.yaml.snakeyaml.nodes.SequenceNode;

 import org.yaml.snakeyaml.serializer.Serializer;

@@ -140,7 +141,7 @@
 

     protected Node representMapping(String tag, Map<? extends Object, Object> mapping,

             Boolean flowStyle) {

-        List<Node[]> value = new LinkedList<Node[]>();

+        List<NodeTuple> value = new LinkedList<NodeTuple>();

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

         representedObjects.put(objectToRepresent, node);

         isRoot = false;

@@ -155,7 +156,7 @@
             if (!((nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null))) {

                 bestStyle = false;

             }

-            value.add(new Node[] { nodeKey, nodeValue });

+            value.add(new NodeTuple(nodeKey, nodeValue));

         }

         if (flowStyle == null) {

             if (defaultFlowStyle != null) {

diff --git a/src/main/java/org/yaml/snakeyaml/representer/Representer.java b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
index 6147803..123a886 100644
--- a/src/main/java/org/yaml/snakeyaml/representer/Representer.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
@@ -22,6 +22,7 @@
 import org.yaml.snakeyaml.introspector.Property;
 import org.yaml.snakeyaml.nodes.MappingNode;
 import org.yaml.snakeyaml.nodes.Node;
+import org.yaml.snakeyaml.nodes.NodeTuple;
 import org.yaml.snakeyaml.nodes.ScalarNode;
 
 /**
@@ -71,7 +72,7 @@
     }
 
     private Node representJavaBean(Set<Property> properties, Object javaBean) {
-        List<Node[]> value = new LinkedList<Node[]>();
+        List<NodeTuple> value = new LinkedList<NodeTuple>();
         String tag;
         String customTag = classTags.get(javaBean.getClass());
         if (customTag == null) {
@@ -110,7 +111,7 @@
             if (!((nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null))) {
                 bestStyle = false;
             }
-            value.add(new Node[] { nodeKey, nodeValue });
+            value.add(new NodeTuple(nodeKey, nodeValue));
         }
         if (defaultFlowStyle != null) {
             node.setFlowStyle(defaultFlowStyle);
diff --git a/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java b/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java
index 0468d00..1edf4f9 100644
--- a/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java
+++ b/src/main/java/org/yaml/snakeyaml/serializer/Serializer.java
@@ -24,8 +24,10 @@
 import org.yaml.snakeyaml.events.StreamEndEvent;
 import org.yaml.snakeyaml.events.StreamStartEvent;
 import org.yaml.snakeyaml.nodes.CollectionNode;
+import org.yaml.snakeyaml.nodes.MappingNode;
 import org.yaml.snakeyaml.nodes.Node;
 import org.yaml.snakeyaml.nodes.NodeId;
+import org.yaml.snakeyaml.nodes.NodeTuple;
 import org.yaml.snakeyaml.nodes.ScalarNode;
 import org.yaml.snakeyaml.resolver.Resolver;
 
@@ -118,10 +120,11 @@
                 }
                 break;
             case mapping:
-                List<Object[]> map = (List<Object[]>) node.getValue();
-                for (Object[] object : map) {
-                    Node key = (Node) object[0];
-                    Node value = (Node) object[1];
+                MappingNode mnode = (MappingNode) node;
+                List<NodeTuple> map = mnode.getValue();
+                for (NodeTuple object : map) {
+                    Node key = object.getKeyNode();
+                    Node value = object.getValueNode();
                     anchorNode(key);
                     anchorNode(value);
                 }
@@ -177,12 +180,13 @@
                 boolean implicitM = (node.getTag().equals(implicitTag));
                 this.emitter.emit(new MappingStartEvent(tAlias, node.getTag(), implicitM, null,
                         null, ((CollectionNode) node).getFlowStyle()));
-                List<Object[]> map = (List<Object[]>) node.getValue();
-                for (Object[] row : map) {
-                    Node key = (Node) row[0];
-                    Node value = (Node) row[1];
-                    serializeNode(key, node, null);
-                    serializeNode(value, node, key);
+                MappingNode mnode = (MappingNode) node;
+                List<NodeTuple> map = mnode.getValue();
+                for (NodeTuple row : map) {
+                    Node key = row.getKeyNode();
+                    Node value = row.getValueNode();
+                    serializeNode(key, mnode, null);
+                    serializeNode(value, mnode, key);
                 }
                 this.emitter.emit(new MappingEndEvent(null, null));
             }
diff --git a/src/test/java/org/pyyaml/PyStructureTest.java b/src/test/java/org/pyyaml/PyStructureTest.java
index 719a712..eaf12f3 100644
--- a/src/test/java/org/pyyaml/PyStructureTest.java
+++ b/src/test/java/org/pyyaml/PyStructureTest.java
@@ -22,6 +22,7 @@
 import org.yaml.snakeyaml.events.ScalarEvent;

 import org.yaml.snakeyaml.nodes.MappingNode;

 import org.yaml.snakeyaml.nodes.Node;

+import org.yaml.snakeyaml.nodes.NodeTuple;

 import org.yaml.snakeyaml.nodes.ScalarNode;

 import org.yaml.snakeyaml.nodes.SequenceNode;

 import org.yaml.snakeyaml.parser.ParserImpl;

@@ -130,11 +131,11 @@
                 MappingNode seq2 = (MappingNode) node2;

                 assertEquals(seq1.getTag(), seq2.getTag());

                 assertEquals(seq1.getValue().size(), seq2.getValue().size());

-                Iterator<Node[]> iter2 = seq2.getValue().iterator();

-                for (Node[] child1 : seq1.getValue()) {

-                    Node[] child2 = iter2.next();

-                    compareNodes(child1[0], child2[0]);// keys

-                    compareNodes(child1[1], child2[1]);// values

+                Iterator<NodeTuple> iter2 = seq2.getValue().iterator();

+                for (NodeTuple child1 : seq1.getValue()) {

+                    NodeTuple child2 = iter2.next();

+                    compareNodes(child1.getKeyNode(), child2.getKeyNode());

+                    compareNodes(child1.getValueNode(), child2.getValueNode());

                 }

             }

         }

diff --git a/src/test/java/org/yaml/snakeyaml/LoaderTest.java b/src/test/java/org/yaml/snakeyaml/LoaderTest.java
index 052350c..40b732b 100644
--- a/src/test/java/org/yaml/snakeyaml/LoaderTest.java
+++ b/src/test/java/org/yaml/snakeyaml/LoaderTest.java
@@ -9,6 +9,7 @@
 import org.yaml.snakeyaml.nodes.MappingNode;

 import org.yaml.snakeyaml.nodes.Node;

 import org.yaml.snakeyaml.nodes.NodeId;

+import org.yaml.snakeyaml.nodes.NodeTuple;

 import org.yaml.snakeyaml.nodes.ScalarNode;

 import org.yaml.snakeyaml.resolver.Resolver;

 

@@ -19,14 +20,14 @@
         loader.setResolver(new Resolver());

         String yaml = "abc: 3";

         MappingNode node = (MappingNode) loader.compose(new StringReader(yaml));

-        List<Node[]> nodes = node.getValue();

+        List<NodeTuple> nodes = node.getValue();

         assertEquals(1, nodes.size());

-        Node[] pairs = nodes.get(0);

-        ScalarNode key = (ScalarNode) pairs[0];

+        NodeTuple pairs = nodes.get(0);

+        ScalarNode key = (ScalarNode) pairs.getKeyNode();

         assertEquals("tag:yaml.org,2002:str", key.getTag());

         assertEquals("abc", key.getValue());

         //

-        ScalarNode value = (ScalarNode) pairs[1];

+        ScalarNode value = (ScalarNode) pairs.getValueNode();

         assertEquals("tag:yaml.org,2002:int", value.getTag());

         assertEquals("3", value.getValue());

         //

diff --git a/src/test/java/org/yaml/snakeyaml/YamlComposeTest.java b/src/test/java/org/yaml/snakeyaml/YamlComposeTest.java
index 8ca2632..e59d3c4 100644
--- a/src/test/java/org/yaml/snakeyaml/YamlComposeTest.java
+++ b/src/test/java/org/yaml/snakeyaml/YamlComposeTest.java
@@ -27,8 +27,8 @@
     public void testComposeFromReader() {

         Yaml yaml = new Yaml();

         MappingNode node = (MappingNode) yaml.compose(new StringReader("abc: 56"));

-        assertEquals("abc", node.getValue().get(0)[0].getValue());

-        assertEquals("56", node.getValue().get(0)[1].getValue());

+        assertEquals("abc", node.getValue().get(0).getKeyNode().getValue());

+        assertEquals("56", node.getValue().get(0).getValueNode().getValue());

     }

 

     public void testComposeAllFromReader() {