Index: /trunk/src/org/openstreetmap/josm/actions/AlignInCircleAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/AlignInCircleAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/AlignInCircleAction.java	(revision 1862)
@@ -113,9 +113,9 @@
             // distance between two nodes.
             if (nodes.size() > 0) {
-                if (nodes.size() == 1 && way.nodes.contains(nodes.get(0))) {
+                if (nodes.size() == 1 && way.getNodes().contains(nodes.get(0))) {
                     regular = true;
                 } else {
 
-                    center = nodes.get(way.nodes.contains(nodes.get(0)) ? 1 : 0).getEastNorth();
+                    center = nodes.get(way.getNodes().contains(nodes.get(0)) ? 1 : 0).getEastNorth();
                     if (nodes.size() == 2) {
                         radius = distance(nodes.get(0).getEastNorth(), nodes.get(1).getEastNorth());
@@ -125,5 +125,5 @@
             }
 
-            for (Node n : way.nodes) {
+            for (Node n : way.getNodes()) {
                 if (!nodes.contains(n)) {
                     nodes.add(n);
Index: /trunk/src/org/openstreetmap/josm/actions/AlignInLineAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/AlignInLineAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/AlignInLineAction.java	(revision 1862)
@@ -56,6 +56,6 @@
             for (OsmPrimitive osm : sel)
                 if (osm instanceof Way) {
-                    nodes.addAll(((Way)osm).nodes);
-                    itnodes.addAll(((Way)osm).nodes);
+                    nodes.addAll(((Way)osm).getNodes());
+                    itnodes.addAll(((Way)osm).getNodes());
                 }
         }
Index: /trunk/src/org/openstreetmap/josm/actions/ApiPreconditionChecker.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ApiPreconditionChecker.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/ApiPreconditionChecker.java	(revision 1862)
@@ -104,9 +104,9 @@
 
             if (osmPrimitive instanceof Way &&
-                    ((Way)osmPrimitive).nodes.size() > maxNodes) {
+                    ((Way)osmPrimitive).getNodesCount() > maxNodes) {
                 OptionPaneUtil.showMessageDialog(
                         Main.parent,
                         tr("{0} nodes in way {1} exceed the max. allowed number of nodes {2}",
-                                ((Way)osmPrimitive).nodes.size(),
+                                ((Way)osmPrimitive).getNodesCount(),
                                 Long.toString(osmPrimitive.id),
                                 maxNodes
Index: /trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java	(revision 1862)
@@ -144,9 +144,9 @@
         List<Node> nodeList = null;
         Object firstTry = actuallyCombineWays(selectedWays, false);
-        if (firstTry instanceof List) {
+        if (firstTry instanceof List<?>) {
             nodeList = (List<Node>) firstTry;
         } else {
             Object secondTry = actuallyCombineWays(selectedWays, true);
-            if (secondTry instanceof List) {
+            if (secondTry instanceof List<?>) {
                 int option = new ExtendedDialog(Main.parent,
                         tr("Change directions?"),
@@ -182,6 +182,5 @@
         Way newWay = new Way(modifyWay);
 
-        newWay.nodes.clear();
-        newWay.nodes.addAll(nodeList);
+        newWay.setNodes(nodeList);
 
         // display conflict dialog
Index: /trunk/src/org/openstreetmap/josm/actions/CopyAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CopyAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/CopyAction.java	(revision 1862)
@@ -81,7 +81,6 @@
                 Way wnew = new Way();
                 wnew.cloneFrom(w);
-                wnew.nodes.clear();
                 List<Node> nodes = new ArrayList<Node>();
-                for (Node n : w.nodes) {
+                for (Node n : w.getNodes()) {
                     if (! map.containsKey(n)) {
                         n.visit(this);
@@ -89,5 +88,5 @@
                     nodes.add((Node)map.get(n));
                 }
-                wnew.nodes.addAll(nodes);
+                wnew.setNodes(nodes);
                 pasteBuffer.addPrimitive(wnew);
             }
Index: /trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/CreateCircleAction.java	(revision 1862)
@@ -99,5 +99,5 @@
                 if (osm instanceof Way) {
                     existingWay = ((Way)osm);
-                    for (Node n : ((Way)osm).nodes)
+                    for (Node n : ((Way)osm).getNodes())
                     {
                         if(!nodes.contains(n)) {
Index: /trunk/src/org/openstreetmap/josm/actions/DistributeAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/DistributeAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/DistributeAction.java	(revision 1862)
@@ -54,6 +54,6 @@
             for (OsmPrimitive osm : sel)
                 if (osm instanceof Way) {
-                    nodes.addAll(((Way)osm).nodes);
-                    itnodes.addAll(((Way)osm).nodes);
+                    nodes.addAll(((Way)osm).getNodes());
+                    itnodes.addAll(((Way)osm).getNodes());
                 }
         }
Index: /trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java	(revision 1862)
@@ -50,6 +50,6 @@
             }
 
-            if (ws.way.nodes.get(ws.lowerIndex) != node
-                    && ws.way.nodes.get(ws.lowerIndex+1) != node) {
+            if (ws.way.getNode(ws.lowerIndex) != node
+                    && ws.way.getNode(ws.lowerIndex+1) != node) {
                 is.add(ws.lowerIndex);
             }
Index: /trunk/src/org/openstreetmap/josm/actions/MergeNodesAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/MergeNodesAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/MergeNodesAction.java	(revision 1862)
@@ -217,5 +217,5 @@
 
         for (Way w : getCurrentDataSet().ways) {
-            if (w.deleted || w.incomplete || w.nodes.size() < 1) {
+            if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
                 continue;
             }
@@ -225,5 +225,5 @@
                     continue;
                 }
-                if (w.nodes.contains(sn)) {
+                if (w.getNodes().contains(sn)) {
                     modify = true;
                 }
@@ -235,6 +235,5 @@
             ArrayList<Node> nn = new ArrayList<Node>();
             Node lastNode = null;
-            for (int i = 0; i < w.nodes.size(); i++) {
-                Node pushNode = w.nodes.get(i);
+            for (Node pushNode: w.getNodes()) {
                 if (allNodes.contains(pushNode)) {
                     pushNode = dest;
@@ -262,6 +261,5 @@
             } else {
                 Way newWay = new Way(w);
-                newWay.nodes.clear();
-                newWay.nodes.addAll(nn);
+                newWay.setNodes(nn);
                 cmds.add(new ChangeCommand(w, newWay));
             }
Index: /trunk/src/org/openstreetmap/josm/actions/MirrorAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/MirrorAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/MirrorAction.java	(revision 1862)
@@ -45,5 +45,5 @@
                 nodes.add((Node)osm);
             } else if (osm instanceof Way) {
-                nodes.addAll(((Way)osm).nodes);
+                nodes.addAll(((Way)osm).getNodes());
             }
         }
Index: /trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/OrthogonalizeAction.java	(revision 1862)
@@ -83,5 +83,5 @@
             // Check if every way is made of at least four segments and closed
             Way way = (Way)osm;
-            if ((way.nodes.size() < 5) || (!way.nodes.get(0).equals(way.nodes.get(way.nodes.size() - 1)))) {
+            if ((way.getNodesCount() < 5) || !way.isClosed()) {
                 OptionPaneUtil.showMessageDialog(
                         Main.parent,
Index: /trunk/src/org/openstreetmap/josm/actions/PasteAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/PasteAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/PasteAction.java	(revision 1862)
@@ -81,9 +81,8 @@
             /* make sure we reference the new nodes corresponding to the old ones */
             List<Node> nodes = new ArrayList<Node>();
-            for (Node n : w.nodes) {
+            for (Node n : w.getNodes()) {
                 nodes.add((Node)map.get(n));
             }
-            wnew.nodes.clear();
-            wnew.nodes.addAll(nodes);
+            wnew.setNodes(nodes);
             map.put(w, wnew);
         }
Index: /trunk/src/org/openstreetmap/josm/actions/ReverseWayAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ReverseWayAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/ReverseWayAction.java	(revision 1862)
@@ -9,4 +9,5 @@
 import java.util.Collections;
 import java.util.LinkedList;
+import java.util.List;
 
 import javax.swing.JOptionPane;
@@ -19,4 +20,5 @@
 import org.openstreetmap.josm.corrector.UserCancelException;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
@@ -58,5 +60,7 @@
         for (Way w : sel) {
             Way wnew = new Way(w);
-            Collections.reverse(wnew.nodes);
+            List<Node> nodesCopy = wnew.getNodes();
+            Collections.reverse(nodesCopy);
+            wnew.setNodes(nodesCopy);
             if (Main.pref.getBoolean("tag-correction.reverse-way", true)) {
                 try
Index: /trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java	(revision 1862)
@@ -106,11 +106,11 @@
                         continue;
                     }
-                    int last = w.nodes.size()-1;
+                    int last = w.getNodesCount()-1;
                     if(last <= 0) {
                         continue; // zero or one node ways
                     }
-                    Boolean circular = w.nodes.get(0).equals(w.nodes.get(last));
+                    boolean circular = w.isClosed();
                     int i = 0;
-                    for (Node wn : w.nodes) {
+                    for (Node wn : w.getNodes()) {
                         if ((circular || (i > 0 && i < last)) && n.equals(wn)) {
                             Integer old = wayOccurenceCounter.get(w);
@@ -159,5 +159,5 @@
 
             HashSet<Node> nds = new HashSet<Node>(selectedNodes);
-            for (Node n : selectedWay.nodes) {
+            for (Node n : selectedWay.getNodes()) {
                 nds.remove(n);
             }
@@ -211,5 +211,5 @@
         wayChunks.add(currentWayChunk);
 
-        Iterator<Node> it = selectedWay.nodes.iterator();
+        Iterator<Node> it = selectedWay.getNodes().iterator();
         while (it.hasNext()) {
             Node currentNode = it.next();
@@ -273,6 +273,5 @@
         // First, change the original way
         Way changedWay = new Way(selectedWay);
-        changedWay.nodes.clear();
-        changedWay.nodes.addAll(chunkIt.next());
+        changedWay.setNodes(chunkIt.next());
         commandList.add(new ChangeCommand(selectedWay, changedWay));
         newSelection.add(selectedWay);
Index: /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 1862)
@@ -67,8 +67,8 @@
             int count = 0;
             for (Way w : getCurrentDataSet().ways) {
-                if (w.deleted || w.incomplete || w.nodes.size() < 1) {
+                if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
                     continue;
                 }
-                if (!w.nodes.contains(selectedNode)) {
+                if (!w.getNodes().contains(selectedNode)) {
                     continue;
                 }
@@ -92,8 +92,8 @@
                 int count = 0;
                 for (Way w : getCurrentDataSet().ways) {
-                    if (w.deleted || w.incomplete || w.nodes.size() < 1) {
+                    if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
                         continue;
                     }
-                    if (!w.nodes.contains(n)) {
+                    if (!w.getNodes().contains(n)) {
                         continue;
                     }
@@ -191,5 +191,5 @@
         boolean isPartOfWay = false;
         for(Way w : getCurrentDataSet().ways) {
-            if(w.nodes.contains(n)) {
+            if(w.getNodes().contains(n)) {
                 isPartOfWay = true;
                 break;
@@ -232,9 +232,9 @@
                 selectedNode = (Node) p;
                 if (size == 1 || selectedWay != null)
-                    return size == 1 || selectedWay.nodes.contains(selectedNode);
+                    return size == 1 || selectedWay.getNodes().contains(selectedNode);
             } else if (p instanceof Way) {
                 selectedWay = (Way) p;
                 if (size == 2 && selectedNode != null)
-                    return selectedWay.nodes.contains(selectedNode);
+                    return selectedWay.getNodes().contains(selectedNode);
             }
         }
@@ -276,5 +276,5 @@
             if (p instanceof Node) {
                 Node n = (Node) p;
-                if (!selectedWay.nodes.contains(n))
+                if (!selectedWay.getNodes().contains(n))
                     return false;
                 selectedNodes.add(n);
@@ -283,5 +283,5 @@
 
         if (selectedNodes.size() < 1) {
-            selectedNodes.addAll(selectedWay.nodes);
+            selectedNodes.addAll(selectedWay.getNodes());
         }
 
@@ -298,5 +298,5 @@
     private Way modifyWay(Node originalNode, Way w, List<Command> cmds, List<Node> newNodes) {
         ArrayList<Node> nn = new ArrayList<Node>();
-        for (Node pushNode : w.nodes) {
+        for (Node pushNode : w.getNodes()) {
             if (originalNode == pushNode) {
                 // clone the node for all other ways
@@ -309,6 +309,5 @@
         }
         Way newWay = new Way(w);
-        newWay.nodes.clear();
-        newWay.nodes.addAll(nn);
+        newWay.setNodes(nn);
 
         return newWay;
@@ -370,8 +369,8 @@
             // modify all ways containing the nodes
             for (Way w : getCurrentDataSet().ways) {
-                if (w.deleted || w.incomplete || w.nodes.size() < 1) {
+                if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
                     continue;
                 }
-                if (!w.nodes.contains(selectedNode)) {
+                if (!w.getNodes().contains(selectedNode)) {
                     continue;
                 }
Index: /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 1862)
@@ -65,5 +65,5 @@
     /**
      * Replies true if we are currently running on OSX
-     * 
+     *
      * @return true if we are currently running on OSX
      */
@@ -306,6 +306,6 @@
                 {
                     Way w = (Way)osm;
-                    Point p1 = c.getPoint(w.nodes.get(nearestWS.lowerIndex));
-                    Point p2 = c.getPoint(w.nodes.get(nearestWS.lowerIndex+1));
+                    Point p1 = c.getPoint(w.getNode(nearestWS.lowerIndex));
+                    Point p2 = c.getPoint(w.getNode(nearestWS.lowerIndex+1));
                     if(SimplePaintVisitor.isLargeSegment(p1, p2, Main.pref.getInteger("mappaint.node.virtual-space", 70)))
                     {
@@ -317,10 +317,10 @@
                             // virtual node at the same spot will be joined which is likely unwanted
                             if(virtualWayNode != null) {
-                                if(  !w.nodes.get(nearestWS.lowerIndex+1).equals(virtualWayNode)
-                                        && !w.nodes.get(nearestWS.lowerIndex  ).equals(virtualWayNode)) {
+                                if(  !w.getNode(nearestWS.lowerIndex+1).equals(virtualWayNode)
+                                        && !w.getNode(nearestWS.lowerIndex).equals(virtualWayNode)) {
                                     continue;
                                 }
                             } else {
-                                virtualWayNode = w.nodes.get(nearestWS.lowerIndex+1);
+                                virtualWayNode = w.getNode(nearestWS.lowerIndex+1);
                             }
 
@@ -459,5 +459,5 @@
                     {
                         s.add(osm);
-                        s.addAll(((Way)osm).nodes);
+                        s.addAll(((Way)osm).getNodes());
                     }
                     if(s.size() > max)
Index: /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 1862)
@@ -375,5 +375,5 @@
         public NodeCount(int count) {this.count = count;}
         @Override public boolean match(OsmPrimitive osm) {
-            return osm instanceof Way && ((Way) osm).nodes.size() == count;
+            return osm instanceof Way && ((Way) osm).getNodesCount() == count;
         }
         @Override public String toString() {return "nodes="+count;}
@@ -394,5 +394,5 @@
         @Override public boolean match(OsmPrimitive osm) {
             if(!(osm instanceof Way)) return false;
-            int size = ((Way)osm).nodes.size();
+            int size = ((Way)osm).getNodesCount();
             return (size >= minCount) && (size <= maxCount);
         }
@@ -441,5 +441,5 @@
 
             if (osm instanceof Way) {
-                for (Node n : ((Way)osm).nodes) {
+                for (Node n : ((Way)osm).getNodes()) {
                     isParent |= child.match(n);
                 }
Index: /trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/command/PurgePrimitivesCommand.java	(revision 1862)
@@ -21,5 +21,4 @@
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -28,10 +27,10 @@
  * layer and disconnects any references from {@see Way}s or {@see Relation}s
  * to this primitive.
- * 
+ *
  * This command is necessary if a local {@see OsmPrimitive} has been deleted on
  * the server by another user and if the local user decides to delete his version
  * too. If he only deleted it "logically" JOSM would try to delete it on the server
  * which would result in an non resolvable conflict.
- * 
+ *
  */
 public class PurgePrimitivesCommand extends ConflictResolveCommand{
@@ -44,5 +43,5 @@
      * because a {@see Relation} refers to any other {@see OsmPrimitive}
      * via a relation member.
-     * 
+     *
      */
     static class OsmParentChildPair {
@@ -100,5 +99,5 @@
      * as child and given set of parents. We don't use {@see CollectBackReferencesVisitor}
      * because it seems quite inefficient.
-     * 
+     *
      * @param parents  the set of potential parents
      * @param child the child
@@ -110,5 +109,5 @@
             if (parent instanceof Way) {
                 Way w = (Way)parent;
-                for (OsmPrimitive node : w.nodes) {
+                for (OsmPrimitive node : w.getNodes()) {
                     if (node == child) {
                         OsmParentChildPair pair = new OsmParentChildPair(parent, node);
@@ -170,10 +169,10 @@
     /**
      * Purges an {@see OsmPrimitive} <code>toPurge</code> from a {@see DataSet}.
-     * 
+     *
      * @param toPurge the primitive to purge
      * @param ds  the dataset to purge from
      * @param hive the hive of {@see OsmPrimitive}s we remember other {@see OsmPrimitive}
      * we have to purge because we purge <code>toPurge</code>.
-     * 
+     *
      */
     protected void purge(OsmPrimitive toPurge, DataSet ds, ArrayList<OsmPrimitive> hive) {
Index: /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 1862)
@@ -76,5 +76,5 @@
         ArrayList<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>();
         primitives.add(way);
-        primitives.addAll(way.nodes);
+        primitives.addAll(way.getNodes());
 
         for (OsmPrimitive primitive : primitives) {
Index: /trunk/src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 1862)
@@ -4,13 +4,13 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 import static org.openstreetmap.josm.tools.I18n.trn;
-
-import java.util.HashSet;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
+import org.openstreetmap.josm.tools.CopyList;
 import org.openstreetmap.josm.tools.Pair;
 
@@ -26,4 +26,43 @@
      */
     public final List<Node> nodes = new ArrayList<Node>();
+
+    /**
+     *
+     * You can modify returned list but changes will not be propagated back
+     * to the Way. Use {@link #setNodes(List)} to update this way
+     * @return Nodes composing the way
+     * @since 1862
+     */
+    public List<Node> getNodes() {
+        return new CopyList<Node>(nodes.toArray(new Node[nodes.size()]));
+    }
+
+    /**
+     * @param nodes
+     * @since 1862
+     */
+    public void setNodes(List<Node> nodes) {
+        this.nodes.clear();
+        this.nodes.addAll(nodes);
+    }
+
+    /**
+     *
+     * @return
+     * @since 1862
+     */
+    public int getNodesCount() {
+        return nodes.size();
+    }
+
+    /**
+     *
+     * @param index
+     * @return
+     * @since 1862
+     */
+    public Node getNode(int index) {
+        return nodes.get(index);
+    }
 
     /* mappaint data */
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/CollectBackReferencesVisitor.java	(revision 1862)
@@ -6,8 +6,8 @@
 
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
 
@@ -47,5 +47,5 @@
         for (Way w : ds.ways) {
             if (w.deleted || w.incomplete) continue;
-            for (Node n2 : w.nodes) {
+            for (Node n2 : w.getNodes()) {
                 if (n == n2) {
                     data.add(w);
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 1862)
@@ -21,4 +21,5 @@
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 
 import javax.swing.ImageIcon;
@@ -162,5 +163,5 @@
      */
     public void visit(Way w) {
-        if(w.nodes.size() < 2)
+        if(w.getNodesCount() < 2)
         {
             w.mappaintVisibleCode = viewid;
@@ -174,5 +175,5 @@
         double maxy = -10000;
 
-        for (Node n : w.nodes)
+        for (Node n : w.getNodes())
         {
             if(n.getEastNorth().east() > maxx) maxx = n.getEastNorth().east();
@@ -293,5 +294,5 @@
                 {
                     lastN = null;
-                    for(Node n : w.nodes)
+                    for(Node n : w.getNodes())
                     {
                         if(lastN != null)
@@ -308,5 +309,5 @@
         /* draw the way */
         lastN = null;
-        Iterator<Node> it = w.nodes.iterator();
+        Iterator<Node> it = w.getNodes().iterator();
         while (it.hasNext())
         {
@@ -326,5 +327,5 @@
                 {
                     lastN = null;
-                    for(Node n : w.nodes)
+                    for(Node n : w.getNodes())
                     {
                         if(lastN != null)
@@ -365,5 +366,5 @@
             Way w = null;
             Boolean selected = false;
-            ArrayList<Node> n = null;
+            List<Node> n = null;
             Boolean joined = true;
             while(joined && left != 0)
@@ -380,21 +381,21 @@
                         {
                             int mode = 0;
-                            int cl = c.nodes.size()-1;
+                            int cl = c.getNodesCount()-1;
                             int nl;
                             if(n == null)
                             {
-                                nl = w.nodes.size()-1;
-                                if(w.nodes.get(nl) == c.nodes.get(0)) mode = 21;
-                                else if(w.nodes.get(nl) == c.nodes.get(cl)) mode = 22;
-                                else if(w.nodes.get(0) == c.nodes.get(0)) mode = 11;
-                                else if(w.nodes.get(0) == c.nodes.get(cl)) mode = 12;
+                                nl = w.getNodesCount()-1;
+                                if(w.getNode(nl) == c.getNode(0)) mode = 21;
+                                else if(w.getNode(nl) == c.getNode(cl)) mode = 22;
+                                else if(w.getNode(0) == c.getNode(0)) mode = 11;
+                                else if(w.getNode(0) == c.getNode(cl)) mode = 12;
                             }
                             else
                             {
                                 nl = n.size()-1;
-                                if(n.get(nl) == c.nodes.get(0)) mode = 21;
-                                else if(n.get(0) == c.nodes.get(cl)) mode = 12;
-                                else if(n.get(0) == c.nodes.get(0)) mode = 11;
-                                else if(n.get(nl) == c.nodes.get(cl)) mode = 22;
+                                if(n.get(nl) == c.getNode(0)) mode = 21;
+                                else if(n.get(0) == c.getNode(cl)) mode = 12;
+                                else if(n.get(0) == c.getNode(0)) mode = 11;
+                                else if(n.get(nl) == c.getNode(cl)) mode = 22;
                             }
                             if(mode != 0)
@@ -404,18 +405,18 @@
                                 if(c.selected) selected = true;
                                 --left;
-                                if(n == null) n = new ArrayList<Node>(w.nodes);
+                                if(n == null) n = w.getNodes();
                                 n.remove((mode == 21 || mode == 22) ? nl : 0);
                                 if(mode == 21)
-                                    n.addAll(c.nodes);
+                                    n.addAll(c.getNodes());
                                 else if(mode == 12)
-                                    n.addAll(0, c.nodes);
+                                    n.addAll(0, c.getNodes());
                                 else if(mode == 22)
                                 {
-                                    for(Node node : c.nodes)
+                                    for(Node node : c.getNodes())
                                         n.add(nl, node);
                                 }
                                 else /* mode == 11 */
                                 {
-                                    for(Node node : c.nodes)
+                                    for(Node node : c.getNodes())
                                         n.add(0, node);
                                 }
@@ -551,5 +552,5 @@
                 {
                     Way w = (Way) m.member;
-                    if(w.nodes.size() < 2)
+                    if(w.getNodesCount() < 2)
                     {
                         r.putError(tr("Way ''{0}'' with less than two points.",
@@ -640,8 +641,8 @@
         if(fromWay.firstNode() == via) {
             //System.out.println("From way heading away from via");
-            fromNode = fromWay.nodes.get(1);
+            fromNode = fromWay.getNode(1);
         } else {
             //System.out.println("From way heading towards via");
-            fromNode = fromWay.nodes.get(fromWay.nodes.size()-2);
+            fromNode = fromWay.getNode(fromWay.nodes.size()-2);
         }
 
@@ -796,5 +797,5 @@
                 {
                     Way w = (Way) m.member;
-                    if(w.nodes.size() < 2)
+                    if(w.getNodesCount() < 2)
                     {
                         r.putError(tr("Way ''{0}'' with less than two points.",
@@ -881,5 +882,5 @@
                     {
                         way = w;
-                        for (Node n : w.nodes)
+                        for (Node n : w.getNodes())
                         {
                             p = nc.getPoint(n);
@@ -1059,5 +1060,5 @@
         Polygon polygon = new Polygon();
 
-        for (Node n : w.nodes)
+        for (Node n : w.getNodes())
         {
             Point p = nc.getPoint(n);
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 1862)
@@ -7,4 +7,5 @@
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
@@ -51,7 +52,7 @@
     /**
      * constructor
-     * 
+     *
      * The visitor will merge <code>theirDataSet</code> onto <code>myDataSet</code>
-     * 
+     *
      * @param myDataSet  dataset with my primitives
      * @param theirDataSet dataset with their primitives.
@@ -76,13 +77,13 @@
     /**
      * Merges a primitive <code>other</code> of type <P> onto my primitives.
-     * 
+     *
      * If other.id != 0 it tries to merge it with an corresponding primitive from
      * my dataset with the same id. If this is not possible a conflict is remembered
      * in {@see #conflicts}.
-     * 
+     *
      * If other.id == 0 it tries to find a primitive in my dataset with id == 0 which
      * is semantically equal. If it finds one it merges its technical attributes onto
      * my primitive.
-     * 
+     *
      * @param <P>  the type of the other primitive
      * @param other  the other primitive
@@ -171,6 +172,6 @@
     private void fixWay(Way w) {
         boolean replacedSomething = false;
-        LinkedList<Node> newNodes = new LinkedList<Node>();
-        for (Node myNode : w.nodes) {
+        List<Node> newNodes = new LinkedList<Node>();
+        for (Node myNode : w.getNodes()) {
             Node mergedNode = (Node) merged.get(myNode);
             if (mergedNode != null) {
@@ -184,6 +185,5 @@
         }
         if (replacedSomething) {
-            w.nodes.clear();
-            w.nodes.addAll(newNodes);
+            w.setNodes(newNodes);
         }
     }
@@ -310,5 +310,5 @@
      * Runs the merge operation. Successfully merged {@see OsmPrimitive}s are in
      * {@see #getMyDataSet()}.
-     * 
+     *
      * See {@see #getConflicts()} for a map of conflicts after the merge operation.
      */
@@ -322,5 +322,5 @@
     /**
      * replies my dataset
-     * 
+     *
      * @return
      */
@@ -332,5 +332,5 @@
     /**
      * replies the map of conflicts
-     * 
+     *
      * @return the map of conflicts
      */
Index: /trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 1861)
+++ /trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java	(revision 1862)
@@ -20,8 +20,8 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.NavigatableComponent;
@@ -269,5 +269,5 @@
 
     public void visitVirtual(Way w) {
-        Iterator<Node> it = w.nodes.iterator();
+        Iterator<Node> it = w.getNodes().iterator();
         if (it.hasNext()) {
             Point lastP = nc.getPoint(it.next());
@@ -294,5 +294,5 @@
      */
     public void visit(Way w) {
-        if (w.incomplete || w.nodes.size() < 2)
+        if (w.incomplete || w.getNodesCount() < 2)
             return;
 
@@ -361,5 +361,5 @@
 
                 boolean first = true;
-                for (Node n : ((Way) m.member).nodes) {
+                for (Node n : ((Way) m.member).getNodes()) {
                     if (n.incomplete || n.deleted) continue;
                     Point p = nc.getPoint(n);
Index: /trunk/src/org/openstreetmap/josm/tools/CopyList.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/CopyList.java	(revision 1862)
+++ /trunk/src/org/openstreetmap/josm/tools/CopyList.java	(revision 1862)
@@ -0,0 +1,150 @@
+/*
+ *  JOSMng - a Java Open Street Map editor, the next generation.
+ *
+ *  Copyright (C) 2008 Petr Nejedly <P.Nejedly@sh.cvut.cz>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.openstreetmap.josm.tools;
+
+import java.util.AbstractList;
+import java.util.RandomAccess;
+
+/**
+ * A List implementation initially based on given array, but never modifying
+ * the array directly. On the first modification, the implementation will
+ * create its own copy of the array, and after that it behaves mostly as
+ * an ArrayList.
+ *
+ * @author nenik
+ */
+public class CopyList<E> extends AbstractList<E> implements RandomAccess, Cloneable {
+    private E[] array;
+    private int size;
+    private boolean pristine;
+
+    /**
+     * Create a List over given array.
+     * @param array The initial List content. The array is never modified
+     * by the {@code CopyList}.
+     */
+    public CopyList(E[] array) {
+        this(array, array.length);
+    }
+
+    private CopyList(E[] array, int size) {
+        this.array = array;
+        this.size = size;
+        pristine = true;
+    }
+
+    // read-only access:
+    public @Override E get(int index) {
+        rangeCheck(index);
+        return array[index];
+    }
+
+    public @Override int size() {
+        return size;
+    }
+
+    // modification:
+    public @Override E set(int index, E element) {
+        rangeCheck(index);
+        changeCheck();
+
+        E old = array[index];
+        array[index] = element;
+        return old;
+    }
+
+    // full resizable semantics:
+    public @Override void add(int index, E element) {
+        // range check
+        ensureCapacity(size+1);
+        changeCheck();
+
+        System.arraycopy(array, index, array, index+1, size-index);
+        array[index] = element;
+        size++;
+    }
+
+    public @Override E remove(int index) {
+        rangeCheck(index);
+        changeCheck();
+
+        modCount++;
+        E element = array[index];
+        if (index < size-1) {
+            System.arraycopy(array, index+1, array, index, size-index-1);
+        } else {
+            array[index] = null;
+        }
+        size--;
+        return element;
+    }
+
+
+    // speed optimizations:
+    public @Override boolean add(E element) {
+        ensureCapacity(size+1);
+        changeCheck();
+        array[size++] = element;
+        return true;
+    }
+
+    public @Override void clear() {
+    modCount++;
+
+        // clean up the array
+        while (size > 0) array[--size] = null;
+    }
+
+    // helpers:
+    /**
+     * Returns another independent copy-on-write copy of this <tt>List</tt>
+     * instance. Neither the elements nor the backing storage are copied.
+     *
+     * @return a clone of this <tt>CopyList</tt> instance
+     */
+    public @Override Object clone() {
+        return new CopyList<E>(array, size);
+    }
+
+    private void rangeCheck(int index) {
+    if (index >= size || index < 0) throw new IndexOutOfBoundsException();
+    }
+
+    private void changeCheck() {
+        if (pristine) {
+            array = array.clone();
+            pristine = false;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void ensureCapacity(int target) {
+        modCount++;
+        if (target > array.length) {
+            E[] old = array;
+
+            int newCapacity = Math.max(target, (array.length * 3)/2 + 1);
+            array = (E[]) new Object[newCapacity];
+            System.arraycopy(old, 0, array, 0, size);
+            pristine = false;
+    }
+    }
+}
