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

Last change on this file since 10308 was 9371, checked in by simon04, 8 years ago

Java 7: use Objects.equals and Objects.hash

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