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

Last change on this file since 13818 was 10715, checked in by simon04, 8 years ago

see #11390, see #12890 - Deprecate Predicates class

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