Changeset 18724 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2023-05-10T19:37:19+02:00 (17 months ago)
Author:
taylor.smock
Message:

Fix #22808: Add bulk removal method to DataSet

This fixes an issue where selecting a large number of objects that will be
removed after pasting them will cause a massive number of events to be fired.

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java

    r17240 r18724  
    1818import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1919import org.openstreetmap.josm.data.osm.PrimitiveData;
     20import org.openstreetmap.josm.data.osm.PrimitiveId;
    2021import org.openstreetmap.josm.tools.CheckParameterUtil;
    2122
     
    128129        }
    129130        // reversed order, see #14620
    130         for (int i = createdPrimitives.size() - 1; i >= 0; i--) {
    131             OsmPrimitive osm = createdPrimitives.get(i);
    132             Optional<PrimitiveData> previous = preExistingData.stream()
    133                     .filter(pd -> pd.getPrimitiveId().equals(osm.getPrimitiveId())).findAny();
    134             if (previous.isPresent()) {
    135                 osm.load(previous.get());
    136             } else {
    137                 ds.removePrimitive(osm);
    138             }
    139         }
     131        final List<PrimitiveId> toRemove = new ArrayList<>(this.createdPrimitives.size());
     132        ds.update(() -> {
     133                    for (int i = createdPrimitives.size() - 1; i >= 0; i--) {
     134                        OsmPrimitive osm = createdPrimitives.get(i);
     135                        Optional<PrimitiveData> previous = preExistingData.stream()
     136                                .filter(pd -> pd.getPrimitiveId().equals(osm.getPrimitiveId())).findAny();
     137                        if (previous.isPresent()) {
     138                            osm.load(previous.get());
     139                        } else {
     140                            toRemove.add(osm);
     141                        }
     142                    }
     143                });
     144        ds.removePrimitives(toRemove);
    140145    }
    141146
  • trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r18539 r18724  
    66import java.awt.geom.Area;
    77import java.util.ArrayList;
     8import java.util.Arrays;
    89import java.util.Collection;
    910import java.util.Collections;
     
    546547    /**
    547548     * Removes a primitive from the dataset. This method only removes the
    548      * primitive form the respective collection of primitives managed
     549     * primitive from the respective collection of primitives managed
    549550     * by this dataset, i.e. from {@code store.nodes}, {@code store.ways}, or
    550551     * {@code store.relations}. References from other primitives to this
     
    565566    }
    566567
     568    /**
     569     * Removes primitives from the dataset. This method only removes the
     570     * primitives from the respective collection of primitives managed
     571     * by this dataset, i.e. from {@code store.nodes}, {@code store.ways}, or
     572     * {@code store.relations}. References from other primitives to this
     573     * primitive are left unchanged.
     574     *
     575     * @param primitiveIds the ids of the primitive
     576     * @throws IllegalStateException if the dataset is read-only
     577     * @since 18724
     578     */
     579    public void removePrimitives(PrimitiveId... primitiveIds) {
     580        this.removePrimitives(Arrays.asList(primitiveIds));
     581    }
     582
     583    /**
     584     * Removes primitives from the dataset. This method only removes the
     585     * primitives from the respective collection of primitives managed
     586     * by this dataset, i.e. from {@code store.nodes}, {@code store.ways}, or
     587     * {@code store.relations}. References from other primitives to this
     588     * primitive are left unchanged.
     589     *
     590     * @param primitiveIds the ids of the primitive
     591     * @throws IllegalStateException if the dataset is read-only
     592     * @since 18724
     593     */
     594    public void removePrimitives(Collection<PrimitiveId> primitiveIds) {
     595        checkModifiable();
     596        final List<PrimitiveId> selected = new ArrayList<>();
     597        update(() -> {
     598            clearSelection(primitiveIds);
     599            final List<OsmPrimitive> removed = new ArrayList<>(primitiveIds.size());
     600            for (PrimitiveId primitiveId : primitiveIds) {
     601                OsmPrimitive primitive = this.getPrimitiveByIdChecked(primitiveId);
     602                if (primitive == null) {
     603                    continue;
     604                } else if (primitive.isSelected()) {
     605                    selected.add(primitive);
     606                }
     607                this.removePrimitiveFromStorage(primitive);
     608                removed.add(primitive);
     609            }
     610            firePrimitivesRemoved(removed, false);
     611        });
     612        if (!selected.isEmpty()) {
     613            throw new DataIntegrityProblemException("Primitives were re-selected by a selection listener: "
     614            + selected.stream().map(PrimitiveId::toString).collect(Collectors.joining(", ")));
     615        }
     616    }
     617
    567618    private void removePrimitiveImpl(OsmPrimitive primitive) {
    568619        clearSelection(primitive.getPrimitiveId());
     
    570621            throw new DataIntegrityProblemException("Primitive was re-selected by a selection listener: " + primitive);
    571622        }
     623        this.removePrimitiveFromStorage(primitive);
     624    }
     625
     626    private void removePrimitiveFromStorage(OsmPrimitive primitive) {
    572627        store.removePrimitive(primitive);
    573628        allPrimitives.remove(primitive);
Note: See TracChangeset for help on using the changeset viewer.