Ticket #14410: AddPrimitivesCommand-undo-existing.patch
File AddPrimitivesCommand-undo-existing.patch, 7.8 KB (added by , 7 years ago) |
---|
-
josm/core/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java
9 9 import java.util.List; 10 10 import java.util.Objects; 11 11 import java.util.Optional; 12 import java.util.stream.Collectors; 12 13 13 14 import javax.swing.Icon; 14 15 … … 27 28 */ 28 29 public class AddPrimitivesCommand extends Command { 29 30 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> preexistinglData; 32 34 33 35 // only filled on undo 34 36 private List<OsmPrimitive> createdPrimitives; 35 private Collection<OsmPrimitive> createdPrimitivesToSelect;36 37 37 38 /** 38 39 * Constructs a new {@code AddPrimitivesCommand} to add data to the current edit layer. … … 65 66 66 67 private void init(List<PrimitiveData> data, List<PrimitiveData> toSelect) { 67 68 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); 71 74 } 72 75 } 73 76 74 77 @Override 75 78 public boolean executeCommand() { 76 Collection<OsmPrimitive> primitivesToSelect;79 DataSet ds = getAffectedDataSet(); 77 80 if (createdPrimitives == null) { // first time execution 78 81 List<OsmPrimitive> newPrimitives = new ArrayList<>(data.size()); 79 pr imitivesToSelect = new ArrayList<>(toSelect.size());82 preexistinglData = new ArrayList<>(); 80 83 81 84 for (PrimitiveData pd : data) { 82 OsmPrimitive primitive = getAffectedDataSet().getPrimitiveById(pd);85 OsmPrimitive primitive = ds.getPrimitiveById(pd); 83 86 boolean created = primitive == null; 84 if ( created) {87 if (primitive == null) { 85 88 primitive = pd.getType().newInstance(pd.getUniqueId(), true); 89 } else { 90 preexistinglData.add(primitive.save()); 86 91 } 87 92 if (pd instanceof NodeData) { // Load nodes immediately because they can't be added to dataset without coordinates 88 93 primitive.load(pd); 89 94 } 90 95 if (created) { 91 getAffectedDataSet().addPrimitive(primitive);96 ds.addPrimitive(primitive); 92 97 } 93 98 newPrimitives.add(primitive); 94 if (toSelect.contains(pd)) {95 primitivesToSelect.add(primitive);96 }97 99 } 98 100 99 101 // Then load ways and relations … … 107 109 // When redoing this command, we have to add the same objects, otherwise 108 110 // a subsequent command (e.g. MoveCommand) cannot be redone. 109 111 for (OsmPrimitive osm : createdPrimitives) { 110 getAffectedDataSet().addPrimitive(osm); 112 if (preexistinglData.stream().anyMatch(pd -> pd.getUniqueId() == osm.getUniqueId())) { 113 osm.load(data.stream().filter(pd -> pd.getUniqueId() == osm.getUniqueId()).findAny().get()); 114 } else { 115 ds.addPrimitive(osm); 116 } 111 117 } 112 primitivesToSelect = createdPrimitivesToSelect;113 118 } 114 115 getAffectedDataSet().setSelected(primitivesToSelect); 119 if (toSelect != null) { 120 ds.setSelected(toSelect.stream() 121 .map(pd -> ds.getPrimitiveById(pd)) 122 .collect(Collectors.toList())); 123 } 116 124 return true; 117 125 } 118 126 119 127 @Override public void undoCommand() { 120 128 DataSet ds = getAffectedDataSet(); 121 122 129 if (createdPrimitives == null) { 123 130 createdPrimitives = new ArrayList<>(data.size()); 124 createdPrimitivesToSelect = new ArrayList<>(toSelect.size());125 126 131 for (PrimitiveData pd : data) { 127 132 OsmPrimitive p = ds.getPrimitiveById(pd); 128 133 createdPrimitives.add(p); 129 if (toSelect.contains(pd)) {130 createdPrimitivesToSelect.add(p);131 }132 134 } 133 135 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) { 136 } 137 for (OsmPrimitive osm : createdPrimitives) { 138 Optional<PrimitiveData> previous = preexistinglData.stream().filter(pd -> pd.getUniqueId() == osm.getUniqueId()).findAny(); 139 if (previous.isPresent()) { 140 osm.load(previous.get()); 141 } else { 143 142 ds.removePrimitive(osm); 144 143 } 145 144 } … … 177 176 178 177 @Override 179 178 public int hashCode() { 180 return Objects.hash(super.hashCode(), data, toSelect, createdPrimitives, createdPrimitivesToSelect);179 return Objects.hash(super.hashCode(), data, toSelect, preexistinglData, createdPrimitives); 181 180 } 182 181 183 182 @Override … … 188 187 AddPrimitivesCommand that = (AddPrimitivesCommand) obj; 189 188 return Objects.equals(data, that.data) && 190 189 Objects.equals(toSelect, that.toSelect) && 191 Objects.equals( createdPrimitives, that.createdPrimitives) &&192 Objects.equals(createdPrimitives ToSelect, that.createdPrimitivesToSelect);190 Objects.equals(preexistinglData, that.preexistinglData) && 191 Objects.equals(createdPrimitives, that.createdPrimitives); 193 192 } 194 193 } -
josm/core/test/unit/org/openstreetmap/josm/command/AddPrimitivesCommandTest.java
175 175 } 176 176 177 177 /** 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 } 217 218 /** 178 219 * Test {@link AddCommand#getParticipatingPrimitives()} 179 220 */ 180 221 @Test