source: josm/trunk/src/org/openstreetmap/josm/data/osm/ChangesetDataSet.java@ 14947

Last change on this file since 14947 was 14947, checked in by GerdP, 5 years ago

fix findBugs issue SIC_INNER_SHOULD_BE_STATIC_NEEDS_THIS

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.util.Collections;
6import java.util.HashMap;
7import java.util.Iterator;
8import java.util.Map;
9import java.util.Map.Entry;
10import java.util.Set;
11
12import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
13import org.openstreetmap.josm.tools.CheckParameterUtil;
14import org.openstreetmap.josm.tools.Logging;
15
16/**
17 * A ChangesetDataSet holds the content of a changeset. Typically, a primitive is modified only once in a changeset,
18 * but if there are multiple modifications, the first and last are kept. Further intermediate versions are not kept.
19 */
20public class ChangesetDataSet {
21
22 /**
23 * Type of primitive modification.
24 */
25 public enum ChangesetModificationType {
26 /** The primitive has been created */
27 CREATED,
28 /** The primitive has been updated */
29 UPDATED,
30 /** The primitive has been deleted */
31 DELETED
32 }
33
34 /**
35 * An entry in the changeset dataset.
36 */
37 public interface ChangesetDataSetEntry {
38
39 /**
40 * Returns the type of modification.
41 * @return the type of modification
42 */
43 ChangesetModificationType getModificationType();
44
45 /**
46 * Returns the affected history primitive.
47 * @return the affected history primitive
48 */
49 HistoryOsmPrimitive getPrimitive();
50 }
51
52 /** maps an id to either one {@link ChangesetDataSetEntry} or an array of {@link ChangesetDataSetEntry} */
53 private final Map<PrimitiveId, Object> entryMap = new HashMap<>();
54
55 /**
56 * Remembers a history primitive with the given modification type
57 *
58 * @param primitive the primitive. Must not be null.
59 * @param cmt the modification type. Must not be null.
60 * @throws IllegalArgumentException if primitive is null
61 * @throws IllegalArgumentException if cmt is null
62 * @throws IllegalArgumentException if the same primitive was already stored with a higher or equal version
63 */
64 public void put(HistoryOsmPrimitive primitive, ChangesetModificationType cmt) {
65 CheckParameterUtil.ensureParameterNotNull(primitive, "primitive");
66 CheckParameterUtil.ensureParameterNotNull(cmt, "cmt");
67 DefaultChangesetDataSetEntry csEntry = new DefaultChangesetDataSetEntry(cmt, primitive);
68 Object val = entryMap.get(primitive.getPrimitiveId());
69 ChangesetDataSetEntry[] entries;
70 if (val == null) {
71 entryMap.put(primitive.getPrimitiveId(), csEntry);
72 return;
73 }
74 if (val instanceof ChangesetDataSetEntry) {
75 entries = new ChangesetDataSetEntry[2];
76 entries[0] = (ChangesetDataSetEntry) val;
77 if (primitive.getVersion() <= entries[0].getPrimitive().getVersion()) {
78 throw new IllegalArgumentException(
79 tr("Changeset {0}: Unexpected order of versions for {1}: v{2} is not higher than v{3}",
80 String.valueOf(primitive.getChangesetId()), primitive.getPrimitiveId(),
81 primitive.getVersion(), entries[0].getPrimitive().getVersion()));
82 }
83 } else {
84 entries = (ChangesetDataSetEntry[]) val;
85 }
86 if (entries[1] != null) {
87 Logging.info("Changeset {0}: Change of {1} v{2} is replaced by version v{3}",
88 String.valueOf(primitive.getChangesetId()), primitive.getPrimitiveId(),
89 entries[1].getPrimitive().getVersion(), primitive.getVersion());
90 }
91 entries[1] = csEntry;
92 entryMap.put(primitive.getPrimitiveId(), entries);
93 }
94
95 /**
96 * Replies true if the changeset content contains the object with primitive <code>id</code>.
97 * @param id the id.
98 * @return true if the changeset content contains the object with primitive <code>id</code>
99 */
100 public boolean contains(PrimitiveId id) {
101 if (id == null) return false;
102 return entryMap.containsKey(id);
103 }
104
105 /**
106 * Replies the last modification type for the object with id <code>id</code>. Replies null, if id is null or
107 * if the object with id <code>id</code> isn't in the changeset content.
108 *
109 * @param id the id
110 * @return the last modification type or null
111 */
112 public ChangesetModificationType getModificationType(PrimitiveId id) {
113 ChangesetDataSetEntry e = getLastEntry(id);
114 return e != null ? e.getModificationType() : null;
115 }
116
117 /**
118 * Replies true if the primitive with id <code>id</code> was created in this
119 * changeset. Replies false, if id is null or not in the dataset.
120 *
121 * @param id the id
122 * @return true if the primitive with id <code>id</code> was created in this
123 * changeset.
124 */
125 public boolean isCreated(PrimitiveId id) {
126 ChangesetDataSetEntry e = getFirstEntry(id);
127 return e != null && e.getModificationType() == ChangesetModificationType.CREATED;
128 }
129
130 /**
131 * Replies true if the primitive with id <code>id</code> was updated in this
132 * changeset. Replies false, if id is null or not in the dataset.
133 *
134 * @param id the id
135 * @return true if the primitive with id <code>id</code> was updated in this
136 * changeset.
137 */
138 public boolean isUpdated(PrimitiveId id) {
139 ChangesetDataSetEntry e = getLastEntry(id);
140 return e != null && e.getModificationType() == ChangesetModificationType.UPDATED;
141 }
142
143 /**
144 * Replies true if the primitive with id <code>id</code> was deleted in this
145 * changeset. Replies false, if id is null or not in the dataset.
146 *
147 * @param id the id
148 * @return true if the primitive with id <code>id</code> was deleted in this
149 * changeset.
150 */
151 public boolean isDeleted(PrimitiveId id) {
152 ChangesetDataSetEntry e = getLastEntry(id);
153 return e != null && e.getModificationType() == ChangesetModificationType.DELETED;
154 }
155
156 /**
157 * Replies the number of primitives in the dataset.
158 *
159 * @return the number of primitives in the dataset.
160 */
161 public int size() {
162 return entryMap.size();
163 }
164
165 /**
166 * Replies the {@link HistoryOsmPrimitive} with id <code>id</code> from this dataset.
167 * null, if there is no such primitive in the data set. If the primitive was modified
168 * multiple times, the last version is returned.
169 *
170 * @param id the id
171 * @return the {@link HistoryOsmPrimitive} with id <code>id</code> from this dataset
172 */
173 public HistoryOsmPrimitive getPrimitive(PrimitiveId id) {
174 ChangesetDataSetEntry e = getLastEntry(id);
175 return e != null ? e.getPrimitive() : null;
176 }
177
178 /**
179 * @return an unmodifiable set of all primitives in this dataset.
180 * @since 14946
181 */
182 public Set<PrimitiveId> getIds() {
183 return Collections.unmodifiableSet(entryMap.keySet());
184 }
185
186 /**
187 * Replies the first {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset.
188 * null, if there is no such primitive in the data set.
189 * @param id the id
190 * @return the first {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset or null.
191 * @since 14946
192 */
193 public ChangesetDataSetEntry getFirstEntry(PrimitiveId id) {
194 if (id == null)
195 return null;
196 Object val = entryMap.get(id);
197 if (val == null)
198 return null;
199 if (val instanceof ChangesetDataSetEntry[]) {
200 ChangesetDataSetEntry[] entries = (ChangesetDataSetEntry[]) val;
201 return entries[0];
202 } else {
203 return (ChangesetDataSetEntry) val;
204 }
205 }
206
207 /**
208 * Replies the last {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset.
209 * null, if there is no such primitive in the data set.
210 * @param id the id
211 * @return the last {@link ChangesetDataSetEntry} with id <code>id</code> from this dataset or null.
212 * @since 14946
213 */
214 public ChangesetDataSetEntry getLastEntry(PrimitiveId id) {
215 if (id == null)
216 return null;
217 Object val = entryMap.get(id);
218 if (val == null)
219 return null;
220 if (val instanceof ChangesetDataSetEntry[]) {
221 ChangesetDataSetEntry[] entries = (ChangesetDataSetEntry[]) val;
222 return entries[1];
223 } else {
224 return (ChangesetDataSetEntry) val;
225 }
226 }
227
228 /**
229 * Returns an iterator over dataset entries. The elements are returned in no particular order.
230 * @return an iterator over dataset entries. If a primitive was changed multiple times, only the last entry is returned.
231 */
232 public Iterator<ChangesetDataSetEntry> iterator() {
233 return new DefaultIterator(entryMap);
234 }
235
236 /**
237 * Class to keep one entry of a changeset: the combination of modification type and primitive.
238 */
239 public static class DefaultChangesetDataSetEntry implements ChangesetDataSetEntry {
240 private final ChangesetModificationType modificationType;
241 private final HistoryOsmPrimitive primitive;
242
243 /**
244 * Construct new entry.
245 * @param modificationType the modification type
246 * @param primitive the primitive
247 */
248 public DefaultChangesetDataSetEntry(ChangesetModificationType modificationType, HistoryOsmPrimitive primitive) {
249 this.modificationType = modificationType;
250 this.primitive = primitive;
251 }
252
253 @Override
254 public ChangesetModificationType getModificationType() {
255 return modificationType;
256 }
257
258 @Override
259 public HistoryOsmPrimitive getPrimitive() {
260 return primitive;
261 }
262
263 @Override
264 public String toString() {
265 return modificationType.toString() + " " + primitive.toString();
266 }
267 }
268
269 private static class DefaultIterator implements Iterator<ChangesetDataSetEntry> {
270 private final Iterator<Entry<PrimitiveId, Object>> typeIterator;
271
272 DefaultIterator(Map<PrimitiveId, Object> entryMap) {
273 typeIterator = entryMap.entrySet().iterator();
274 }
275
276 @Override
277 public boolean hasNext() {
278 return typeIterator.hasNext();
279 }
280
281 @Override
282 public ChangesetDataSetEntry next() {
283 Entry<PrimitiveId, Object> next = typeIterator.next();
284 // get last entry
285 Object val = next.getValue();
286 ChangesetDataSetEntry last;
287 if (val instanceof ChangesetDataSetEntry[]) {
288 ChangesetDataSetEntry[] entries = (ChangesetDataSetEntry[]) val;
289 last = entries[1];
290 } else {
291 last = (ChangesetDataSetEntry) val;
292 }
293 return new DefaultChangesetDataSetEntry(last.getModificationType(), last.getPrimitive());
294 }
295
296 @Override
297 public void remove() {
298 throw new UnsupportedOperationException();
299 }
300 }
301}
Note: See TracBrowser for help on using the repository browser.