1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package fulmine.util.collection;
17
18 import java.util.Collection;
19 import java.util.Iterator;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.Map.Entry;
23
24 import fulmine.IAddressable;
25 import fulmine.util.reference.is;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public abstract class AbstractCoalescingCollection<E extends IAddressable>
44 implements Collection<E>
45 {
46
47
48
49
50
51
52
53
54
55
56
57 private final class DelegateIterator implements Iterator<E>
58 {
59 private final Iterator<Entry<Object, E>> delegate;
60
61 private DelegateIterator(Iterator<Entry<Object, E>> delegate)
62 {
63 super();
64 this.delegate = delegate;
65 }
66
67 public boolean hasNext()
68 {
69 return delegate.hasNext();
70 }
71
72 public E next()
73 {
74 return delegate.next().getValue();
75 }
76
77 public void remove()
78 {
79 delegate.remove();
80 }
81 }
82
83 protected final Map<Object, E> data;
84
85
86
87
88
89
90
91 protected AbstractCoalescingCollection(Map<Object, E> data)
92 {
93 this.data = data;
94 }
95
96 public boolean add(E e)
97 {
98 Object sysId = AbstractCoalescingCollection.getSystemIdentity(e);
99 final E value = this.data.put(sysId, e);
100 return value == null || value != e;
101 }
102
103 public boolean addAll(Collection<? extends E> c)
104 {
105 boolean changed = false;
106 if (c != null)
107 {
108 for (E e : c)
109 {
110 changed |= add(e);
111 }
112 }
113 return changed;
114 }
115
116 public void clear()
117 {
118 this.data.clear();
119 }
120
121 public boolean contains(Object o)
122 {
123 return this.data.containsKey(AbstractCoalescingCollection.getSystemIdentity(o));
124 }
125
126 public boolean containsAll(Collection<?> c)
127 {
128 return this.data.values().containsAll(c);
129 }
130
131 public boolean isEmpty()
132 {
133 return this.data.isEmpty();
134 }
135
136 public Iterator<E> iterator()
137 {
138 return new DelegateIterator(this.data.entrySet().iterator());
139 }
140
141 public boolean remove(Object o)
142 {
143 return this.data.remove(AbstractCoalescingCollection.getSystemIdentity(o)) != null;
144 }
145
146 public boolean removeAll(Collection<?> c)
147 {
148 boolean changed = false;
149 if (c != null)
150 {
151 for (Object object : c)
152 {
153 changed |= remove(object);
154 }
155 }
156 return changed;
157 }
158
159
160
161
162
163
164 public boolean retainAll(Collection<?> c)
165 {
166 throw new UnsupportedOperationException();
167 }
168
169 public int size()
170 {
171 return this.data.size();
172 }
173
174 public Object[] toArray()
175 {
176 Object[] array = new Object[this.data.size()];
177 final Set<Entry<Object, E>> entrySet = this.data.entrySet();
178 int i = 0;
179 for (Entry<Object, E> entry : entrySet)
180 {
181 array[i++] = entry.getValue();
182 }
183 return array;
184 }
185
186 @SuppressWarnings("unchecked")
187 public <T> T[] toArray(T[] array)
188 {
189 final Set<Entry<Object, E>> entrySet = this.data.entrySet();
190 int i = 0;
191 for (Entry<Object, E> entry : entrySet)
192 {
193 array[i++] = (T) entry.getValue();
194 }
195 return array;
196 }
197
198 @Override
199 public final String toString()
200 {
201 return getClass().getSimpleName()
202 + CollectionUtils.toFormattedString(this.data.keySet()).toString();
203 }
204
205 @Override
206 public final int hashCode()
207 {
208 final int prime = 31;
209 int result = 1;
210 result =
211 prime * result + ((this.data == null) ? 0 : this.data.hashCode());
212 return result;
213 }
214
215 @SuppressWarnings("unchecked")
216 @Override
217 public final boolean equals(Object obj)
218 {
219 if (is.same(this, obj))
220 {
221 return true;
222 }
223 if (!(obj instanceof AbstractCoalescingCollection))
224 {
225 return false;
226 }
227 final AbstractCoalescingCollection other =
228 (AbstractCoalescingCollection) obj;
229 return is.eq(this.data, other.data);
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243
244 public static final String getSystemIdentity(Object object)
245 {
246 if (object instanceof IAddressable)
247 {
248 final IAddressable addressable = ((IAddressable) object);
249 return addressable.getAddress();
250 }
251 final int identityHashCode = System.identityHashCode(object);
252 return Integer.toString(identityHashCode);
253 }
254
255 }