1 package org.djutils.event.util;
2
3 import java.io.Serializable;
4 import java.rmi.RemoteException;
5 import java.util.Collection;
6
7 import org.djutils.event.EventInterface;
8 import org.djutils.event.EventListenerInterface;
9 import org.djutils.event.EventProducer;
10 import org.djutils.event.EventType;
11 import org.djutils.event.IdProvider;
12 import org.djutils.event.ref.ReferenceType;
13 import org.djutils.exceptions.Throw;
14 import org.djutils.metadata.MetaData;
15 import org.djutils.metadata.ObjectDescriptor;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 public class EventProducingCollection<T> extends EventProducer implements EventListenerInterface, Collection<T>
34 {
35
36 private static final long serialVersionUID = 20191230L;
37
38
39 public static final EventType OBJECT_ADDED_EVENT =
40 new EventType("OBJECT_ADDED_EVENT", new MetaData("Size of the collection after add", "Size of the collection",
41 new ObjectDescriptor("Size of the collection after add", "Size of the collection", Integer.class)));
42
43
44 public static final EventType OBJECT_REMOVED_EVENT =
45 new EventType("OBJECT_REMOVED_EVENT", new MetaData("Size of the collection after remove", "Size of the collection",
46 new ObjectDescriptor("Size of the collection after remove", "Size of the collection", Integer.class)));
47
48
49 public static final EventType OBJECT_CHANGED_EVENT =
50 new EventType("OBJECT_CHANGED_EVENT", new MetaData("Size of the collection after change", "Size of the collection",
51 new ObjectDescriptor("Size of the collection after change", "Size of the collection", Integer.class)));
52
53
54 private Collection<T> parent = null;
55
56
57 private final IdProvider sourceIdProvider;
58
59
60
61
62
63
64 public EventProducingCollection(final Collection<T> parent, final Serializable sourceId)
65 {
66 this(parent, new IdProvider()
67 {
68
69 private static final long serialVersionUID = 20200119L;
70
71 @Override
72 public Serializable id()
73 {
74 return sourceId;
75 }
76 });
77 }
78
79
80
81
82
83
84
85 public EventProducingCollection(final Collection<T> parent, final IdProvider sourceIdProvider)
86 {
87 Throw.whenNull(parent, "parent cannot be null");
88 Throw.whenNull(sourceIdProvider, "sourceIdprovider cannot be null");
89 this.parent = parent;
90 this.sourceIdProvider = sourceIdProvider;
91 }
92
93
94 @Override
95 public Serializable getSourceId()
96 {
97 return this.sourceIdProvider.id();
98 }
99
100
101 @Override
102 public int size()
103 {
104 return this.parent.size();
105 }
106
107
108 @Override
109 public boolean isEmpty()
110 {
111 return this.parent.isEmpty();
112 }
113
114
115 @Override
116 public void clear()
117 {
118 int nr = this.parent.size();
119 this.parent.clear();
120 if (nr != this.parent.size())
121 {
122 this.fireEvent(OBJECT_REMOVED_EVENT, this.parent.size());
123 }
124 }
125
126
127 @Override
128 public boolean add(final T o)
129 {
130 boolean changed = this.parent.add(o);
131 if (changed)
132 {
133 this.fireEvent(OBJECT_ADDED_EVENT, this.parent.size());
134 }
135 else
136 {
137 this.fireEvent(OBJECT_CHANGED_EVENT, this.parent.size());
138 }
139 return changed;
140 }
141
142
143 @Override
144 public boolean addAll(final Collection<? extends T> c)
145 {
146 boolean changed = this.parent.addAll(c);
147 if (changed)
148 {
149 this.fireEvent(OBJECT_ADDED_EVENT, this.parent.size());
150 }
151 else
152 {
153 if (!c.isEmpty())
154 {
155 this.fireEvent(OBJECT_CHANGED_EVENT, this.parent.size());
156 }
157 }
158 return changed;
159 }
160
161
162 @Override
163 public boolean contains(final Object o)
164 {
165 return this.parent.contains(o);
166 }
167
168
169 @Override
170 public boolean containsAll(final Collection<?> c)
171 {
172 return this.parent.containsAll(c);
173 }
174
175
176 @Override
177 public EventProducingIterator<T> iterator()
178 {
179 EventProducingIterator<T> iterator = new EventProducingIterator<T>(this.parent.iterator(), this.sourceIdProvider);
180
181 iterator.addListener(this, EventProducingIterator.OBJECT_REMOVED_EVENT, ReferenceType.WEAK);
182 return iterator;
183 }
184
185
186 @Override
187 public void notify(final EventInterface event) throws RemoteException
188 {
189
190 if (event.getType().equals(EventProducingIterator.OBJECT_REMOVED_EVENT))
191 {
192 this.fireEvent(OBJECT_REMOVED_EVENT, this.parent.size());
193 }
194 }
195
196
197 @Override
198 public boolean remove(final Object o)
199 {
200 boolean changed = this.parent.remove(o);
201 if (changed)
202 {
203 this.fireEvent(OBJECT_REMOVED_EVENT, this.parent.size());
204 }
205 return changed;
206 }
207
208
209 @Override
210 public boolean removeAll(final Collection<?> c)
211 {
212 boolean changed = this.parent.removeAll(c);
213 if (changed)
214 {
215 this.fireEvent(OBJECT_REMOVED_EVENT, this.parent.size());
216 }
217 return changed;
218 }
219
220
221 @Override
222 public boolean retainAll(final Collection<?> c)
223 {
224 boolean changed = this.parent.retainAll(c);
225 if (changed)
226 {
227 this.fireEvent(OBJECT_REMOVED_EVENT, this.parent.size());
228 }
229 return changed;
230 }
231
232
233 @Override
234 public Object[] toArray()
235 {
236 return this.parent.toArray();
237 }
238
239
240 @Override
241 public <E> E[] toArray(final E[] a)
242 {
243 return this.parent.toArray(a);
244 }
245 }