Subject: [PATCH] Fix #22808: Undoing "Paste" for ways of a route relation is very slow
---
Index: src/org/openstreetmap/josm/command/AddPrimitivesCommand.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java b/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java
--- a/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java	(revision 18715)
+++ b/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java	(date 1682437443486)
@@ -17,6 +17,7 @@
 import org.openstreetmap.josm.data.osm.NodeData;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.PrimitiveData;
+import org.openstreetmap.josm.data.osm.PrimitiveId;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
 /**
@@ -127,6 +128,7 @@
             createdPrimitives = PurgeCommand.topoSort(createdPrimitives);
         }
         // reversed order, see #14620
+        List<PrimitiveId> toRemove = new ArrayList<>(this.createdPrimitives.size());
         for (int i = createdPrimitives.size() - 1; i >= 0; i--) {
             OsmPrimitive osm = createdPrimitives.get(i);
             Optional<PrimitiveData> previous = preExistingData.stream()
@@ -134,9 +136,11 @@
             if (previous.isPresent()) {
                 osm.load(previous.get());
             } else {
+                toRemove.add(osm);
                 ds.removePrimitive(osm);
             }
         }
+        ds.removePrimitives(toRemove);
     }
 
     @Override
Index: src/org/openstreetmap/josm/data/osm/DataSet.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/data/osm/DataSet.java b/src/org/openstreetmap/josm/data/osm/DataSet.java
--- a/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 18715)
+++ b/src/org/openstreetmap/josm/data/osm/DataSet.java	(date 1682437388773)
@@ -5,6 +5,7 @@
 
 import java.awt.geom.Area;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -564,6 +565,48 @@
         });
     }
 
+    /**
+     * Removes primitives from the dataset. This method only removes the
+     * primitives form the respective collection of primitives managed
+     * by this dataset, i.e. from {@code store.nodes}, {@code store.ways}, or
+     * {@code store.relations}. References from other primitives to this
+     * primitive are left unchanged.
+     *
+     * @param primitiveIds the ids of the primitive
+     * @throws IllegalStateException if the dataset is read-only
+     * @since xxx
+     */
+    public void removePrimitives(PrimitiveId... primitiveIds) {
+        this.removePrimitives(Arrays.asList(primitiveIds));
+    }
+
+    /**
+     * Removes primitives from the dataset. This method only removes the
+     * primitives form the respective collection of primitives managed
+     * by this dataset, i.e. from {@code store.nodes}, {@code store.ways}, or
+     * {@code store.relations}. References from other primitives to this
+     * primitive are left unchanged.
+     *
+     * @param primitiveIds the ids of the primitive
+     * @throws IllegalStateException if the dataset is read-only
+     * @since xxx
+     */
+    public void removePrimitives(Collection<PrimitiveId> primitiveIds) {
+        checkModifiable();
+        update(() -> {
+            final List<OsmPrimitive> removed = new ArrayList<>(primitiveIds.size());
+            for (PrimitiveId primitiveId : primitiveIds) {
+                OsmPrimitive primitive = this.getPrimitiveByIdChecked(primitiveId);
+                if (primitive == null) {
+                    continue;
+                }
+                removePrimitiveImpl(primitive);
+                removed.add(primitive);
+            }
+            firePrimitivesRemoved(removed, false);
+        });
+    }
+
     private void removePrimitiveImpl(OsmPrimitive primitive) {
         clearSelection(primitive.getPrimitiveId());
         if (primitive.isSelected()) {
