Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
EventGroup |
|
| 2.0;2 |
1 | /* | |
2 | * $Id: EventGroup.java 7963 2007-08-21 08:53:15Z dirk.olmes $ | |
3 | * -------------------------------------------------------------------------------------- | |
4 | * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com | |
5 | * | |
6 | * The software in this package is published under the terms of the CPAL v1.0 | |
7 | * license, a copy of which has been included with this distribution in the | |
8 | * LICENSE.txt file. | |
9 | */ | |
10 | ||
11 | package org.mule.routing.inbound; | |
12 | ||
13 | import org.mule.umo.UMOEvent; | |
14 | import org.mule.util.ClassUtils; | |
15 | ||
16 | import java.io.Serializable; | |
17 | import java.util.ArrayList; | |
18 | import java.util.Iterator; | |
19 | import java.util.List; | |
20 | ||
21 | import edu.emory.mathcs.backport.java.util.concurrent.helpers.Utils; | |
22 | import org.apache.commons.collections.IteratorUtils; | |
23 | ||
24 | /** | |
25 | * <code>EventGroup</code> is a holder over events grouped by a common group Id. | |
26 | * This can be used by components such as routers to managed related events. | |
27 | */ | |
28 | // @ThreadSafe | |
29 | public class EventGroup implements Comparable, Serializable | |
30 | { | |
31 | /** | |
32 | * Serial version | |
33 | */ | |
34 | private static final long serialVersionUID = 953739659615692697L; | |
35 | ||
36 | 2 | public static final UMOEvent[] EMPTY_EVENTS_ARRAY = new UMOEvent[0]; |
37 | ||
38 | private final Object groupId; | |
39 | // @GuardedBy("this") | |
40 | private final List events; | |
41 | private final long created; | |
42 | private final int expectedSize; | |
43 | ||
44 | public EventGroup(Object groupId) | |
45 | { | |
46 | 38 | this(groupId, -1); |
47 | 38 | } |
48 | ||
49 | public EventGroup(Object groupId, int expectedSize) | |
50 | { | |
51 | 38 | super(); |
52 | 38 | this.created = Utils.nanoTime(); |
53 | 38 | this.events = new ArrayList(expectedSize > 0 ? expectedSize : 10); |
54 | 38 | this.expectedSize = expectedSize; |
55 | 38 | this.groupId = groupId; |
56 | 38 | } |
57 | ||
58 | /** | |
59 | * Compare this EventGroup to another one. If the receiver and the argument both | |
60 | * have groupIds that are {@link Comparable}, they are used for the comparison; | |
61 | * otherwise - since the id can be any object - the group creation time stamp is | |
62 | * used as fallback. Older groups are considered "smaller". | |
63 | * | |
64 | * @see java.lang.Comparable#compareTo(java.lang.Object) | |
65 | */ | |
66 | public int compareTo(Object o) | |
67 | { | |
68 | 16 | EventGroup other = (EventGroup) o; |
69 | 14 | Object otherId = other.getGroupId(); |
70 | ||
71 | 12 | if (groupId instanceof Comparable && otherId instanceof Comparable) |
72 | { | |
73 | 8 | return ((Comparable) groupId).compareTo(otherId); |
74 | } | |
75 | else | |
76 | { | |
77 | 4 | long diff = created - other.getCreated(); |
78 | 4 | return (diff > 0 ? 1 : (diff < 0 ? -1 : 0)); |
79 | } | |
80 | } | |
81 | ||
82 | /** | |
83 | * Compares two EventGroups for equality. EventGroups are considered equal when | |
84 | * their groupIds (as returned by {@link #getGroupId()}) are equal. | |
85 | * | |
86 | * @see java.lang.Object#equals(Object) | |
87 | */ | |
88 | // @Override | |
89 | public boolean equals(Object obj) | |
90 | { | |
91 | 20 | if (this == obj) |
92 | { | |
93 | 0 | return true; |
94 | } | |
95 | ||
96 | 20 | if (!(obj instanceof EventGroup)) |
97 | { | |
98 | 0 | return false; |
99 | } | |
100 | ||
101 | 20 | final EventGroup other = (EventGroup) obj; |
102 | 20 | if (groupId == null) |
103 | { | |
104 | 0 | return (other.groupId == null); |
105 | } | |
106 | ||
107 | 20 | return groupId.equals(other.groupId); |
108 | } | |
109 | ||
110 | /** | |
111 | * The hashCode of an EventGroup is derived from the object returned by | |
112 | * {@link #getGroupId()}. | |
113 | * | |
114 | * @see java.lang.Object#hashCode() | |
115 | */ | |
116 | // @Override | |
117 | public int hashCode() | |
118 | { | |
119 | 20 | return groupId.hashCode(); |
120 | } | |
121 | ||
122 | /** | |
123 | * Returns an identifier for this EventGroup. It is recommended that this id is | |
124 | * unique and {@link Comparable} e.g. a UUID. | |
125 | * | |
126 | * @return the id of this event group | |
127 | */ | |
128 | public Object getGroupId() | |
129 | { | |
130 | 24 | return groupId; |
131 | } | |
132 | ||
133 | /** | |
134 | * Returns an iterator over a snapshot copy of this group's collected events. If | |
135 | * you need to iterate over the group and e.g. remove select events, do so via | |
136 | * {@link #removeEvent(UMOEvent)}. If you need to do so atomically in order to | |
137 | * prevent e.g. concurrent reception/aggregation of the group during iteration, | |
138 | * wrap the iteration in a synchronized block on the group instance. | |
139 | * | |
140 | * @return an iterator over collected {@link UMOEvent}s. | |
141 | */ | |
142 | public Iterator iterator() | |
143 | { | |
144 | 10 | synchronized (this) |
145 | { | |
146 | 10 | if (events.isEmpty()) |
147 | { | |
148 | 2 | return IteratorUtils.emptyIterator(); |
149 | } | |
150 | else | |
151 | { | |
152 | 8 | return IteratorUtils.arrayIterator(this.toArray()); |
153 | } | |
154 | 0 | } |
155 | } | |
156 | ||
157 | /** | |
158 | * Returns a snapshot of collected events in this group. | |
159 | * | |
160 | * @return an array of collected {@link UMOEvent}s. | |
161 | */ | |
162 | public UMOEvent[] toArray() | |
163 | { | |
164 | 14 | synchronized (this) |
165 | { | |
166 | 14 | if (events.isEmpty()) |
167 | { | |
168 | 0 | return EMPTY_EVENTS_ARRAY; |
169 | } | |
170 | ||
171 | 14 | return (UMOEvent[]) events.toArray(EMPTY_EVENTS_ARRAY); |
172 | 0 | } |
173 | } | |
174 | ||
175 | /** | |
176 | * Add the given event to this group. | |
177 | * | |
178 | * @param event the event to add | |
179 | */ | |
180 | public void addEvent(UMOEvent event) | |
181 | { | |
182 | 34 | synchronized (this) |
183 | { | |
184 | 34 | events.add(event); |
185 | 34 | } |
186 | 34 | } |
187 | ||
188 | /** | |
189 | * Remove the given event from the group. | |
190 | * | |
191 | * @param event the evnt to remove | |
192 | */ | |
193 | public void removeEvent(UMOEvent event) | |
194 | { | |
195 | 0 | synchronized (this) |
196 | { | |
197 | 0 | events.remove(event); |
198 | 0 | } |
199 | 0 | } |
200 | ||
201 | /** | |
202 | * Return the creation timestamp of the current group. | |
203 | * | |
204 | * @return the timestamp when this group was instantiated. | |
205 | * @see {@link Utils#nanoTime()} | |
206 | */ | |
207 | public long getCreated() | |
208 | { | |
209 | 4 | return created; |
210 | } | |
211 | ||
212 | /** | |
213 | * Returns the number of events collected so far. | |
214 | * | |
215 | * @return number of events in this group or 0 if the group is empty. | |
216 | */ | |
217 | public int size() | |
218 | { | |
219 | 8 | synchronized (this) |
220 | { | |
221 | 8 | return events.size(); |
222 | 0 | } |
223 | } | |
224 | ||
225 | /** | |
226 | * Returns the number of events that this EventGroup is expecting before | |
227 | * correlation can proceed. | |
228 | * | |
229 | * @return expected number of events or -1 if no expected size was specified. | |
230 | */ | |
231 | public int expectedSize() | |
232 | { | |
233 | 0 | return expectedSize; |
234 | } | |
235 | ||
236 | /** | |
237 | * Removes all events from this group. | |
238 | */ | |
239 | public void clear() | |
240 | { | |
241 | 0 | synchronized (this) |
242 | { | |
243 | 0 | events.clear(); |
244 | 0 | } |
245 | 0 | } |
246 | ||
247 | // @Override | |
248 | public String toString() | |
249 | { | |
250 | 6 | StringBuffer buf = new StringBuffer(80); |
251 | 6 | buf.append(ClassUtils.getSimpleName(this.getClass())); |
252 | 6 | buf.append(" {"); |
253 | 6 | buf.append("id=").append(groupId); |
254 | 6 | buf.append(", expected size=").append(expectedSize); |
255 | ||
256 | 6 | synchronized (this) |
257 | { | |
258 | 6 | int currentSize = events.size(); |
259 | 6 | buf.append(", current events=").append(currentSize); |
260 | ||
261 | 6 | if (currentSize > 0) |
262 | { | |
263 | 4 | buf.append(" ["); |
264 | 4 | Iterator i = events.iterator(); |
265 | 10 | while (i.hasNext()) |
266 | { | |
267 | 6 | UMOEvent event = (UMOEvent) i.next(); |
268 | 6 | buf.append(event.getMessage().getUniqueId()); |
269 | 6 | if (i.hasNext()) |
270 | { | |
271 | 2 | buf.append(", "); |
272 | } | |
273 | 6 | } |
274 | 4 | buf.append(']'); |
275 | } | |
276 | 6 | } |
277 | ||
278 | 6 | buf.append('}'); |
279 | ||
280 | 6 | return buf.toString(); |
281 | } | |
282 | ||
283 | } |