Index: trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java	(revision 1910)
@@ -6,4 +6,5 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedList;
@@ -134,12 +135,5 @@
 
             // build a way for the circle
-            Way wayToAdd;
-            if (existingWay == null) {
-                wayToAdd = new Way();
-            } else {
-                // re-use existing way if it was selected
-                wayToAdd = new Way(existingWay);
-                wayToAdd.nodes.clear();
-            }
+            List<Node> wayToAdd = new ArrayList<Node>();
 
             for (int i = 1; i <= numberOfNodesInCircle; i++) {
@@ -148,9 +142,9 @@
                 // insert existing nodes if they fit before this new node (999 means "already added this node")
                 if ((a1 < 999) && (a1 > a - 1E-9) && (a1 < a + 1E-9)) {
-                    wayToAdd.nodes.add(n1);
+                    wayToAdd.add(n1);
                     a1 = 999;
                 }
                 else if ((a2 < 999) && (a2 > a - 1E-9) && (a2 < a + 1E-9)) {
-                    wayToAdd.nodes.add(n2);
+                    wayToAdd.add(n2);
                     a2 = 999;
                 }
@@ -160,13 +154,17 @@
                     double y = yc + r*Math.sin(a);
                     Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
-                    wayToAdd.nodes.add(n);
+                    wayToAdd.add(n);
                     cmds.add(new AddCommand(n));
                 }
             }
-            wayToAdd.nodes.add(wayToAdd.nodes.get(0)); // close the circle
+            wayToAdd.add(wayToAdd.get(0)); // close the circle
             if (existingWay == null) {
-                cmds.add(new AddCommand(wayToAdd));
+                Way newWay = new Way();
+                newWay.setNodes(wayToAdd);
+                cmds.add(new AddCommand(newWay));
             } else {
-                cmds.add(new ChangeCommand(existingWay, wayToAdd));
+                Way newWay = new Way(existingWay);
+                newWay.setNodes(wayToAdd);
+                cmds.add(new ChangeCommand(existingWay, newWay));
             }
 
@@ -229,25 +227,18 @@
 
             // build a way for the circle
-            Way wayToAdd;
-            if (existingWay == null) {
-                wayToAdd = new Way();
-            } else {
-                // re-use existing way if it was selected
-                wayToAdd = new Way(existingWay);
-                wayToAdd.nodes.clear();
-            }
+            List<Node> wayToAdd = new ArrayList<Node>();
             for (int i = 1; i <= numberOfNodesInCircle; i++) {
                 double a = 2*Math.PI*(1.0 - i/(double)numberOfNodesInCircle); // "1-" to get it clock-wise
                 // insert existing nodes if they fit before this new node (999 means "already added this node")
                 if (a1 < 999 && a1 > a) {
-                    wayToAdd.nodes.add(n1);
+                    wayToAdd.add(n1);
                     a1 = 999;
                 }
                 if (a2 < 999 && a2 > a) {
-                    wayToAdd.nodes.add(n2);
+                    wayToAdd.add(n2);
                     a2 = 999;
                 }
                 if (a3 < 999 && a3 > a) {
-                    wayToAdd.nodes.add(n3);
+                    wayToAdd.add(n3);
                     a3 = 999;
                 }
@@ -256,12 +247,16 @@
                 double y = yc + r*Math.sin(a);
                 Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
-                wayToAdd.nodes.add(n);
+                wayToAdd.add(n);
                 cmds.add(new AddCommand(n));
             }
-            wayToAdd.nodes.add(wayToAdd.nodes.get(0)); // close the circle
+            wayToAdd.add(wayToAdd.get(0)); // close the circle
             if (existingWay == null) {
-                cmds.add(new AddCommand(wayToAdd));
+                Way newWay = new Way();
+                newWay.setNodes(wayToAdd);
+                cmds.add(new AddCommand(newWay));
             } else {
-                cmds.add(new ChangeCommand(existingWay, wayToAdd));
+                Way newWay = new Way(existingWay);
+                newWay.setNodes(wayToAdd);
+                cmds.add(new ChangeCommand(existingWay, newWay));
             }
 
Index: trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java	(revision 1910)
@@ -59,10 +59,12 @@
         for (Map.Entry<Way, List<Integer>> insertPoint : insertPoints.entrySet()) {
             Way w = insertPoint.getKey();
-            Way wnew = new Way(w);
+            List<Node> nodesToAdd = new ArrayList<Node>();
             List<Integer> is = insertPoint.getValue();
             pruneSuccsAndReverse(is);
             for (int i : is) {
-                wnew.nodes.add(i+1, node);
+                nodesToAdd.add(i+1, node);
             }
+            Way wnew = new Way(w);
+            wnew.setNodes(nodesToAdd);
             cmds.add(new ChangeCommand(w, wnew));
         }
Index: trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java	(revision 1910)
@@ -186,5 +186,7 @@
                 Way w = (Way)pair.getParent();
                 System.out.println(tr("removing reference from way {0}",w.id));
-                w.nodes.remove(primitive);
+                List<Node> wayNodes = w.getNodes();
+                wayNodes.remove(primitive);
+                w.setNodes(wayNodes);
                 // if a way ends up with less than two node we
                 // remember it on the "hive"
Index: trunk/src/org/openstreetmap/josm/command/WayNodesConflictResolverCommand.java
===================================================================
--- trunk/src/org/openstreetmap/josm/command/WayNodesConflictResolverCommand.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/command/WayNodesConflictResolverCommand.java	(revision 1910)
@@ -37,5 +37,5 @@
 
     /**
-     * 
+     *
      * @param my my may
      * @param their their way
@@ -68,12 +68,10 @@
         // nodes
         //
-        conflict.getMy().nodes.clear();
-        for (int i=0; i<mergedNodeList.size();i++) {
-            Node n = mergedNodeList.get(i);
-            conflict.getMy().nodes.add(n);
+        for (Node n:mergedNodeList) {
             if (! getLayer().data.nodes.contains(n)) {
                 logger.warning(tr("Main dataset does not include node {0}", n.toString()));
             }
         }
+        conflict.getMy().setNodes(mergedNodeList);
         rememberConflict(conflict);
         return true;
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 1910)
@@ -372,5 +372,5 @@
 
     protected void deleteWay(Way way) {
-        way.nodes.clear();
+        way.setNodes(null);
         way.delete(true);
     }
@@ -383,8 +383,10 @@
     public void unlinkNodeFromWays(Node node) {
         for (Way way: ways) {
-            if (way.nodes.contains(node)) {
-                way.nodes.remove(node);
-                if (way.nodes.size() < 2) {
+            List<Node> nodes = way.getNodes();
+            if (nodes.remove(node)) {
+                if (nodes.size() < 2) {
                     deleteWay(way);
+                } else {
+                    way.setNodes(nodes);
                 }
             }
Index: trunk/src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 1910)
@@ -24,5 +24,5 @@
     /**
      * All way nodes in this way
-     * 
+     *
      * @deprecated This public field will become private or protected in the future.
      *  Use the new public API instead.
@@ -43,10 +43,13 @@
 
     /**
-     * @param nodes
+     * @param nodes New way nodes. Can be null, in that case all way nodes are removed
      * @since 1862
      */
     public void setNodes(List<Node> nodes) {
         this.nodes.clear();
-        this.nodes.addAll(nodes);
+        if (nodes != null) {
+            this.nodes.addAll(nodes);
+        }
+        clearCached();
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitor.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitor.java	(revision 1910)
@@ -136,5 +136,5 @@
             return;
         Way clone = new Way(w);
-        clone.nodes.clear();
+        clone.setNodes(null);
         clone.incomplete = true;
         mappedPrimitives.put(w, clone);
Index: trunk/src/org/openstreetmap/josm/gui/SelectionManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/gui/SelectionManager.java	(revision 1910)
@@ -289,5 +289,5 @@
                         continue;
                 if (alt) {
-                    for (Node n : w.nodes) {
+                    for (Node n : w.getNodes()) {
                         if (!n.incomplete && r.contains(nc.getPoint(n))) {
                             selection.add(w);
@@ -297,5 +297,5 @@
                 } else {
                     boolean allIn = true;
-                    for (Node n : w.nodes) {
+                    for (Node n : w.getNodes()) {
                         if (!n.incomplete && !r.contains(nc.getPoint(n))) {
                             allIn = false;
Index: trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1910)
@@ -710,5 +710,5 @@
             for (GpxTrack trk : data.tracks) {
                 for (Collection<WayPoint> segment : trk.trackSegs) {
-                    Way w = new Way();
+                    List<Node> nodes = new ArrayList<Node>();
                     for (WayPoint p : segment) {
                         Node n = new Node(p.getCoor());
@@ -718,6 +718,8 @@
                         }
                         ds.nodes.add(n);
-                        w.nodes.add(n);
-                    }
+                        nodes.add(n);
+                    }
+                    Way w = new Way();
+                    w.setNodes(nodes);
                     ds.ways.add(w);
                 }
@@ -741,5 +743,5 @@
     /**
      * Action that issues a series of download requests to the API, following the GPX track.
-     * 
+     *
      * @author fred
      */
@@ -842,5 +844,5 @@
              * can only download rectangles, so the following is an attempt at finding a number of
              * rectangles to download.
-             * 
+             *
              * The idea is simply: Start out with the full bounding box. If it is too large, then
              * split it in half and repeat recursively for each half until you arrive at something
@@ -1141,5 +1143,5 @@
      * Makes a WayPoint at the projection of point P onto the track providing P is less than
      * tolerance away from the track
-     * 
+     *
      * @param P : the point to determine the projection for
      * @param tolerance : must be no further than this from the track
@@ -1151,21 +1153,21 @@
          * assume the coordinates of P are xp,yp, and those of a section of track between two
          * trackpoints are R=xr,yr and S=xs,ys. Let N be the projected point.
-         * 
+         *
          * The equation of RS is Ax + By + C = 0 where A = ys - yr B = xr - xs C = - Axr - Byr
-         * 
+         *
          * Also, note that the distance RS^2 is A^2 + B^2
-         * 
+         *
          * If RS^2 == 0.0 ignore the degenerate section of track
-         * 
+         *
          * PN^2 = (Axp + Byp + C)^2 / RS^2 that is the distance from P to the line
-         * 
+         *
          * so if PN^2 is less than PNmin^2 (initialized to tolerance) we can reject the line;
          * otherwise... determine if the projected poijnt lies within the bounds of the line: PR^2 -
          * PN^2 <= RS^2 and PS^2 - PN^2 <= RS^2
-         * 
+         *
          * where PR^2 = (xp - xr)^2 + (yp-yr)^2 and PS^2 = (xp - xs)^2 + (yp-ys)^2
-         * 
+         *
          * If so, calculate N as xn = xr + (RN/RS) B yn = y1 + (RN/RS) A
-         * 
+         *
          * where RN = sqrt(PR^2 - PN^2)
          */
Index: trunk/src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/gui/layer/RawGpsLayer.java	(revision 1910)
@@ -14,5 +14,7 @@
 import java.awt.event.ActionListener;
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 import javax.swing.AbstractAction;
@@ -73,10 +75,12 @@
             DataSet ds = new DataSet();
             for (Collection<GpsPoint> c : data) {
-                Way w = new Way();
+                List<Node> nodes = new ArrayList<Node>();
                 for (GpsPoint p : c) {
                     Node n = new Node(p.latlon);
                     ds.nodes.add(n);
-                    w.nodes.add(n);
-                }
+                    nodes.add(n);
+                }
+                Way w = new Way();
+                w.setNodes(nodes);
                 ds.ways.add(w);
             }
Index: trunk/src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmReader.java	(revision 1909)
+++ trunk/src/org/openstreetmap/josm/io/OsmReader.java	(revision 1910)
@@ -12,4 +12,5 @@
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -330,4 +331,5 @@
             Way w = new Way(e.getKey().id);
             boolean incomplete = false;
+            List<Node> wayNodes = new ArrayList<Node>();
             for (long id : e.getValue()) {
                 Node n = findNode(id);
@@ -337,8 +339,10 @@
                     incomplete = true;
                 }
-                w.nodes.add(n);
-            }
+                wayNodes.add(n);
+            }
+            w.setNodes(wayNodes);
             if (incomplete) {
-                logger.warning(tr("marked way {0} with {1} nodes incomplete because at least one node was missing in the loaded data and is therefore incomplete too", e.getKey().id, w.nodes.size()));
+                logger.warning(tr("marked way {0} with {1} nodes incomplete because at least one node was missing in the " +
+                		"loaded data and is therefore incomplete too", e.getKey().id, w.getNodesCount()));
                 e.getKey().copyTo(w);
                 w.incomplete = true;
