Index: /trunk/src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 2741)
@@ -216,5 +216,5 @@
         WayData data = new WayData();
         saveCommonAttributes(data);
-        for (Node node:getNodes()) {
+        for (Node node:nodes) {
             data.getNodes().add(node.getUniqueId());
         }
@@ -387,5 +387,5 @@
 
     public boolean hasIncompleteNodes() {
-        for (Node node:getNodes()) {
+        for (Node node:nodes) {
             if (node.isIncomplete())
                 return true;
Index: /trunk/src/org/openstreetmap/josm/data/osm/event/DataChangedEvent.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/event/DataChangedEvent.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/data/osm/event/DataChangedEvent.java	(revision 2741)
@@ -10,6 +10,13 @@
 public class DataChangedEvent extends AbstractDatasetChangedEvent {
 
+    private final List<AbstractDatasetChangedEvent> events;
+
+    public DataChangedEvent(DataSet dataSet, List<AbstractDatasetChangedEvent> events) {
+        super(dataSet);
+        this.events = events;
+    }
+
     public DataChangedEvent(DataSet dataSet) {
-        super(dataSet);
+        this(dataSet, null);
     }
 
@@ -32,3 +39,11 @@
     }
 
+    /**
+     * 
+     * @return List of events that caused this DataChangedEvent. Might be null
+     */
+    public List<AbstractDatasetChangedEvent> getEvents() {
+        return events;
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/data/osm/event/DatasetEventManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/event/DatasetEventManager.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/data/osm/event/DatasetEventManager.java	(revision 2741)
@@ -2,4 +2,7 @@
 package org.openstreetmap.josm.data.osm.event;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Queue;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -8,4 +11,5 @@
 import javax.swing.SwingUtilities;
 
+import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter.Listener;
 import org.openstreetmap.josm.gui.MapView;
@@ -25,4 +29,33 @@
     private static final DatasetEventManager instance = new DatasetEventManager();
 
+    public enum FireMode {
+        IMMEDIATELY,
+        IN_EDT,
+        /**
+         * Fire in event dispatch thread. If more than one event arrived when event queue is checked, merged them to
+         * one event
+         */
+        IN_EDT_CONSOLIDATED}
+
+    private static class ListenerInfo {
+        final DataSetListener listener;
+        final boolean consolidate;
+
+        public ListenerInfo(DataSetListener listener, boolean consolidate) {
+            this.listener = listener;
+            this.consolidate = consolidate;
+        }
+
+        @Override
+        public int hashCode() {
+            return listener.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof ListenerInfo && ((ListenerInfo)o).listener == listener;
+        }
+    }
+
     public static DatasetEventManager getInstance() {
         return instance;
@@ -30,6 +63,6 @@
 
     private final Queue<AbstractDatasetChangedEvent> eventsInEDT = new LinkedBlockingQueue<AbstractDatasetChangedEvent>();
-    private final CopyOnWriteArrayList<DataSetListener> inEDTListeners = new CopyOnWriteArrayList<DataSetListener>();
-    private final CopyOnWriteArrayList<DataSetListener> normalListeners = new CopyOnWriteArrayList<DataSetListener>();
+    private final CopyOnWriteArrayList<ListenerInfo> inEDTListeners = new CopyOnWriteArrayList<ListenerInfo>();
+    private final CopyOnWriteArrayList<ListenerInfo> normalListeners = new CopyOnWriteArrayList<ListenerInfo>();
     private final DataSetListener myListener = new DataSetListenerAdapter(this);
 
@@ -44,15 +77,16 @@
      * instead of thread that caused the dataset change
      */
-    public void addDatasetListener(DataSetListener listener, boolean fireInEDT) {
-        if (fireInEDT) {
-            inEDTListeners.addIfAbsent(listener);
+    public void addDatasetListener(DataSetListener listener, FireMode fireMode) {
+        if (fireMode == FireMode.IN_EDT || fireMode == FireMode.IN_EDT_CONSOLIDATED) {
+            inEDTListeners.addIfAbsent(new ListenerInfo(listener, fireMode == FireMode.IN_EDT_CONSOLIDATED));
         } else {
-            normalListeners.addIfAbsent(listener);
+            normalListeners.addIfAbsent(new ListenerInfo(listener, false));
         }
     }
 
     public void removeDatasetListener(DataSetListener listener) {
-        inEDTListeners.remove(listener);
-        normalListeners.remove(listener);
+        ListenerInfo searchListener = new ListenerInfo(listener, false);
+        inEDTListeners.remove(searchListener);
+        normalListeners.remove(searchListener);
     }
 
@@ -70,8 +104,22 @@
     }
 
+    private void fireEvents(List<ListenerInfo> listeners, AbstractDatasetChangedEvent event) {
+        for (ListenerInfo listener: listeners) {
+            if (!listener.consolidate) {
+                event.fire(listener.listener);
+            }
+        }
+    }
+
+    private void fireConsolidatedEvents(List<ListenerInfo> listeners, AbstractDatasetChangedEvent event) {
+        for (ListenerInfo listener: listeners) {
+            if (listener.consolidate) {
+                event.fire(listener.listener);
+            }
+        }
+    }
+
     public void processDatasetEvent(AbstractDatasetChangedEvent event) {
-        for (DataSetListener listener: normalListeners) {
-            event.fire(listener);
-        }
+        fireEvents(normalListeners, event);
         eventsInEDT.add(event);
         SwingUtilities.invokeLater(edtRunnable);
@@ -80,9 +128,36 @@
     private final Runnable edtRunnable = new Runnable() {
         public void run() {
-            AbstractDatasetChangedEvent event = null;
-            while ((event = eventsInEDT.poll()) != null) {
-                for (DataSetListener listener: inEDTListeners) {
-                    event.fire(listener);
+            while (!eventsInEDT.isEmpty()) {
+                List<AbstractDatasetChangedEvent> events = new ArrayList<AbstractDatasetChangedEvent>();
+                events.addAll(eventsInEDT);
+
+                DataSet dataSet = null;
+                AbstractDatasetChangedEvent consolidatedEvent = null;
+                AbstractDatasetChangedEvent event = null;
+
+                while ((event = eventsInEDT.poll()) != null) {
+                    fireEvents(inEDTListeners, event);
+
+                    // DataSet changed - fire consolidated event early
+                    if (consolidatedEvent != null && dataSet != event.getDataset()) {
+                        fireConsolidatedEvents(inEDTListeners, consolidatedEvent);
+                        dataSet = event.getDataset();
+                        consolidatedEvent = null;
+                    }
+
+                    // Build consolidated event
+                    if (consolidatedEvent == null) {
+                        consolidatedEvent = event;
+                        dataSet = event.getDataset();
+                    } else if (consolidatedEvent instanceof DataChangedEvent) {
+                        ((DataChangedEvent)consolidatedEvent).getEvents().add(event);
+                    } else {
+                        consolidatedEvent = new DataChangedEvent(dataSet,
+                                new ArrayList<AbstractDatasetChangedEvent>(Arrays.asList(consolidatedEvent)));
+                    }
                 }
+
+                // Fire consolidated event
+                fireConsolidatedEvents(inEDTListeners, consolidatedEvent);
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 2741)
@@ -26,5 +26,4 @@
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
-import javax.swing.JToolBar;
 import javax.swing.ListSelectionModel;
 import javax.swing.SwingUtilities;
@@ -39,4 +38,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
+import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.gui.MapView;
@@ -154,5 +154,5 @@
     public void showNotify() {
         registerAsListener();
-        DatasetEventManager.getInstance().addDatasetListener(inActiveDataLayerModel, true);
+        DatasetEventManager.getInstance().addDatasetListener(inActiveDataLayerModel, FireMode.IN_EDT);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 2741)
@@ -22,7 +22,7 @@
 import javax.swing.DefaultListSelectionModel;
 import javax.swing.JList;
+import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
-import javax.swing.JPanel;
 import javax.swing.KeyStroke;
 import javax.swing.ListSelectionModel;
@@ -46,4 +46,5 @@
 import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
 import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
 import org.openstreetmap.josm.gui.MapView;
@@ -143,5 +144,5 @@
         MapView.addLayerChangeListener(newAction);
         newAction.updateEnabledState();
-        DatasetEventManager.getInstance().addDatasetListener(this, true);
+        DatasetEventManager.getInstance().addDatasetListener(this, FireMode.IN_EDT);
         dataChanged(null);
     }
@@ -518,5 +519,5 @@
         }
 
-        public synchronized void sort() {
+        public void sort() {
             Collections.sort(
                     relations,
@@ -535,5 +536,5 @@
         }
 
-        public synchronized void setRelations(Collection<Relation> relations) {
+        public void setRelations(Collection<Relation> relations) {
             List<Relation> sel =  getSelectedRelations();
             this.relations.clear();
@@ -561,5 +562,5 @@
          * ways, and relations.
          */
-        public synchronized void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
+        public void addRelations(Collection<? extends OsmPrimitive> addedPrimitives) {
             boolean added = false;
             for (OsmPrimitive p: addedPrimitives) {
@@ -591,5 +592,5 @@
          *   and relations
          */
-        public synchronized void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
+        public void removeRelations(Collection<? extends OsmPrimitive> removedPrimitives) {
             if (removedPrimitives == null) return;
             // extract the removed relations
@@ -664,5 +665,5 @@
          * @return sel the list of selected relations
          */
-        public synchronized void setSelectedRelations(List<Relation> sel) {
+        public void setSelectedRelations(List<Relation> sel) {
             selectionModel.clearSelection();
             if (sel == null || sel.isEmpty())
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 2741)
@@ -11,5 +11,4 @@
 import java.awt.Font;
 import java.awt.GridBagLayout;
-import java.awt.GridLayout;
 import java.awt.Point;
 import java.awt.event.ActionEvent;
@@ -65,5 +64,8 @@
 import org.openstreetmap.josm.data.osm.RelationMember;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter;
 import org.openstreetmap.josm.data.osm.event.DatasetEventManager;
+import org.openstreetmap.josm.data.osm.event.DatasetEventManager.FireMode;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
 import org.openstreetmap.josm.gui.ExtendedDialog;
@@ -99,5 +101,5 @@
  * @author imi
  */
-public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener {
+public class PropertiesDialog extends ToggleDialog implements SelectionChangedListener, MapView.EditLayerChangeListener, DataSetListenerAdapter.Listener {
     /**
      * Watches for double clicks and from editing or new property, depending on the
@@ -144,7 +146,10 @@
     private final ListOfUsedTags listOfUsedTags = new ListOfUsedTags();
 
+    private DataSetListenerAdapter dataChangedAdapter = new DataSetListenerAdapter(this);
+
     @Override
     public void showNotify() {
-        DatasetEventManager.getInstance().addDatasetListener(listOfUsedTags, false);
+        DatasetEventManager.getInstance().addDatasetListener(listOfUsedTags, FireMode.IMMEDIATELY);
+        DatasetEventManager.getInstance().addDatasetListener(dataChangedAdapter, FireMode.IN_EDT_CONSOLIDATED);
         listOfUsedTags.rebuildNecessary();
         DataSet.selListeners.add(this);
@@ -155,4 +160,5 @@
     public void hideNotify() {
         DatasetEventManager.getInstance().removeDatasetListener(listOfUsedTags);
+        DatasetEventManager.getInstance().removeDatasetListener(dataChangedAdapter);
         DataSet.selListeners.remove(this);
     }
@@ -310,4 +316,5 @@
      * @param row
      */
+    @SuppressWarnings("unchecked")
     void membershipEdit(int row) {
         Relation relation = (Relation)membershipData.getValueAt(row, 0);
@@ -455,11 +462,11 @@
                     if (value instanceof String) {
                         str = (String) value;
-                    } else if (value instanceof Map) {
-                        Map v = (Map) value;
+                    } else if (value instanceof Map<?, ?>) {
+                        Map<?, ?> v = (Map<?, ?>) value;
                         if (v.size() != 1) {
                             str=tr("<different>");
                             c.setFont(c.getFont().deriveFont(Font.ITALIC));
                         } else {
-                            final Map.Entry entry = (Map.Entry) v.entrySet().iterator().next();
+                            final Map.Entry<?, ?> entry = v.entrySet().iterator().next();
                             str = (String) entry.getKey();
                         }
@@ -810,4 +817,8 @@
     }
 
+    public void processDatasetEvent(AbstractDatasetChangedEvent event) {
+        updateSelection();
+    }
+
     class DeleteAction extends AbstractAction implements ListSelectionListener {
 
@@ -922,5 +933,5 @@
     }
 
-    class SelectRelationAction extends AbstractAction {
+    static class SelectRelationAction extends AbstractAction {
         boolean selectionmode;
         Relation relation;
@@ -929,17 +940,18 @@
             relation = r;
             if(select) {
-              putValue(NAME, tr("Select relation"));
-              putValue(SHORT_DESCRIPTION, tr("Select relation in main selection."));
+                putValue(NAME, tr("Select relation"));
+                putValue(SHORT_DESCRIPTION, tr("Select relation in main selection."));
             } else {
-              putValue(NAME, tr("Select in relation list"));
-              putValue(SHORT_DESCRIPTION, tr("Select relation in relation list."));
+                putValue(NAME, tr("Select in relation list"));
+                putValue(SHORT_DESCRIPTION, tr("Select relation in relation list."));
             }
         }
 
         public void actionPerformed(ActionEvent e) {
-            if(selectionmode)
+            if(selectionmode) {
                 Main.map.mapView.getEditLayer().data.setSelected(relation);
-            else
+            } else {
                 Main.map.relationListDialog.selectRelation(relation);
+            }
         }
     }
Index: /trunk/src/org/openstreetmap/josm/tools/CopyList.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/CopyList.java	(revision 2740)
+++ /trunk/src/org/openstreetmap/josm/tools/CopyList.java	(revision 2741)
@@ -22,4 +22,7 @@
 
 import java.util.AbstractList;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 import java.util.RandomAccess;
 
@@ -32,5 +35,5 @@
  * @author nenik
  */
-public class CopyList<E> extends AbstractList<E> implements RandomAccess, Cloneable {
+public final class CopyList<E> extends AbstractList<E> implements RandomAccess, Cloneable {
     private E[] array;
     private int size;
@@ -107,8 +110,10 @@
 
     public @Override void clear() {
-    modCount++;
+        modCount++;
 
         // clean up the array
-        while (size > 0) array[--size] = null;
+        while (size > 0) {
+            array[--size] = null;
+        }
     }
 
@@ -125,5 +130,5 @@
 
     private void rangeCheck(int index) {
-    if (index >= size || index < 0) throw new IndexOutOfBoundsException();
+        if (index >= size || index < 0) throw new IndexOutOfBoundsException();
     }
 
@@ -145,5 +150,70 @@
             System.arraycopy(old, 0, array, 0, size);
             pristine = false;
-    }
-    }
+        }
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return new Itr();
+    }
+
+    private class Itr implements Iterator<E> {
+        /**
+         * Index of element to be returned by subsequent call to next.
+         */
+        int cursor = 0;
+
+        /**
+         * Index of element returned by most recent call to next or
+         * previous.  Reset to -1 if this element is deleted by a call
+         * to remove.
+         */
+        int lastRet = -1;
+
+        /**
+         * The modCount value that the iterator believes that the backing
+         * List should have.  If this expectation is violated, the iterator
+         * has detected concurrent modification.
+         */
+        int expectedModCount = modCount;
+
+        public boolean hasNext() {
+            return cursor != size;
+        }
+
+        public E next() {
+            checkForComodification();
+            try {
+                E next = array[cursor];
+                lastRet = cursor++;
+                return next;
+            } catch (IndexOutOfBoundsException e) {
+                checkForComodification();
+                throw new NoSuchElementException();
+            }
+        }
+
+        public void remove() {
+            if (lastRet == -1)
+                throw new IllegalStateException();
+            checkForComodification();
+
+            try {
+                CopyList.this.remove(lastRet);
+                if (lastRet < cursor) {
+                    cursor--;
+                }
+                lastRet = -1;
+                expectedModCount = modCount;
+            } catch (IndexOutOfBoundsException e) {
+                throw new ConcurrentModificationException();
+            }
+        }
+
+        final void checkForComodification() {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+        }
+    }
+
 }
