Index: trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.groovy
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.groovy	(revision 14046)
+++ 	(revision )
@@ -1,206 +1,0 @@
-package org.openstreetmap.josm.io;
-
-import static groovy.test.GroovyAssert.shouldFail
-import static org.junit.Assert.*
-
-import org.junit.Test
-import org.openstreetmap.josm.data.coor.LatLon
-import org.openstreetmap.josm.data.osm.Changeset
-import org.openstreetmap.josm.data.osm.Node
-
-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)
-
-        // should be OK
-        builder.start()
-        Node n = new Node(LatLon.ZERO)
-        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(LatLon.ZERO)
-
-        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 document 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 = LatLon.ZERO
-        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 = LatLon.ZERO
-        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 = LatLon.ZERO
-        n1.incomplete = false
-        n1.deleted = true
-
-        Node n2 = new Node(LatLon.ZERO)
-
-        Node n3 = new Node(2)
-        n3.coor = LatLon.ZERO
-        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/OsmChangeBuilderTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.java	(revision 14047)
+++ trunk/test/unit/org/openstreetmap/josm/io/OsmChangeBuilderTest.java	(revision 14047)
@@ -0,0 +1,192 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.Logging;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Unit tests of {@link OsmChangeBuilder}
+ */
+public class OsmChangeBuilderTest {
+
+    /**
+     * Setup rule
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules();
+
+    private static void shouldFail(Runnable r) {
+        try {
+            r.run();
+            fail("should throw exception");
+        } catch (IllegalStateException e) {
+            Logging.trace(e);
+        }
+    }
+
+    /**
+     * Test various constructor invocations
+     */
+    @Test
+    public void testConstructor() {
+        Changeset cs = new Changeset(1);
+        // should not fail
+        new OsmChangeBuilder(cs);
+        new OsmChangeBuilder(null);
+        new OsmChangeBuilder(cs, "0.5");
+        new OsmChangeBuilder(cs, null);
+        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() {
+        Changeset cs = new Changeset(1);
+        OsmChangeBuilder csBuilder = new OsmChangeBuilder(cs);
+
+        // should be OK
+        csBuilder.start();
+        Node n = new Node(LatLon.ZERO);
+        csBuilder.append(n);
+        csBuilder.finish();
+
+        shouldFail(() -> {
+            OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+            builder.append(n);
+        });
+
+        shouldFail(() -> {
+            OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+            builder.append(Arrays.asList(n));
+        });
+
+        shouldFail(() -> {
+            OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+            builder.finish();
+        });
+
+        shouldFail(() -> {
+            OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+            builder.start();
+            builder.start();
+        });
+    }
+
+    /**
+     * Test building a document with a new node
+     */
+    @Test
+    public void testDocumentWithNewNode() {
+        Changeset cs = new Changeset(1);
+        OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+        Node n = new Node(LatLon.ZERO);
+
+        builder.start();
+        builder.append(n);
+        builder.finish();
+
+        assertEquals(String.format(
+                "<osmChange version=\"0.6\" generator=\"JOSM\">%n" +
+                "<create>%n" +
+                "  <node id='-6' changeset='1' lat='0.0' lon='0.0' />%n" +
+                "</create>%n" +
+                "</osmChange>%n"), builder.getDocument());
+    }
+
+    /**
+     * Test building a document with a modified node
+     */
+    @Test
+    public void testDocumentWithModifiedNode() {
+        Changeset cs = new Changeset(1);
+        OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+        Node n = new Node(LatLon.ZERO);
+        n.setOsmId(1, 1);
+        n.setModified(true);
+
+        builder.start();
+        builder.append(n);
+        builder.finish();
+
+        assertEquals(String.format(
+                "<osmChange version=\"0.6\" generator=\"JOSM\">%n" +
+                "<modify>%n" +
+                "  <node id='1' version='1' changeset='1' lat='0.0' lon='0.0' />%n" +
+                "</modify>%n" +
+                "</osmChange>%n"), builder.getDocument());
+    }
+
+    /**
+     * Test building a document with a deleted node
+     */
+    @Test
+    public void testDocumentWithDeletedNode() {
+        Changeset cs = new Changeset(1);
+        OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+        Node n = new Node(LatLon.ZERO);
+        n.setOsmId(1, 1);
+        n.setDeleted(true);
+
+        builder.start();
+        builder.append(n);
+        builder.finish();
+
+        assertEquals(String.format(
+                "<osmChange version=\"0.6\" generator=\"JOSM\">%n" +
+                "<delete>%n" +
+                "  <node id='1' version='1' changeset='1'/>%n" +
+                "</delete>%n" +
+                "</osmChange>%n"), builder.getDocument());
+    }
+
+    /**
+     * Test building a mixed document.
+     */
+    @Test
+    public void testMixed() {
+        Changeset cs = new Changeset(1);
+        OsmChangeBuilder builder = new OsmChangeBuilder(cs);
+        Node n1 = new Node(LatLon.ZERO);
+        n1.setOsmId(1, 1);
+        n1.setDeleted(true);
+
+        Node n2 = new Node(LatLon.ZERO);
+
+        Node n3 = new Node(LatLon.ZERO);
+        n3.setOsmId(2, 1);
+        n3.setModified(true);
+
+        builder.start();
+        builder.append(Arrays.asList(n1, n2, n3));
+        builder.finish();
+
+        assertEquals(String.format(
+                "<osmChange version=\"0.6\" generator=\"JOSM\">%n" +
+                "<delete>%n" +
+                "  <node id='1' version='1' changeset='1'/>%n" +
+                "</delete>%n" +
+                "<create>%n" +
+                "  <node id='-3' changeset='1' lat='0.0' lon='0.0' />%n" +
+                "</create>%n" +
+                "<modify>%n" +
+                "  <node id='2' version='1' changeset='1' lat='0.0' lon='0.0' />%n" +
+                "</modify>%n" +
+                "</osmChange>%n"), builder.getDocument());
+    }
+}
Index: trunk/test/unit/org/openstreetmap/josm/io/OsmChangesetContentParserTest.groovy
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmChangesetContentParserTest.groovy	(revision 14046)
+++ 	(revision )
@@ -1,215 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.io;
-
-import static groovy.test.GroovyAssert.shouldFail
-
-import java.nio.charset.StandardCharsets
-
-import org.junit.Test
-import org.openstreetmap.josm.data.osm.ChangesetDataSet
-import org.openstreetmap.josm.data.osm.OsmPrimitiveType
-import org.openstreetmap.josm.data.osm.SimplePrimitiveId
-import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType
-import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive
-import org.openstreetmap.josm.data.osm.history.HistoryRelation
-import org.openstreetmap.josm.data.osm.history.HistoryWay
-import org.openstreetmap.josm.gui.progress.NullProgressMonitor
-
-class OsmChangesetContentParserTest {
-
-    @Test
-    public void test_Constructor() {
-        OsmChangesetContentParser parser
-
-        // should be OK
-        parser = new OsmChangesetContentParser(new ByteArrayInputStream("".bytes))
-
-        shouldFail(IllegalArgumentException) {
-            parser = new OsmChangesetContentParser((String) null)
-        }
-
-        shouldFail(IllegalArgumentException) {
-            parser = new OsmChangesetContentParser((InputStream) null)
-        }
-    }
-
-
-    @Test
-    public void test_parse_arguments() {
-        OsmChangesetContentParser parser
-
-        def String doc = """
-            <osmChange version="0.6" generator="OpenStreetMap server">
-            </osmChange>
-        """
-
-        // should be OK
-        parser = new OsmChangesetContentParser(new ByteArrayInputStream(doc.getBytes(StandardCharsets.UTF_8)))
-        parser.parse null
-
-        // should be OK
-        parser = new OsmChangesetContentParser(new ByteArrayInputStream(doc.getBytes(StandardCharsets.UTF_8)))
-        parser.parse NullProgressMonitor.INSTANCE
-
-        // should be OK
-        parser = new OsmChangesetContentParser(doc)
-        parser.parse null
-    }
-
-    /**
-     * A simple changeset content document with one created node
-     *
-     */
-    @Test
-    public void test_OK_OneCreatedNode() {
-        OsmChangesetContentParser parser
-
-        def String doc = """
-            <osmChange version="0.6" generator="OpenStreetMap server">
-              <create>
-                <node id="1" version="1" visible="true" changeset="1" lat="1.0" lon="1.0" timestamp="2009-12-22" />
-              </create>
-            </osmChange>
-        """
-
-        // should be OK
-        parser = new OsmChangesetContentParser(doc)
-        ChangesetDataSet ds = parser.parse()
-
-        assert ds.size() == 1
-        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
-        assert p != null
-        assert p.getId() == 1
-        assert p.getVersion() == 1
-        assert p.getChangesetId() == 1
-        assert p.getTimestamp() != null
-        assert ds.getModificationType(p.getPrimitiveId()) == ChangesetModificationType.CREATED
-        assert ds.isCreated(p.getPrimitiveId())
-    }
-
-    /**
-     * A simple changeset content document with one updated node
-     *
-     */
-    @Test
-    public void test_OK_OneUpdatedNode() {
-        OsmChangesetContentParser parser
-
-        def String doc = """
-            <osmChange version="0.6" generator="OpenStreetMap server">
-              <modify>
-                <node id="1" version="1" visible="true" changeset="1" lat="1.0" lon="1.0" timestamp="2009-12-22" />
-              </modify>
-            </osmChange>
-        """
-
-        // should be OK
-        parser = new OsmChangesetContentParser(doc)
-        ChangesetDataSet ds = parser.parse()
-
-        assert ds.size() == 1
-        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
-        assert p != null
-        assert p.getId() == 1
-        assert p.getVersion() == 1
-        assert p.getChangesetId() == 1
-        assert p.getTimestamp() != null
-        assert ds.getModificationType(p.getPrimitiveId()) == ChangesetModificationType.UPDATED
-        assert ds.isUpdated(p.getPrimitiveId())
-    }
-
-    /**
-     * A simple changeset content document with one deleted node
-     *
-     */
-    @Test
-    public void test_OK_OneDeletedNode() {
-        OsmChangesetContentParser parser
-
-        def String doc = """
-            <osmChange version="0.6" generator="OpenStreetMap server">
-              <delete>
-                <node id="1" version="1" visible="true" changeset="1" lat="1.0" lon="1.0" timestamp="2009-12-22" />
-              </delete>
-            </osmChange>
-        """
-
-        // should be OK
-        parser = new OsmChangesetContentParser(doc)
-        ChangesetDataSet ds = parser.parse()
-
-        assert ds.size() == 1
-        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
-        assert p != null
-        assert p.getId() == 1
-        assert p.getVersion() == 1
-        assert p.getChangesetId() == 1
-        assert p.getTimestamp() != null
-        assert ds.getModificationType(p.getPrimitiveId()) == ChangesetModificationType.DELETED
-        assert ds.isDeleted(p.getPrimitiveId())
-    }
-
-    /**
-     * A more complex test with a document including nodes, ways, and relations.
-     *
-     */
-    @Test
-    public void test_OK_ComplexTestCase() {
-        OsmChangesetContentParser parser
-
-        def String doc = """
-            <osmChange version="0.6" generator="OpenStreetMap server">
-              <create>
-                <node id="1" version="1" visible="true" changeset="1" lat="1.0" lon="1.0" timestamp="2009-12-22">
-                  <tag k="a.key" v="a.value" />
-                </node>
-              </create>
-              <modify>
-               <way id="2" version="2" visible="true" changeset="1" timestamp="2009-12-22">
-                  <nd ref="21"/>
-                  <nd ref="22"/>
-               </way>
-             </modify>
-             <delete>
-                <relation id="3" version="3" visible="true" changeset="1" timestamp="2009-12-22" />
-              </delete>
-            </osmChange>
-        """
-
-        // should be OK
-        parser = new OsmChangesetContentParser(doc)
-        ChangesetDataSet ds = parser.parse()
-
-        assert ds.size() == 3
-
-        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
-        assert p != null
-        assert p.getId() == 1
-        assert p.getVersion() == 1
-        assert p.getChangesetId() == 1
-        assert p.getTimestamp() != null
-        assert ds.getModificationType(p.getPrimitiveId()) == ChangesetModificationType.CREATED
-        assert ds.isCreated(p.getPrimitiveId())
-        assert p.get("a.key") == "a.value"
-
-        HistoryWay w = (HistoryWay)ds.getPrimitive(new SimplePrimitiveId(2, OsmPrimitiveType.WAY));
-        assert w != null
-        assert w.getId() == 2
-        assert w.getVersion() == 2
-        assert w.getChangesetId() == 1
-        assert w.getTimestamp() != null
-        assert ds.getModificationType(w.getPrimitiveId()) == ChangesetModificationType.UPDATED
-        assert ds.isUpdated(w.getPrimitiveId())
-        assert w.getNumNodes() == 2
-        assert w.getNodes() == [21,22]
-
-        HistoryRelation r = (HistoryRelation)ds.getPrimitive(new SimplePrimitiveId(3, OsmPrimitiveType.RELATION));
-        assert r != null
-        assert r.getId() == 3
-        assert r.getVersion() == 3
-        assert r.getChangesetId() == 1
-        assert r.getTimestamp() != null
-        assert ds.getModificationType(r.getPrimitiveId()) == ChangesetModificationType.DELETED
-        assert ds.isDeleted(r.getPrimitiveId())
-    }
-}
Index: trunk/test/unit/org/openstreetmap/josm/io/OsmChangesetContentParserTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmChangesetContentParserTest.java	(revision 14047)
+++ trunk/test/unit/org/openstreetmap/josm/io/OsmChangesetContentParserTest.java	(revision 14047)
@@ -0,0 +1,244 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.osm.ChangesetDataSet;
+import org.openstreetmap.josm.data.osm.ChangesetDataSet.ChangesetModificationType;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
+import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
+import org.openstreetmap.josm.data.osm.history.HistoryRelation;
+import org.openstreetmap.josm.data.osm.history.HistoryWay;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.XmlParsingException;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Unit tests of {@link OsmChangesetContentParser}.
+ */
+public class OsmChangesetContentParserTest {
+
+    /**
+     * Setup rule
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules();
+
+    private static void shouldFail(Runnable r) {
+        try {
+            r.run();
+            fail("should throw exception");
+        } catch (IllegalArgumentException e) {
+            Logging.trace(e);
+        }
+    }
+
+    /**
+     * Test various constructor invocations
+     */
+    @Test
+    public void test_Constructor() {
+
+        // should be OK
+        new OsmChangesetContentParser(new ByteArrayInputStream("".getBytes()));
+
+        shouldFail(() -> {
+            new OsmChangesetContentParser((String) null);
+        });
+
+        shouldFail(() -> {
+            new OsmChangesetContentParser((InputStream) null);
+        });
+    }
+
+    /**
+     * Test various invocations of {@link OsmChangesetContentParser#parse}
+     * @throws XmlParsingException never
+     */
+    @Test
+    public void test_parse_arguments() throws XmlParsingException {
+        OsmChangesetContentParser parser;
+
+        String doc = "<osmChange version=\"0.6\" generator=\"OpenStreetMap server\"></osmChange>";
+
+        // should be OK
+        parser = new OsmChangesetContentParser(new ByteArrayInputStream(doc.getBytes(StandardCharsets.UTF_8)));
+        parser.parse(null);
+
+        // should be OK
+        parser = new OsmChangesetContentParser(new ByteArrayInputStream(doc.getBytes(StandardCharsets.UTF_8)));
+        parser.parse(NullProgressMonitor.INSTANCE);
+
+        // should be OK
+        parser = new OsmChangesetContentParser(doc);
+        parser.parse(null);
+    }
+
+    /**
+     * A simple changeset content document with one created node
+     * @throws XmlParsingException never
+     */
+    @Test
+    public void test_OK_OneCreatedNode() throws XmlParsingException {
+        OsmChangesetContentParser parser;
+
+        String doc =
+            "<osmChange version=\"0.6\" generator=\"OpenStreetMap server\">\n" +
+            "  <create>\n" +
+            "    <node id=\"1\" version=\"1\" visible=\"true\" changeset=\"1\" lat=\"1.0\" lon=\"1.0\" timestamp=\"2009-12-22\" />\n" +
+            "  </create>\n" +
+            "</osmChange>";
+
+        // should be OK
+        parser = new OsmChangesetContentParser(doc);
+        ChangesetDataSet ds = parser.parse();
+
+        assertEquals(1, ds.size());
+        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
+        assertNotNull(p);
+        assertEquals(1, p.getId());
+        assertEquals(1, p.getVersion());
+        assertEquals(1, p.getChangesetId());
+        assertNotNull(p.getTimestamp());
+        assertEquals(ChangesetModificationType.CREATED, ds.getModificationType(p.getPrimitiveId()));
+        assertTrue(ds.isCreated(p.getPrimitiveId()));
+    }
+
+    /**
+     * A simple changeset content document with one updated node
+     * @throws XmlParsingException never
+     */
+    @Test
+    public void test_OK_OneUpdatedNode() throws XmlParsingException {
+        OsmChangesetContentParser parser;
+
+        String doc =
+            "<osmChange version=\"0.6\" generator=\"OpenStreetMap server\">\n" +
+            "  <modify>\n" +
+            "    <node id=\"1\" version=\"1\" visible=\"true\" changeset=\"1\" lat=\"1.0\" lon=\"1.0\" timestamp=\"2009-12-22\" />\n" +
+            "  </modify>\n" +
+            "</osmChange>";
+
+        // should be OK
+        parser = new OsmChangesetContentParser(doc);
+        ChangesetDataSet ds = parser.parse();
+
+        assertEquals(1, ds.size());
+        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
+        assertNotNull(p);
+        assertEquals(1, p.getId());
+        assertEquals(1, p.getVersion());
+        assertEquals(1, p.getChangesetId());
+        assertNotNull(p.getTimestamp());
+        assertEquals(ChangesetModificationType.UPDATED, ds.getModificationType(p.getPrimitiveId()));
+        assertTrue(ds.isUpdated(p.getPrimitiveId()));
+    }
+
+    /**
+     * A simple changeset content document with one deleted node
+     * @throws XmlParsingException never
+     */
+    @Test
+    public void test_OK_OneDeletedNode() throws XmlParsingException {
+        OsmChangesetContentParser parser;
+
+        String doc =
+            "<osmChange version=\"0.6\" generator=\"OpenStreetMap server\">\n" +
+            "  <delete>\n" +
+            "    <node id=\"1\" version=\"1\" visible=\"true\" changeset=\"1\" lat=\"1.0\" lon=\"1.0\" timestamp=\"2009-12-22\" />\n" +
+            "  </delete>\n" +
+            "</osmChange>";
+
+        // should be OK
+        parser = new OsmChangesetContentParser(doc);
+        ChangesetDataSet ds = parser.parse();
+
+        assertEquals(1, ds.size());
+        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
+        assertNotNull(p);
+        assertEquals(1, p.getId());
+        assertEquals(1, p.getVersion());
+        assertEquals(1, p.getChangesetId());
+        assertNotNull(p.getTimestamp());
+        assertEquals(ChangesetModificationType.DELETED, ds.getModificationType(p.getPrimitiveId()));
+        assertTrue(ds.isDeleted(p.getPrimitiveId()));
+    }
+
+    /**
+     * A more complex test with a document including nodes, ways, and relations.
+     * @throws XmlParsingException never
+     */
+    @Test
+    public void test_OK_ComplexTestCase() throws XmlParsingException {
+        OsmChangesetContentParser parser;
+
+        String doc =
+            "<osmChange version=\"0.6\" generator=\"OpenStreetMap server\">\n" +
+            "  <create>\n" +
+            "    <node id=\"1\" version=\"1\" visible=\"true\" changeset=\"1\" lat=\"1.0\" lon=\"1.0\" timestamp=\"2009-12-22\">\n" +
+            "      <tag k=\"a.key\" v=\"a.value\" />\n" +
+            "    </node>\n" +
+            "  </create>\n" +
+            "  <modify>\n" +
+            "   <way id=\"2\" version=\"2\" visible=\"true\" changeset=\"1\" timestamp=\"2009-12-22\">\n" +
+            "      <nd ref=\"21\"/>\n" +
+            "      <nd ref=\"22\"/>\n" +
+            "   </way>\n" +
+            " </modify>\n" +
+            " <delete>\n" +
+            "    <relation id=\"3\" version=\"3\" visible=\"true\" changeset=\"1\" timestamp=\"2009-12-22\" />\n" +
+            "  </delete>\n" +
+            "</osmChange>";
+
+        // should be OK
+        parser = new OsmChangesetContentParser(doc);
+        ChangesetDataSet ds = parser.parse();
+
+        assertEquals(3, ds.size());
+
+        HistoryOsmPrimitive p = ds.getPrimitive(new SimplePrimitiveId(1, OsmPrimitiveType.NODE));
+        assertNotNull(p);
+        assertEquals(1, p.getId());
+        assertEquals(1, p.getVersion());
+        assertEquals(1, p.getChangesetId());
+        assertNotNull(p.getTimestamp());
+        assertEquals(ChangesetModificationType.CREATED, ds.getModificationType(p.getPrimitiveId()));
+        assertTrue(ds.isCreated(p.getPrimitiveId()));
+        assertEquals("a.value", p.get("a.key"));
+
+        HistoryWay w = (HistoryWay) ds.getPrimitive(new SimplePrimitiveId(2, OsmPrimitiveType.WAY));
+        assertNotNull(w);
+        assertEquals(2, w.getId());
+        assertEquals(2, w.getVersion());
+        assertEquals(1, w.getChangesetId());
+        assertNotNull(w.getTimestamp());
+        assertEquals(ChangesetModificationType.UPDATED, ds.getModificationType(w.getPrimitiveId()));
+        assertTrue(ds.isUpdated(w.getPrimitiveId()));
+        assertEquals(2, w.getNumNodes());
+        assertEquals(Arrays.asList(21L, 22L), w.getNodes());
+
+        HistoryRelation r = (HistoryRelation) ds.getPrimitive(new SimplePrimitiveId(3, OsmPrimitiveType.RELATION));
+        assertNotNull(r);
+        assertEquals(3, r.getId());
+        assertEquals(3, r.getVersion());
+        assertEquals(1, r.getChangesetId());
+        assertNotNull(r.getTimestamp());
+        assertEquals(ChangesetModificationType.DELETED, ds.getModificationType(r.getPrimitiveId()));
+        assertTrue(ds.isDeleted(r.getPrimitiveId()));
+    }
+}
