Index: trunk/test/unit/org/openstreetmap/josm/io/DiffResultProcessorTest.groovy
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/DiffResultProcessorTest.groovy	(revision 2605)
+++ trunk/test/unit/org/openstreetmap/josm/io/DiffResultProcessorTest.groovy	(revision 2605)
@@ -0,0 +1,196 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+
+import org.junit.Test 
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.coor.LatLon
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+
+import static org.junit.Assert.*;
+
+class DiffResultProcessorTest {
+	
+	
+	@Test
+	public void testConstructor() {
+		Node n = new Node(1)
+		// these calls should not fail 
+		//
+		def DiffResultProcessor processor  = new DiffResultProcessor(null)
+		processor  = new DiffResultProcessor([])
+		processor  = new DiffResultProcessor([n])
+	}
+	
+	@Test
+	public void testParse_NOK_Cases() {
+		def DiffResultProcessor processor  = new DiffResultProcessor([])
+		
+		final shouldFail = new GroovyTestCase().&shouldFail
+		
+		shouldFail(IllegalArgumentException) {
+		    processor.parse null, NullProgressMonitor.INSTANCE
+		}
+		
+		shouldFail(OsmDataParsingException) {
+			processor.parse "", NullProgressMonitor.INSTANCE
+		}
+		
+		shouldFail(OsmDataParsingException) {
+			processor.parse "<x></x>", NullProgressMonitor.INSTANCE
+		}		
+	}
+	
+	@Test 
+	public void testParse_OK_Cases() {
+		def DiffResultProcessor processor  = new DiffResultProcessor([])
+		String doc = """\
+		<diffResult version="0.6" generator="Test Data">
+		    <node old_id="-1" new_id="1" new_version="1"/>
+		    <way old_id="-2" new_id="2" new_version="1"/>
+		    <relation old_id="-3" new_id="3" new_version="1"/>
+		</diffResult>
+		"""
+		
+		processor.parse doc, null
+		assert processor.@diffResults.size() == 3
+		SimplePrimitiveId id = new SimplePrimitiveId(-1, OsmPrimitiveType.NODE)
+		def entry = processor.@diffResults[id]
+		assert entry != null
+		assert entry.new_id == 1
+		assert entry.new_version == 1
+		
+		id = new SimplePrimitiveId(-2, OsmPrimitiveType.WAY)
+		entry = processor.@diffResults[id]
+		assert entry != null
+		assert entry.new_id == 2
+		assert entry.new_version == 1
+		
+		id = new SimplePrimitiveId(-3, OsmPrimitiveType.RELATION)
+		entry = processor.@diffResults[id]
+		assert entry != null
+		assert entry.new_id == 3
+		assert entry.new_version == 1		
+	}
+	
+	@Test
+	public void testPostProcess_Invocation_Variants() {
+		def DiffResultProcessor processor  = new DiffResultProcessor([])
+		String doc = """\
+        <diffResult version="0.6" generator="Test Data">
+            <node old_id="-1" new_id="1" new_version="1"/>
+            <way old_id="-2" new_id="2" new_version="1"/>
+            <relation old_id="-3" new_id="3" new_version="1"/>
+        </diffResult>
+        """
+		
+		processor.parse doc, null
+		
+		// should all be ok
+		//
+		processor.postProcess null, null
+		processor.postProcess null, NullProgressMonitor.INSTANCE
+		processor.postProcess new Changeset(1), null
+		processor.postProcess new Changeset(1), NullProgressMonitor.INSTANCE
+	}
+	
+	@Test
+	public void testPostProcess_OK() {
+		
+		Node n = new Node()
+		Way w = new Way()
+		Relation r = new Relation()
+		
+		String doc = """\
+	        <diffResult version="0.6" generator="Test Data">
+	            <node old_id="${n.uniqueId}" new_id="1" new_version="10"/>
+	            <way old_id="${w.uniqueId}" new_id="2" new_version="11"/>
+	            <relation old_id="${r.uniqueId}" new_id="3" new_version="12"/>
+	        </diffResult>
+	        """
+		
+		def DiffResultProcessor processor  = new DiffResultProcessor([n,w,r])
+		processor.parse doc, null
+		def processed = processor.postProcess(new Changeset(5), null)
+		assert processed.size() == 3
+		n = processed.find {it.uniqueId == 1}
+		assert n.changesetId == 5
+		assert n.version == 10
+		
+		w = processed.find {it.uniqueId == 2}
+		assert w.changesetId == 5
+		assert w.version == 11
+		
+		r = processed.find {it.uniqueId == 3}
+		assert r.changesetId == 5
+		assert r.version == 12		
+	}
+	
+	@Test
+	public void testPostProcess_ForCreatedElement() {
+		
+		Node n = new Node()		
+		String doc = """\
+            <diffResult version="0.6" generator="Test Data">
+                <node old_id="${n.uniqueId}" new_id="1" new_version="1"/>
+            </diffResult>
+            """
+		
+		def DiffResultProcessor processor  = new DiffResultProcessor([n])
+		processor.parse doc, null
+		def processed = processor.postProcess(new Changeset(5), null)
+		assert processed.size() == 1
+		n = processed.find {it.uniqueId == 1}
+		assert n.changesetId == 5
+		assert n.version == 1
+	}
+	
+	@Test
+	public void testPostProcess_ForModifiedElement() {
+		
+		Node n = new Node(1)
+		n.coor = new LatLon(1,1)
+		n.setOsmId 1, 2
+		n.modified = true
+		String doc = """\
+            <diffResult version="0.6" generator="Test Data">
+                <node old_id="${n.uniqueId}" new_id="${n.uniqueId}" new_version="3"/>
+            </diffResult>
+            """
+		
+		def DiffResultProcessor processor  = new DiffResultProcessor([n])
+		processor.parse doc, null
+		def processed = processor.postProcess(new Changeset(5), null)
+		assert processed.size() == 1
+		n = processed.find {it.uniqueId == 1}
+		assert n.changesetId == 5
+		assert n.version == 3
+	}
+	
+	@Test
+	public void testPostProcess_ForDeletedElement() {
+		
+		Node n = new Node(1)
+		n.coor = new LatLon(1,1)
+		n.setOsmId 1, 2
+		n.deleted = true
+		String doc = """\
+            <diffResult version="0.6" generator="Test Data">
+                <node old_id="${n.uniqueId}"/>
+            </diffResult>
+            """
+		
+		def DiffResultProcessor processor  = new DiffResultProcessor([n])
+		processor.parse doc, null
+		def processed = processor.postProcess(new Changeset(5), null)
+		assert processed.size() == 1
+		n = processed.find {it.uniqueId == 1}
+		assert n.changesetId == 5
+		assert n.version == 2
+	}
+}
Index: trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.groovy
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.groovy	(revision 2605)
+++ trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.groovy	(revision 2605)
@@ -0,0 +1,210 @@
+// License: GPL. For details, see LICENSE file.
+
+package org.openstreetmap.josm.io;
+
+import org.junit.Test 
+import org.openstreetmap.josm.data.osm.Changeset
+import org.openstreetmap.josm.data.osm.Node
+import org.openstreetmap.josm.data.coor.LatLon
+
+
+import static org.junit.Assert.*;
+
+class OsmChangeBuilderTest {
+	
+	/**
+	 * Test various constructor invocations 
+	 */
+	@Test
+	public void testConstructor() {
+		def Changeset cs = new Changeset(1)
+		// should not fail 
+		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
+		
+		// should not fail either - null allowed
+		builder = new OsmChangeBuilder(null)
+		
+		// should not fail 
+		builder = new OsmChangeBuilder(cs, "0.5")
+		
+		builder = new OsmChangeBuilder(cs, null)
+		
+		builder = new OsmChangeBuilder(null, null)		
+	}
+	
+	/**
+	 * Test the sequence of method calls. Should throw IllegalStateException if
+	 * the protocol start(),append()*, finish() is violated.
+	 */
+	@Test
+	public void testSequenceOfMethodCalls() {
+		def Changeset cs = new Changeset(1) 
+		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
+		
+		final shouldFail = new GroovyTestCase().&shouldFail
+				
+		// should be OK 
+		builder.start()
+		Node n = new Node(new LatLon(0,0))
+		builder.append n
+		builder.finish()
+		
+		shouldFail(IllegalStateException) {
+		    builder = new OsmChangeBuilder(cs)
+			builder.append n
+		}
+		
+		shouldFail(IllegalStateException) {
+			builder = new OsmChangeBuilder(cs)
+			builder.append([n])
+		}
+		
+		shouldFail(IllegalStateException) {
+		    builder = new OsmChangeBuilder(cs)
+			builder.finish()
+		}
+		
+		shouldFail(IllegalStateException) {
+			builder = new OsmChangeBuilder(cs)
+			builder.start()
+			builder.start()
+		}		
+	}
+	
+	@Test
+	public void testDocumentWithNewNode() {
+		def Changeset cs = new Changeset(1) 
+		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
+		Node n = new Node(new LatLon(0,0))
+		
+		builder.start()
+		builder.append n
+		builder.finish()
+		
+		def doc = new XmlParser().parseText(builder.document)
+		assert doc.@version == "0.6"
+		assert doc.@generator == "JOSM"
+		assert doc.name() == "osmChange"
+		assert doc.children().size() == 1
+		def create = doc.create
+		assert create != null
+		
+		assert create.size() == 1
+		def nodes = create[0].node
+		assert nodes.size() == 1
+		def node = nodes[0]
+		assert node.@id == n.uniqueId.toString()
+		assert node.@lat != null
+		assert node.@lon != null
+		assert node.@changeset == cs.id.toString()		
+	}	
+	
+    /**
+     * Test building a coument with a modified node 
+     */
+	@Test
+	public void testDocumentWithModifiedNode() {
+		def Changeset cs = new Changeset(1) 
+		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
+		Node n = new Node(1)
+		n.coor = new LatLon(0,0)
+		n.incomplete = false
+		n.modified = true
+		
+		builder.start()
+		builder.append n
+		builder.finish()
+		
+		def doc = new XmlParser().parseText(builder.document)
+		assert doc.@version == "0.6"
+		assert doc.@generator == "JOSM"
+		assert doc.name() == "osmChange"
+		assert doc.children().size() == 1
+		def modify = doc.modify
+		assert modify != null
+		
+		assert modify.size() == 1
+		def nodes = modify[0].node
+		assert nodes.size() == 1
+		def node = nodes[0]
+		assert node.@id == n.uniqueId.toString()
+		assert node.@lat != null
+		assert node.@lon != null
+		assert node.@changeset == cs.id.toString()      
+	}   
+	
+	/**
+	 * Test building a document with a deleted node 
+	 */
+	@Test
+	public void testDocumentWithDeletedNode() {
+		def Changeset cs = new Changeset(1) 
+		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
+		Node n = new Node(1)
+		n.coor = new LatLon(0,0)
+		n.incomplete = false
+		n.deleted = true
+		
+		builder.start()
+		builder.append n
+		builder.finish()
+		
+		def doc = new XmlParser().parseText(builder.document)
+		assert doc.@version == "0.6"
+		assert doc.@generator == "JOSM"
+		assert doc.name() == "osmChange"
+		assert doc.children().size() == 1
+		def delete = doc.delete
+		assert delete != null
+		
+		assert delete.size() == 1
+		def nodes = delete[0].node
+		assert nodes.size() == 1
+		def node = nodes[0]
+		assert node.@id == n.uniqueId.toString()
+		assert node.@lat != null
+		assert node.@lon != null
+		assert node.@changeset == cs.id.toString()      
+	}
+	
+	/**
+	 * Test building a mixed document. 
+	 *  
+	 */
+	@Test
+	public void testMixed() {
+		def Changeset cs = new Changeset(1) 
+		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
+		Node n1 = new Node(1)
+		n1.coor = new LatLon(0,0)
+		n1.incomplete = false
+		n1.deleted = true
+		
+		Node n2 = new Node(new LatLon(0,0))
+		
+		Node n3 = new Node(2)
+		n3.coor = new LatLon(0,0)
+		n3.incomplete = false
+		n3.modified = true
+		
+		builder.start()
+		builder.append([n1,n2,n3])
+		builder.finish()
+  
+		def doc = new XmlParser().parseText(builder.document)
+		
+		assert doc.children().size() == 3
+		assert doc.children()[0].name() == "delete"
+		assert doc.children()[1].name() == "create"
+		assert doc.children()[2].name() == "modify"
+		
+		def node = doc.children()[0].node[0]
+		assert node.@id == n1.uniqueId.toString()
+		
+		node = doc.children()[1].node[0]
+		assert node.@id == n2.uniqueId.toString()
+		
+		node = doc.children()[2].node[0]
+		assert node.@id == n3.uniqueId.toString()		
+	}
+}
Index: trunk/test/unit/org/openstreetmap/josm/io/ParseWithChangesetReaderTest.groovy
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/ParseWithChangesetReaderTest.groovy	(revision 2605)
+++ trunk/test/unit/org/openstreetmap/josm/io/ParseWithChangesetReaderTest.groovy	(revision 2605)
@@ -0,0 +1,212 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import org.junit.Test 
+
+import org.openstreetmap.josm.data.osm.Node
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType
+import org.openstreetmap.josm.data.osm.DataSet
+
+import static org.junit.Assert.*;
+
+class ParseWithChangesetReaderTest {
+	
+	/**
+	 * A new node with a changeset id. Ignore it.
+	 */
+	@Test
+	public void test_1() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="-1" lat="0.0" lon="0.0" changeset="1"/>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.getPrimitiveById(-1, OsmPrimitiveType.NODE)
+		assert n != null
+		assert n.uniqueId == -1
+		assert n.changesetId == 0
+	}
+	
+	/**
+	 * A new node with an invalid changeset id. Ignore it.
+	 */
+	@Test
+	public void test_11() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="-1" lat="0.0" lon="0.0" changeset="0">
+		    <tag k="external-id" v="-1"/>
+		</node>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.nodes.find {it.get("external-id") == "-1"}
+		assert n != null
+		assert n.changesetId == 0
+	}
+	
+	/**
+	 * A new node with an invalid changeset id. Ignore it.
+	 */
+	@Test
+	public void test_12() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="-1" lat="0.0" lon="0.0" changeset="-1">
+		    <tag k="external-id" v="-1"/>
+        </node>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.nodes.find {it.get("external-id") == "-1"}
+		assert n != null
+		assert n.changesetId == 0
+	}
+	
+	/**
+	 * A new node with an invalid changeset id. Ignore it.
+	 */
+	@Test
+	public void test_13() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="-1" lat="0.0" lon="0.0" changeset="aaa">
+		    <tag k="external-id" v="-1"/>
+        </node>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.nodes.find {it.get("external-id") == "-1"}
+		assert n != null
+		assert n.changesetId == 0
+	}
+	
+	/**
+	 * A new node with a missing changeset id. That's fine. The changeset id
+	 * is reset to 0.
+	 */
+	@Test
+	public void test_14() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="-1" lat="0.0" lon="0.0" >
+		    <tag k="external-id" v="-1"/>
+        </node>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.nodes.find {it.get("external-id") == "-1"}
+		assert n != null
+		assert n.changesetId == 0
+	}
+	
+	
+	/**
+	 * An existing node with a missing changeset id. That's fine. The changeset id
+	 * is reset to 0.
+	 */
+	@Test
+	public void test_2() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="1" lat="0.0" lon="0.0" version="1"/>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.getPrimitiveById(1, OsmPrimitiveType.NODE)
+		assert n != null
+		assert n.uniqueId == 1
+		assert n.changesetId == 0
+	}
+	
+	/**
+     * An existing node with a valid changeset id id. That's fine. The changeset id
+     * is applied.
+     */
+	@Test
+	public void test_3() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="1" lat="0.0" lon="0.0" version="1" changeset="4"/>
+        </osm>
+        """
+		
+		OsmReader reader = new OsmReader()
+		DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		Node n = ds.getPrimitiveById(1, OsmPrimitiveType.NODE)
+		assert n != null
+		assert n.uniqueId == 1
+		assert n.changesetId == 4
+	}
+	
+	/**
+	 * An existing node with an invalid changeset id. That's a problem. An exception
+	 * is thrown.
+	 */
+	@Test
+	public void test_4() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="1" lat="0.0" lon="0.0" version="1" changeset="-1"/>
+        </osm>
+        """
+		
+		final shouldFail = new GroovyTestCase().&shouldFail
+		
+		OsmReader reader = new OsmReader()
+		shouldFail(IllegalDataException) {
+		    DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		}
+	}	
+	/**
+	 * An existing node with an invalid changeset id. That's a problem. An exception
+	 * is thrown.
+	 */
+	@Test
+	public void test_5() {
+		String doc = """\
+         <osm version="0.6">
+        <node id="1" lat="0.0" lon="0.0" version="1" changeset="0"/>
+        </osm>
+        """
+		
+		final shouldFail = new GroovyTestCase().&shouldFail
+		
+		OsmReader reader = new OsmReader()
+		shouldFail(IllegalDataException) {
+			DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		}
+	}   
+	/**
+	 * An existing node with an invalid changeset id. That's a problem. An exception
+	 * is thrown.
+	 */
+	@Test
+	public void test_6() {
+		String doc = """\
+	         <osm version="0.6">
+	        <node id="1" lat="0.0" lon="0.0" version="1" changeset="abc"/>
+	        </osm>
+	        """
+		
+		final shouldFail = new GroovyTestCase().&shouldFail
+		
+		OsmReader reader = new OsmReader()
+		shouldFail(IllegalDataException) {
+			DataSet ds = reader.parseDataSet(new StringBufferInputStream(doc), null)
+		}
+	}   
+}
