source: josm/trunk/src/org/openstreetmap/josm/data/conflict/ConflictCollection.java@ 9101

Last change on this file since 9101 was 9067, checked in by Don-vip, 8 years ago

sonar - Immutable Field

  • Property svn:eol-style set to native
File size: 12.4 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.conflict;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashSet;
9import java.util.Iterator;
10import java.util.List;
11import java.util.Set;
12import java.util.concurrent.CopyOnWriteArrayList;
13
14import org.openstreetmap.josm.data.osm.Node;
15import org.openstreetmap.josm.data.osm.OsmPrimitive;
16import org.openstreetmap.josm.data.osm.Relation;
17import org.openstreetmap.josm.data.osm.Way;
18import org.openstreetmap.josm.tools.CheckParameterUtil;
19import org.openstreetmap.josm.tools.Predicate;
20import org.openstreetmap.josm.tools.Utils;
21
22/**
23 * This is a collection of {@link Conflict}s. This collection is {@link Iterable}, i.e.
24 * it can be used in <code>for</code>-loops as follows:
25 * <pre>
26 * ConflictCollection conflictCollection = ....
27 *
28 * for (Conflict c : conflictCollection) {
29 * // do something
30 * }
31 * </pre>
32 *
33 * This collection emits an event when the content of the collection changes. You can register
34 * and unregister for these events using:
35 * <ul>
36 * <li>{@link #addConflictListener(IConflictListener)}</li>
37 * <li>{@link #removeConflictListener(IConflictListener)}</li>
38 * </ul>
39 */
40public class ConflictCollection implements Iterable<Conflict<? extends OsmPrimitive>> {
41 private final List<Conflict<? extends OsmPrimitive>> conflicts;
42 private final CopyOnWriteArrayList<IConflictListener> listeners;
43
44 private static class FilterPredicate implements Predicate<Conflict<? extends OsmPrimitive>> {
45
46 private final Class<? extends OsmPrimitive> c;
47
48 FilterPredicate(Class<? extends OsmPrimitive> c) {
49 this.c = c;
50 }
51
52 @Override
53 public boolean evaluate(Conflict<? extends OsmPrimitive> conflict) {
54 return conflict != null && c.isInstance(conflict.getMy());
55 }
56 }
57
58 private static final FilterPredicate NODE_FILTER_PREDICATE = new FilterPredicate(Node.class);
59 private static final FilterPredicate WAY_FILTER_PREDICATE = new FilterPredicate(Way.class);
60 private static final FilterPredicate RELATION_FILTER_PREDICATE = new FilterPredicate(Relation.class);
61
62 /**
63 * Constructs a new {@code ConflictCollection}.
64 */
65 public ConflictCollection() {
66 conflicts = new ArrayList<>();
67 listeners = new CopyOnWriteArrayList<>();
68 }
69
70 /**
71 * Adds the specified conflict listener, if not already present.
72 * @param listener The conflict listener to add
73 */
74 public void addConflictListener(IConflictListener listener) {
75 if (listener != null) {
76 listeners.addIfAbsent(listener);
77 }
78 }
79
80 /**
81 * Removes the specified conflict listener.
82 * @param listener The conflict listener to remove
83 */
84 public void removeConflictListener(IConflictListener listener) {
85 listeners.remove(listener);
86 }
87
88 protected void fireConflictAdded() {
89 for (IConflictListener listener : listeners) {
90 listener.onConflictsAdded(this);
91 }
92 }
93
94 protected void fireConflictRemoved() {
95 for (IConflictListener listener : listeners) {
96 listener.onConflictsRemoved(this);
97 }
98 }
99
100 /**
101 * Adds a conflict to the collection
102 *
103 * @param conflict the conflict
104 * @throws IllegalStateException if this collection already includes a conflict for conflict.getMy()
105 */
106 protected void addConflict(Conflict<?> conflict) {
107 if (hasConflictForMy(conflict.getMy()))
108 throw new IllegalStateException(tr("Already registered a conflict for primitive ''{0}''.", conflict.getMy().toString()));
109 if (!conflicts.contains(conflict)) {
110 conflicts.add(conflict);
111 }
112 }
113
114 /**
115 * Adds a conflict to the collection of conflicts.
116 *
117 * @param conflict the conflict to add. Must not be null.
118 * @throws IllegalArgumentException if conflict is null
119 * @throws IllegalStateException if this collection already includes a conflict for conflict.getMy()
120 */
121 public void add(Conflict<?> conflict) {
122 CheckParameterUtil.ensureParameterNotNull(conflict, "conflict");
123 addConflict(conflict);
124 fireConflictAdded();
125 }
126
127 /**
128 * Add the conflicts in <code>otherConflicts</code> to this collection of conflicts
129 *
130 * @param otherConflicts the collection of conflicts. Does nothing is conflicts is null.
131 */
132 public void add(Collection<Conflict<?>> otherConflicts) {
133 if (otherConflicts == null) return;
134 for (Conflict<?> c : otherConflicts) {
135 addConflict(c);
136 }
137 fireConflictAdded();
138 }
139
140 /**
141 * Adds a conflict for the pair of {@link OsmPrimitive}s given by <code>my</code> and
142 * <code>their</code>.
143 *
144 * @param my my primitive
145 * @param their their primitive
146 */
147 public void add(OsmPrimitive my, OsmPrimitive their) {
148 addConflict(new Conflict<>(my, their));
149 fireConflictAdded();
150 }
151
152 /**
153 * removes a conflict from this collection
154 *
155 * @param conflict the conflict
156 */
157 public void remove(Conflict<?> conflict) {
158 conflicts.remove(conflict);
159 fireConflictRemoved();
160 }
161
162 /**
163 * removes the conflict registered for {@link OsmPrimitive} <code>my</code> if any
164 *
165 * @param my the primitive
166 */
167 public void remove(OsmPrimitive my) {
168 Iterator<Conflict<?>> it = iterator();
169 while (it.hasNext()) {
170 if (it.next().isMatchingMy(my)) {
171 it.remove();
172 }
173 }
174 fireConflictRemoved();
175 }
176
177 /**
178 * Replies the conflict for the {@link OsmPrimitive} <code>my</code>, null
179 * if no such conflict exists.
180 *
181 * @param my my primitive
182 * @return the conflict for the {@link OsmPrimitive} <code>my</code>, null
183 * if no such conflict exists.
184 */
185 public Conflict<?> getConflictForMy(OsmPrimitive my) {
186 for (Conflict<?> c : conflicts) {
187 if (c.isMatchingMy(my))
188 return c;
189 }
190 return null;
191 }
192
193 /**
194 * Replies the conflict for the {@link OsmPrimitive} <code>their</code>, null
195 * if no such conflict exists.
196 *
197 * @param their their primitive
198 * @return the conflict for the {@link OsmPrimitive} <code>their</code>, null
199 * if no such conflict exists.
200 */
201 public Conflict<?> getConflictForTheir(OsmPrimitive their) {
202 for (Conflict<?> c : conflicts) {
203 if (c.isMatchingTheir(their))
204 return c;
205 }
206 return null;
207 }
208
209 /**
210 * Replies true, if this collection includes a conflict for <code>my</code>.
211 *
212 * @param my my primitive
213 * @return true, if this collection includes a conflict for <code>my</code>; false, otherwise
214 */
215 public boolean hasConflictForMy(OsmPrimitive my) {
216 return getConflictForMy(my) != null;
217 }
218
219 /**
220 * Replies true, if this collection includes a given conflict
221 *
222 * @param c the conflict
223 * @return true, if this collection includes the conflict; false, otherwise
224 */
225 public boolean hasConflict(Conflict<?> c) {
226 return hasConflictForMy(c.getMy());
227 }
228
229 /**
230 * Replies true, if this collection includes a conflict for <code>their</code>.
231 *
232 * @param their their primitive
233 * @return true, if this collection includes a conflict for <code>their</code>; false, otherwise
234 */
235 public boolean hasConflictForTheir(OsmPrimitive their) {
236 return getConflictForTheir(their) != null;
237 }
238
239 /**
240 * Removes any conflicts for the {@link OsmPrimitive} <code>my</code>.
241 *
242 * @param my the primitive
243 */
244 public void removeForMy(OsmPrimitive my) {
245 Iterator<Conflict<?>> it = iterator();
246 while (it.hasNext()) {
247 if (it.next().isMatchingMy(my)) {
248 it.remove();
249 }
250 }
251 }
252
253 /**
254 * Removes any conflicts for the {@link OsmPrimitive} <code>their</code>.
255 *
256 * @param their the primitive
257 */
258 public void removeForTheir(OsmPrimitive their) {
259 Iterator<Conflict<?>> it = iterator();
260 while (it.hasNext()) {
261 if (it.next().isMatchingTheir(their)) {
262 it.remove();
263 }
264 }
265 }
266
267 /**
268 * Replies the conflicts as list.
269 *
270 * @return the list of conflicts
271 */
272 public List<Conflict<?>> get() {
273 return conflicts;
274 }
275
276 /**
277 * Replies the size of the collection
278 *
279 * @return the size of the collection
280 */
281 public int size() {
282 return conflicts.size();
283 }
284
285 /**
286 * Replies the conflict at position <code>idx</code>
287 *
288 * @param idx the index
289 * @return the conflict at position <code>idx</code>
290 */
291 public Conflict<?> get(int idx) {
292 return conflicts.get(idx);
293 }
294
295 /**
296 * Replies the iterator for this collection.
297 *
298 * @return the iterator
299 */
300 @Override
301 public Iterator<Conflict<?>> iterator() {
302 return conflicts.iterator();
303 }
304
305 /**
306 * Adds all conflicts from another collection.
307 * @param other The other collection of conflicts to add
308 */
309 public void add(ConflictCollection other) {
310 for (Conflict<?> c : other) {
311 add(c);
312 }
313 }
314
315 /**
316 * Replies the set of {@link OsmPrimitive} which participate in the role
317 * of "my" in the conflicts managed by this collection.
318 *
319 * @return the set of {@link OsmPrimitive} which participate in the role
320 * of "my" in the conflicts managed by this collection.
321 */
322 public Set<OsmPrimitive> getMyConflictParties() {
323 Set<OsmPrimitive> ret = new HashSet<>();
324 for (Conflict<?> c: conflicts) {
325 ret.add(c.getMy());
326 }
327 return ret;
328 }
329
330 /**
331 * Replies the set of {@link OsmPrimitive} which participate in the role
332 * of "their" in the conflicts managed by this collection.
333 *
334 * @return the set of {@link OsmPrimitive} which participate in the role
335 * of "their" in the conflicts managed by this collection.
336 */
337 public Set<OsmPrimitive> getTheirConflictParties() {
338 Set<OsmPrimitive> ret = new HashSet<>();
339 for (Conflict<?> c: conflicts) {
340 ret.add(c.getTheir());
341 }
342 return ret;
343 }
344
345 /**
346 * Replies true if this collection is empty
347 *
348 * @return true, if this collection is empty; false, otherwise
349 */
350 public boolean isEmpty() {
351 return size() == 0;
352 }
353
354 @Override
355 public String toString() {
356 return conflicts.toString();
357 }
358
359 /**
360 * Returns the list of conflicts involving nodes.
361 * @return The list of conflicts involving nodes.
362 * @since 6555
363 */
364 public final Collection<Conflict<? extends OsmPrimitive>> getNodeConflicts() {
365 return Utils.filter(conflicts, NODE_FILTER_PREDICATE);
366 }
367
368 /**
369 * Returns the list of conflicts involving nodes.
370 * @return The list of conflicts involving nodes.
371 * @since 6555
372 */
373 public final Collection<Conflict<? extends OsmPrimitive>> getWayConflicts() {
374 return Utils.filter(conflicts, WAY_FILTER_PREDICATE);
375 }
376
377 /**
378 * Returns the list of conflicts involving nodes.
379 * @return The list of conflicts involving nodes.
380 * @since 6555
381 */
382 public final Collection<Conflict<? extends OsmPrimitive>> getRelationConflicts() {
383 return Utils.filter(conflicts, RELATION_FILTER_PREDICATE);
384 }
385
386 @Override
387 public int hashCode() {
388 final int prime = 31;
389 int result = 1;
390 result = prime * result + ((conflicts == null) ? 0 : conflicts.hashCode());
391 result = prime * result + ((listeners == null) ? 0 : listeners.hashCode());
392 return result;
393 }
394
395 @Override
396 public boolean equals(Object obj) {
397 if (this == obj)
398 return true;
399 if (obj == null)
400 return false;
401 if (getClass() != obj.getClass())
402 return false;
403 ConflictCollection other = (ConflictCollection) obj;
404 if (conflicts == null) {
405 if (other.conflicts != null)
406 return false;
407 } else if (!conflicts.equals(other.conflicts))
408 return false;
409 if (listeners == null) {
410 if (other.listeners != null)
411 return false;
412 } else if (!listeners.equals(other.listeners))
413 return false;
414 return true;
415 }
416}
Note: See TracBrowser for help on using the repository browser.