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

Last change on this file since 2655 was 2655, checked in by jttt, 14 years ago

Fixed #4161 Major slowdown in recent versions, used correct pattern for listeners realized using CopyOnWriteArrayList

File size: 9.2 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.OsmPrimitive;
15
16/**
17 * This is a collection of {@see Conflict}s. This collection is {@see Iterable}, i.e.
18 * it can be used in <code>for</code>-loops as follows:
19 * <pre>
20 * ConflictCollection conflictCollection = ....
21 *
22 * for(Conflict c : conflictCollection) {
23 * // do something
24 * }
25 * </pre>
26 *
27 * This collection emits an event when the content of the collection changes. You can register
28 * and unregister for these events using:
29 * <ul>
30 * <li>{@see #addConflictListener(IConflictListener)}</li>
31 * <li>{@see #removeConflictListener(IConflictListener)}</li>
32 * </ul>
33 */
34public class ConflictCollection implements Iterable<Conflict<?>>{
35 private ArrayList<Conflict<?>> conflicts;
36 private CopyOnWriteArrayList<IConflictListener> listeners;
37
38 public ConflictCollection() {
39 conflicts = new ArrayList<Conflict<?>>();
40 listeners = new CopyOnWriteArrayList<IConflictListener>();
41 }
42
43 public void addConflictListener(IConflictListener listener) {
44 if (listener != null) {
45 listeners.addIfAbsent(listener);
46 }
47 }
48
49 public void removeConflictListener(IConflictListener listener) {
50 listeners.remove(listener);
51 }
52
53 protected void fireConflictAdded() {
54 for (IConflictListener listener : listeners) {
55 listener.onConflictsAdded(this);
56 }
57 }
58
59 protected void fireConflictRemoved() {
60 Iterator<IConflictListener> it = listeners.iterator();
61 while(it.hasNext()) {
62 it.next().onConflictsRemoved(this);
63 }
64 }
65
66 /**
67 * Adds a conflict to the collection
68 *
69 * @param conflict the conflict
70 * @exception IllegalStateException thrown, if this collection already includes a
71 * conflict for conflict.getMy()
72 */
73 protected void addConflict(Conflict<?> conflict) throws IllegalStateException {
74 if (hasConflictForMy(conflict.getMy()))
75 throw new IllegalStateException(tr("Already registered a conflict for primitive ''{0}''.", conflict.getMy().toString()));
76 if (!conflicts.contains(conflict)) {
77 conflicts.add(conflict);
78 }
79 }
80
81 /**
82 * Adds a conflict to the collection of conflicts.
83 *
84 * @param conflict the conflict to to add. Must not be null.
85 * @throws IllegalArgumentException thrown, if conflict is null
86 * @throws IllegalStateException thrown if this collection already includes a conflict for conflict.getMy()
87 *
88 */
89 public void add(Conflict<?> conflict) throws IllegalStateException, IllegalArgumentException {
90 if (conflict == null)
91 throw new IllegalArgumentException(tr("Parameter ''{0}'' must not be null.", "conflict"));
92 addConflict(conflict);
93 fireConflictAdded();
94 }
95
96 /**
97 * Add the conflicts in <code>otherConflicts</code> to this collection of conflicts
98 *
99 * @param otherConflicts the collection of conflicts. Does nothing is conflicts is null.
100 */
101 public void add(Collection<Conflict<?>> otherConflicts) {
102 if (otherConflicts == null) return;
103 for(Conflict<?> c : otherConflicts) {
104 addConflict(c);
105 }
106 fireConflictAdded();
107 }
108
109 /**
110 * Adds a conflict for the pair of {@see OsmPrimitive}s given by <code>my</code> and
111 * <code>their</code>.
112 *
113 * @param my my primitive
114 * @param their their primitive
115 */
116 public void add(OsmPrimitive my, OsmPrimitive their) {
117 addConflict(new Conflict<OsmPrimitive>(my, their));
118 fireConflictAdded();
119 }
120
121 /**
122 * removes a conflict from this collection
123 *
124 * @param conflict the conflict
125 */
126 public void remove(Conflict<?> conflict) {
127 conflicts.remove(conflict);
128 fireConflictRemoved();
129 }
130
131 /**
132 * removes the conflict registered for {@see OsmPrimitive} <code>my</code> if any
133 *
134 * @param my the primitive
135 */
136 public void remove(OsmPrimitive my) {
137 Iterator<Conflict<?>> it = iterator();
138 while(it.hasNext()) {
139 if (it.next().isMatchingMy(my)) {
140 it.remove();
141 }
142 }
143 fireConflictRemoved();
144 }
145
146 /**
147 * Replies the conflict for the {@see OsmPrimitive} <code>my</code>, null
148 * if no such conflict exists.
149 *
150 * @param my my primitive
151 * @return the conflict for the {@see OsmPrimitive} <code>my</code>, null
152 * if no such conflict exists.
153 */
154 public Conflict<?> getConflictForMy(OsmPrimitive my) {
155 for(Conflict<?> c : conflicts) {
156 if (c.isMatchingMy(my))
157 return c;
158 }
159 return null;
160 }
161 /**
162 * Replies the conflict for the {@see OsmPrimitive} <code>their</code>, null
163 * if no such conflict exists.
164 *
165 * @param my my primitive
166 * @return the conflict for the {@see OsmPrimitive} <code>their</code>, null
167 * if no such conflict exists.
168 */
169 public Conflict<?> getConflictForTheir(OsmPrimitive their) {
170 for(Conflict<?> c : conflicts) {
171 if (c.isMatchingTheir(their))
172 return c;
173 }
174 return null;
175 }
176
177 /**
178 * Replies true, if this collection includes a conflict for <code>my</code>.
179 *
180 * @param my my primitive
181 * @return true, if this collection includes a conflict for <code>my</code>; false, otherwise
182 */
183 public boolean hasConflictForMy(OsmPrimitive my) {
184 return getConflictForMy(my) != null;
185 }
186
187 /**
188 * Replies true, if this collection includes a given conflict
189 *
190 * @param c the conflict
191 * @return true, if this collection includes the conflict; false, otherwise
192 */
193 public boolean hasConflict(Conflict<?> c) {
194 return hasConflictForMy(c.getMy());
195 }
196
197 /**
198 * Replies true, if this collection includes a conflict for <code>their</code>.
199 *
200 * @param their their primitive
201 * @return true, if this collection includes a conflict for <code>their</code>; false, otherwise
202 */
203 public boolean hasConflictForTheir(OsmPrimitive their) {
204 return getConflictForTheir(their) != null;
205 }
206
207 /**
208 * Removes any conflicts for the {@see OsmPrimitive} <code>my</code>.
209 *
210 * @param my the primitive
211 */
212 public void removeForMy(OsmPrimitive my) {
213 Iterator<Conflict<?>> it = iterator();
214 while(it.hasNext()) {
215 if (it.next().isMatchingMy(my)) {
216 it.remove();
217 }
218 }
219 }
220
221 /**
222 * Removes any conflicts for the {@see OsmPrimitive} <code>their</code>.
223 *
224 * @param their the primitive
225 */
226 public void removeForTheir(OsmPrimitive their) {
227 Iterator<Conflict<?>> it = iterator();
228 while(it.hasNext()) {
229 if (it.next().isMatchingTheir(their)) {
230 it.remove();
231 }
232 }
233 }
234
235 /**
236 * Replies the conflicts as list.
237 *
238 * @return the list of conflicts
239 */
240 public List<Conflict<?>> get() {
241 return conflicts;
242 }
243
244 /**
245 * Replies the size of the collection
246 *
247 * @return the size of the collection
248 */
249 public int size() {
250 return conflicts.size();
251 }
252
253 /**
254 * Replies the conflict at position <code>idx</code>
255 *
256 * @param idx the index
257 * @return the conflict at position <code>idx</code>
258 */
259 public Conflict<?> get(int idx) {
260 return conflicts.get(idx);
261 }
262
263 /**
264 * Replies the iterator for this collection.
265 *
266 * @return the iterator
267 */
268 public Iterator<Conflict<?>> iterator() {
269 return conflicts.iterator();
270 }
271
272 public void add(ConflictCollection other) {
273 for (Conflict<?> c : other) {
274 add(c);
275 }
276 }
277
278 /**
279 * Replies the set of {@see OsmPrimitive} which participate in the role
280 * of "my" in the conflicts managed by this collection.
281 *
282 * @return the set of {@see OsmPrimitive} which participate in the role
283 * of "my" in the conflicts managed by this collection.
284 */
285 public Set<OsmPrimitive> getMyConflictParties() {
286 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
287 for (Conflict<?> c: conflicts) {
288 ret.add(c.getMy());
289 }
290 return ret;
291 }
292 /**
293 * Replies the set of {@see OsmPrimitive} which participate in the role
294 * of "their" in the conflicts managed by this collection.
295 *
296 * @return the set of {@see OsmPrimitive} which participate in the role
297 * of "their" in the conflicts managed by this collection.
298 */
299 public Set<OsmPrimitive> getTheirConflictParties() {
300 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
301 for (Conflict<?> c: conflicts) {
302 ret.add(c.getTheir());
303 }
304 return ret;
305 }
306
307 /**
308 * Replies true if this collection is empty
309 *
310 * @return true, if this collection is empty; false, otherwise
311 */
312 public boolean isEmpty() {
313 return size() == 0;
314 }
315}
Note: See TracBrowser for help on using the repository browser.