source: josm/trunk/src/org/openstreetmap/josm/command/AddPrimitivesCommand.java@ 11608

Last change on this file since 11608 was 11553, checked in by Don-vip, 7 years ago

refactor handling of null values - use Java 8 Optional where possible

  • Property svn:eol-style set to native
File size: 7.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.command;
3
4import static org.openstreetmap.josm.tools.I18n.trn;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashSet;
9import java.util.List;
10import java.util.Objects;
11import java.util.Optional;
12
13import javax.swing.Icon;
14
15import org.openstreetmap.josm.data.osm.DataSet;
16import org.openstreetmap.josm.data.osm.Node;
17import org.openstreetmap.josm.data.osm.NodeData;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.PrimitiveData;
20import org.openstreetmap.josm.gui.layer.OsmDataLayer;
21import org.openstreetmap.josm.tools.CheckParameterUtil;
22import org.openstreetmap.josm.tools.JosmRuntimeException;
23
24/**
25 * Add primitives to a data layer.
26 * @since 2305
27 */
28public class AddPrimitivesCommand extends Command {
29
30 private List<PrimitiveData> data = new ArrayList<>();
31 private Collection<PrimitiveData> toSelect = new ArrayList<>();
32
33 // only filled on undo
34 private List<OsmPrimitive> createdPrimitives;
35 private Collection<OsmPrimitive> createdPrimitivesToSelect;
36
37 /**
38 * Constructs a new {@code AddPrimitivesCommand} to add data to the current edit layer.
39 * @param data The OSM primitives data to add. Must not be {@code null}
40 */
41 public AddPrimitivesCommand(List<PrimitiveData> data) {
42 this(data, data);
43 }
44
45 /**
46 * Constructs a new {@code AddPrimitivesCommand} to add data to the current edit layer.
47 * @param data The OSM primitives to add. Must not be {@code null}
48 * @param toSelect The OSM primitives to select at the end. Can be {@code null}
49 * @since 5953
50 */
51 public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect) {
52 init(data, toSelect);
53 }
54
55 /**
56 * Constructs a new {@code AddPrimitivesCommand} to add data to the given layer.
57 * @param data The OSM primitives data to add. Must not be {@code null}
58 * @param toSelect The OSM primitives to select at the end. Can be {@code null}
59 * @param layer The target data layer. Must not be {@code null}
60 */
61 public AddPrimitivesCommand(List<PrimitiveData> data, List<PrimitiveData> toSelect, OsmDataLayer layer) {
62 super(layer);
63 init(data, toSelect);
64 }
65
66 private void init(List<PrimitiveData> data, List<PrimitiveData> toSelect) {
67 CheckParameterUtil.ensureParameterNotNull(data, "data");
68 this.data.addAll(data);
69 if (toSelect != null) {
70 this.toSelect.addAll(toSelect);
71 }
72 }
73
74 @Override
75 public boolean executeCommand() {
76 Collection<OsmPrimitive> primitivesToSelect;
77 if (createdPrimitives == null) { // first time execution
78 List<OsmPrimitive> newPrimitives = new ArrayList<>(data.size());
79 primitivesToSelect = new ArrayList<>(toSelect.size());
80
81 for (PrimitiveData pd : data) {
82 OsmPrimitive primitive = getAffectedDataSet().getPrimitiveById(pd);
83 boolean created = primitive == null;
84 if (created) {
85 primitive = pd.getType().newInstance(pd.getUniqueId(), true);
86 }
87 if (pd instanceof NodeData) { // Load nodes immediately because they can't be added to dataset without coordinates
88 primitive.load(pd);
89 }
90 if (created) {
91 getAffectedDataSet().addPrimitive(primitive);
92 }
93 newPrimitives.add(primitive);
94 if (toSelect.contains(pd)) {
95 primitivesToSelect.add(primitive);
96 }
97 }
98
99 // Then load ways and relations
100 for (int i = 0; i < newPrimitives.size(); i++) {
101 if (!(newPrimitives.get(i) instanceof Node)) {
102 newPrimitives.get(i).load(data.get(i));
103 }
104 }
105 newPrimitives.stream().forEach(p -> p.setModified(true));
106 } else { // redo
107 // When redoing this command, we have to add the same objects, otherwise
108 // a subsequent command (e.g. MoveCommand) cannot be redone.
109 for (OsmPrimitive osm : createdPrimitives) {
110 getAffectedDataSet().addPrimitive(osm);
111 }
112 primitivesToSelect = createdPrimitivesToSelect;
113 }
114
115 getAffectedDataSet().setSelected(primitivesToSelect);
116 return true;
117 }
118
119 @Override public void undoCommand() {
120 DataSet ds = getAffectedDataSet();
121
122 if (createdPrimitives == null) {
123 createdPrimitives = new ArrayList<>(data.size());
124 createdPrimitivesToSelect = new ArrayList<>(toSelect.size());
125
126 for (PrimitiveData pd : data) {
127 OsmPrimitive p = ds.getPrimitiveById(pd);
128 createdPrimitives.add(p);
129 if (toSelect.contains(pd)) {
130 createdPrimitivesToSelect.add(p);
131 }
132 }
133 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) {
143 ds.removePrimitive(osm);
144 }
145 }
146 }
147
148 @Override
149 public String getDescriptionText() {
150 int size = data != null ? data.size() : createdPrimitives.size();
151 return trn("Added {0} object", "Added {0} objects", size, size);
152 }
153
154 @Override
155 public Icon getDescriptionIcon() {
156 return null;
157 }
158
159 @Override
160 public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted,
161 Collection<OsmPrimitive> added) {
162 // Does nothing because we don't want to create OsmPrimitives.
163 }
164
165 @Override
166 public Collection<? extends OsmPrimitive> getParticipatingPrimitives() {
167 if (createdPrimitives != null)
168 return createdPrimitives;
169
170 Collection<OsmPrimitive> prims = new HashSet<>();
171 for (PrimitiveData d : data) {
172 prims.add(Optional.ofNullable(getAffectedDataSet().getPrimitiveById(d)).orElseThrow(
173 () -> new JosmRuntimeException("No primitive found for " + d)));
174 }
175 return prims;
176 }
177
178 @Override
179 public int hashCode() {
180 return Objects.hash(super.hashCode(), data, toSelect, createdPrimitives, createdPrimitivesToSelect);
181 }
182
183 @Override
184 public boolean equals(Object obj) {
185 if (this == obj) return true;
186 if (obj == null || getClass() != obj.getClass()) return false;
187 if (!super.equals(obj)) return false;
188 AddPrimitivesCommand that = (AddPrimitivesCommand) obj;
189 return Objects.equals(data, that.data) &&
190 Objects.equals(toSelect, that.toSelect) &&
191 Objects.equals(createdPrimitives, that.createdPrimitives) &&
192 Objects.equals(createdPrimitivesToSelect, that.createdPrimitivesToSelect);
193 }
194}
Note: See TracBrowser for help on using the repository browser.