Changeset 11609 in josm for trunk


Ignore:
Timestamp:
2017-02-25T12:52:18+01:00 (3 years ago)
Author:
Don-vip
Message:

fix #14410 - AddPrimitivesCommand undo remove existing data (patch by Tyndare)

Location:
trunk
Files:
2 edited

Legend:

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

    r11553 r11609  
    1010import java.util.Objects;
    1111import java.util.Optional;
     12import java.util.stream.Collectors;
    1213
    1314import javax.swing.Icon;
     
    2829public class AddPrimitivesCommand extends Command {
    2930
    30     private List<PrimitiveData> data = new ArrayList<>();
    31     private Collection<PrimitiveData> toSelect = new ArrayList<>();
     31    private List<PrimitiveData> data;
     32    private Collection<PrimitiveData> toSelect;
     33    private List<PrimitiveData> preExistingData;
    3234
    3335    // only filled on undo
    3436    private List<OsmPrimitive> createdPrimitives;
    35     private Collection<OsmPrimitive> createdPrimitivesToSelect;
    3637
    3738    /**
     
    6667    private void init(List<PrimitiveData> data, List<PrimitiveData> toSelect) {
    6768        CheckParameterUtil.ensureParameterNotNull(data, "data");
    68         this.data.addAll(data);
    69         if (toSelect != null) {
    70             this.toSelect.addAll(toSelect);
     69        this.data = new ArrayList<>(data);
     70        if (toSelect == data) {
     71            this.toSelect = this.data;
     72        } else if (toSelect != null) {
     73            this.toSelect = new ArrayList<>(toSelect);
    7174        }
    7275    }
     
    7477    @Override
    7578    public boolean executeCommand() {
    76         Collection<OsmPrimitive> primitivesToSelect;
     79        DataSet ds = getAffectedDataSet();
    7780        if (createdPrimitives == null) { // first time execution
    7881            List<OsmPrimitive> newPrimitives = new ArrayList<>(data.size());
    79             primitivesToSelect = new ArrayList<>(toSelect.size());
     82            preExistingData = new ArrayList<>();
    8083
    8184            for (PrimitiveData pd : data) {
    82                 OsmPrimitive primitive = getAffectedDataSet().getPrimitiveById(pd);
     85                OsmPrimitive primitive = ds.getPrimitiveById(pd);
    8386                boolean created = primitive == null;
    84                 if (created) {
     87                if (primitive == null) {
    8588                    primitive = pd.getType().newInstance(pd.getUniqueId(), true);
     89                } else {
     90                    preExistingData.add(primitive.save());
    8691                }
    8792                if (pd instanceof NodeData) { // Load nodes immediately because they can't be added to dataset without coordinates
     
    8994                }
    9095                if (created) {
    91                     getAffectedDataSet().addPrimitive(primitive);
     96                    ds.addPrimitive(primitive);
    9297                }
    9398                newPrimitives.add(primitive);
    94                 if (toSelect.contains(pd)) {
    95                     primitivesToSelect.add(primitive);
    96                 }
    9799            }
    98100
     
    108110            // a subsequent command (e.g. MoveCommand) cannot be redone.
    109111            for (OsmPrimitive osm : createdPrimitives) {
    110                 getAffectedDataSet().addPrimitive(osm);
     112                if (preExistingData.stream().anyMatch(pd -> pd.getUniqueId() == osm.getUniqueId())) {
     113                    Optional<PrimitiveData> o = data.stream().filter(pd -> pd.getUniqueId() == osm.getUniqueId()).findAny();
     114                    if (o.isPresent()) {
     115                        osm.load(o.get());
     116                    }
     117                } else {
     118                    ds.addPrimitive(osm);
     119                }
    111120            }
    112             primitivesToSelect = createdPrimitivesToSelect;
    113121        }
    114 
    115         getAffectedDataSet().setSelected(primitivesToSelect);
     122        if (toSelect != null) {
     123            ds.setSelected(toSelect.stream().map(ds::getPrimitiveById).collect(Collectors.toList()));
     124        }
    116125        return true;
    117126    }
     
    119128    @Override public void undoCommand() {
    120129        DataSet ds = getAffectedDataSet();
    121 
    122130        if (createdPrimitives == null) {
    123131            createdPrimitives = new ArrayList<>(data.size());
    124             createdPrimitivesToSelect = new ArrayList<>(toSelect.size());
    125 
    126132            for (PrimitiveData pd : data) {
    127133                OsmPrimitive p = ds.getPrimitiveById(pd);
    128134                createdPrimitives.add(p);
    129                 if (toSelect.contains(pd)) {
    130                     createdPrimitivesToSelect.add(p);
    131                 }
    132135            }
    133136            createdPrimitives = PurgeCommand.topoSort(createdPrimitives);
    134 
    135             for (PrimitiveData p : data) {
    136                 ds.removePrimitive(p);
    137             }
    138             data = null;
    139             toSelect = null;
    140 
    141         } else {
    142             for (OsmPrimitive osm : createdPrimitives) {
     137        }
     138        for (OsmPrimitive osm : createdPrimitives) {
     139            Optional<PrimitiveData> previous = preExistingData.stream().filter(pd -> pd.getUniqueId() == osm.getUniqueId()).findAny();
     140            if (previous.isPresent()) {
     141                osm.load(previous.get());
     142            } else {
    143143                ds.removePrimitive(osm);
    144144            }
     
    178178    @Override
    179179    public int hashCode() {
    180         return Objects.hash(super.hashCode(), data, toSelect, createdPrimitives, createdPrimitivesToSelect);
     180        return Objects.hash(super.hashCode(), data, toSelect, preExistingData, createdPrimitives);
    181181    }
    182182
     
    189189        return Objects.equals(data, that.data) &&
    190190               Objects.equals(toSelect, that.toSelect) &&
    191                Objects.equals(createdPrimitives, that.createdPrimitives) &&
    192                Objects.equals(createdPrimitivesToSelect, that.createdPrimitivesToSelect);
     191               Objects.equals(preExistingData, that.preExistingData) &&
     192               Objects.equals(createdPrimitives, that.createdPrimitives);
    193193    }
    194194}
  • trunk/test/unit/org/openstreetmap/josm/command/AddPrimitivesCommandTest.java

    r10804 r11609  
    176176
    177177    /**
     178     * Tests if the undo command does not remove
     179     * data ignored by by the add command because they where already existing.
     180     */
     181    @Test
     182    public void testUndoIgnoresExisting() {
     183        OsmDataLayer layer1 = new OsmDataLayer(new DataSet(), "l1", null);
     184        Main.getLayerManager().addLayer(layer1);
     185
     186        List<PrimitiveData> testData = createTestData();
     187
     188        assertTrue(new AddPrimitivesCommand(testData).executeCommand());
     189        assertEquals(2, layer1.data.getNodes().size());
     190        assertEquals(1, layer1.data.getWays().size());
     191
     192        testData.set(2, createTestNode(7));
     193
     194        AddPrimitivesCommand command = new AddPrimitivesCommand(testData);
     195
     196        assertTrue(command.executeCommand());
     197
     198        assertEquals(3, layer1.data.getNodes().size());
     199        assertEquals(1, layer1.data.getWays().size());
     200
     201        for (int i = 0; i < 2; i++) {
     202            // Needs to work multiple times.
     203            command.undoCommand();
     204
     205            assertEquals(2, layer1.data.getNodes().size());
     206            assertEquals(1, layer1.data.getWays().size());
     207
     208            // redo
     209            assertTrue(command.executeCommand());
     210
     211            assertEquals(3, layer1.data.getNodes().size());
     212            assertEquals(1, layer1.data.getWays().size());
     213        }
     214    }
     215
     216    /**
    178217     * Test {@link AddCommand#getParticipatingPrimitives()}
    179218     */
Note: See TracChangeset for help on using the changeset viewer.