|
@@ -23,33 +23,259 @@
|
23
|
23
|
package com.dmdirc.parser.common;
|
24
|
24
|
|
25
|
25
|
import com.dmdirc.parser.interfaces.Parser;
|
|
26
|
+import com.dmdirc.parser.interfaces.SpecificCallback;
|
|
27
|
+import com.dmdirc.parser.interfaces.callbacks.AuthNoticeListener;
|
|
28
|
+import com.dmdirc.parser.interfaces.callbacks.AwayStateListener;
|
26
|
29
|
import com.dmdirc.parser.interfaces.callbacks.CallbackInterface;
|
|
30
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelActionListener;
|
|
31
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelCtcpListener;
|
|
32
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelCtcpReplyListener;
|
|
33
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelJoinListener;
|
|
34
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelKickListener;
|
|
35
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelListModeListener;
|
|
36
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelMessageListener;
|
|
37
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelModeChangeListener;
|
|
38
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelModeMessageListener;
|
|
39
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelModeNoticeListener;
|
|
40
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelNamesListener;
|
|
41
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelNickChangeListener;
|
|
42
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelNonUserModeChangeListener;
|
|
43
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelNoticeListener;
|
|
44
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelOtherAwayStateListener;
|
|
45
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelPartListener;
|
|
46
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelQuitListener;
|
|
47
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelSelfJoinListener;
|
|
48
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelSingleModeChangeListener;
|
|
49
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelTopicListener;
|
|
50
|
+import com.dmdirc.parser.interfaces.callbacks.ChannelUserModeChangeListener;
|
|
51
|
+import com.dmdirc.parser.interfaces.callbacks.CompositionStateChangeListener;
|
|
52
|
+import com.dmdirc.parser.interfaces.callbacks.ConnectErrorListener;
|
|
53
|
+import com.dmdirc.parser.interfaces.callbacks.DataInListener;
|
|
54
|
+import com.dmdirc.parser.interfaces.callbacks.DataOutListener;
|
|
55
|
+import com.dmdirc.parser.interfaces.callbacks.DebugInfoListener;
|
|
56
|
+import com.dmdirc.parser.interfaces.callbacks.ErrorInfoListener;
|
|
57
|
+import com.dmdirc.parser.interfaces.callbacks.GroupListEndListener;
|
|
58
|
+import com.dmdirc.parser.interfaces.callbacks.GroupListEntryListener;
|
|
59
|
+import com.dmdirc.parser.interfaces.callbacks.GroupListStartListener;
|
|
60
|
+import com.dmdirc.parser.interfaces.callbacks.InviteListener;
|
|
61
|
+import com.dmdirc.parser.interfaces.callbacks.MotdEndListener;
|
|
62
|
+import com.dmdirc.parser.interfaces.callbacks.MotdLineListener;
|
|
63
|
+import com.dmdirc.parser.interfaces.callbacks.MotdStartListener;
|
|
64
|
+import com.dmdirc.parser.interfaces.callbacks.NetworkDetectedListener;
|
|
65
|
+import com.dmdirc.parser.interfaces.callbacks.NickChangeListener;
|
|
66
|
+import com.dmdirc.parser.interfaces.callbacks.NickInUseListener;
|
|
67
|
+import com.dmdirc.parser.interfaces.callbacks.NumericListener;
|
|
68
|
+import com.dmdirc.parser.interfaces.callbacks.OtherAwayStateListener;
|
|
69
|
+import com.dmdirc.parser.interfaces.callbacks.PasswordRequiredListener;
|
|
70
|
+import com.dmdirc.parser.interfaces.callbacks.PingFailureListener;
|
|
71
|
+import com.dmdirc.parser.interfaces.callbacks.PingSentListener;
|
|
72
|
+import com.dmdirc.parser.interfaces.callbacks.PingSuccessListener;
|
|
73
|
+import com.dmdirc.parser.interfaces.callbacks.PrivateActionListener;
|
|
74
|
+import com.dmdirc.parser.interfaces.callbacks.PrivateCtcpListener;
|
|
75
|
+import com.dmdirc.parser.interfaces.callbacks.PrivateCtcpReplyListener;
|
|
76
|
+import com.dmdirc.parser.interfaces.callbacks.PrivateMessageListener;
|
|
77
|
+import com.dmdirc.parser.interfaces.callbacks.PrivateNoticeListener;
|
|
78
|
+import com.dmdirc.parser.interfaces.callbacks.QuitListener;
|
|
79
|
+import com.dmdirc.parser.interfaces.callbacks.ServerErrorListener;
|
|
80
|
+import com.dmdirc.parser.interfaces.callbacks.ServerNoticeListener;
|
|
81
|
+import com.dmdirc.parser.interfaces.callbacks.ServerReadyListener;
|
|
82
|
+import com.dmdirc.parser.interfaces.callbacks.SocketCloseListener;
|
|
83
|
+import com.dmdirc.parser.interfaces.callbacks.UnknownActionListener;
|
|
84
|
+import com.dmdirc.parser.interfaces.callbacks.UnknownCtcpListener;
|
|
85
|
+import com.dmdirc.parser.interfaces.callbacks.UnknownCtcpReplyListener;
|
|
86
|
+import com.dmdirc.parser.interfaces.callbacks.UnknownMessageListener;
|
|
87
|
+import com.dmdirc.parser.interfaces.callbacks.UnknownNoticeListener;
|
|
88
|
+import com.dmdirc.parser.interfaces.callbacks.UnknownServerNoticeListener;
|
|
89
|
+import com.dmdirc.parser.interfaces.callbacks.UserModeChangeListener;
|
|
90
|
+import com.dmdirc.parser.interfaces.callbacks.UserModeDiscoveryListener;
|
|
91
|
+import com.dmdirc.parser.interfaces.callbacks.WallDesyncListener;
|
|
92
|
+import com.dmdirc.parser.interfaces.callbacks.WallopListener;
|
|
93
|
+import com.dmdirc.parser.interfaces.callbacks.WalluserListener;
|
|
94
|
+
|
|
95
|
+import java.lang.reflect.InvocationHandler;
|
|
96
|
+import java.lang.reflect.Method;
|
|
97
|
+import java.lang.reflect.Proxy;
|
|
98
|
+import java.util.Collections;
|
|
99
|
+import java.util.HashMap;
|
|
100
|
+import java.util.Map;
|
27
|
101
|
|
28
|
102
|
/**
|
29
|
103
|
* Parser Callback Manager.
|
30
|
104
|
* Manages adding/removing/calling callbacks.
|
31
|
105
|
*/
|
32
|
|
-public interface CallbackManager {
|
|
106
|
+public class CallbackManager {
|
|
107
|
+
|
|
108
|
+ private static final Class<?>[] CLASSES = {
|
|
109
|
+ AwayStateListener.class,
|
|
110
|
+ OtherAwayStateListener.class,
|
|
111
|
+ ChannelOtherAwayStateListener.class,
|
|
112
|
+ ChannelActionListener.class,
|
|
113
|
+ ChannelCtcpListener.class,
|
|
114
|
+ ChannelCtcpReplyListener.class,
|
|
115
|
+ ChannelListModeListener.class,
|
|
116
|
+ ChannelNamesListener.class,
|
|
117
|
+ ChannelJoinListener.class,
|
|
118
|
+ ChannelKickListener.class,
|
|
119
|
+ ChannelMessageListener.class,
|
|
120
|
+ ChannelModeChangeListener.class,
|
|
121
|
+ ChannelNickChangeListener.class,
|
|
122
|
+ ChannelNonUserModeChangeListener.class,
|
|
123
|
+ ChannelModeMessageListener.class,
|
|
124
|
+ ChannelModeNoticeListener.class,
|
|
125
|
+ ChannelNoticeListener.class,
|
|
126
|
+ ChannelPartListener.class,
|
|
127
|
+ ChannelQuitListener.class,
|
|
128
|
+ ChannelSelfJoinListener.class,
|
|
129
|
+ ChannelSingleModeChangeListener.class,
|
|
130
|
+ ChannelTopicListener.class,
|
|
131
|
+ ChannelUserModeChangeListener.class,
|
|
132
|
+ CompositionStateChangeListener.class,
|
|
133
|
+ ConnectErrorListener.class,
|
|
134
|
+ DataInListener.class,
|
|
135
|
+ DataOutListener.class,
|
|
136
|
+ DebugInfoListener.class,
|
|
137
|
+ ErrorInfoListener.class,
|
|
138
|
+ GroupListStartListener.class,
|
|
139
|
+ GroupListEntryListener.class,
|
|
140
|
+ GroupListEndListener.class,
|
|
141
|
+ NetworkDetectedListener.class,
|
|
142
|
+ InviteListener.class,
|
|
143
|
+ MotdEndListener.class,
|
|
144
|
+ MotdLineListener.class,
|
|
145
|
+ MotdStartListener.class,
|
|
146
|
+ NickChangeListener.class,
|
|
147
|
+ NickInUseListener.class,
|
|
148
|
+ AuthNoticeListener.class,
|
|
149
|
+ NumericListener.class,
|
|
150
|
+ PasswordRequiredListener.class,
|
|
151
|
+ PingFailureListener.class,
|
|
152
|
+ PingSuccessListener.class,
|
|
153
|
+ PingSentListener.class,
|
|
154
|
+ PrivateActionListener.class,
|
|
155
|
+ PrivateCtcpListener.class,
|
|
156
|
+ PrivateCtcpReplyListener.class,
|
|
157
|
+ PrivateMessageListener.class,
|
|
158
|
+ PrivateNoticeListener.class,
|
|
159
|
+ QuitListener.class,
|
|
160
|
+ ServerErrorListener.class,
|
|
161
|
+ ServerReadyListener.class,
|
|
162
|
+ SocketCloseListener.class,
|
|
163
|
+ UnknownActionListener.class,
|
|
164
|
+ UnknownCtcpListener.class,
|
|
165
|
+ UnknownCtcpReplyListener.class,
|
|
166
|
+ UnknownMessageListener.class,
|
|
167
|
+ UnknownNoticeListener.class,
|
|
168
|
+ UserModeChangeListener.class,
|
|
169
|
+ UserModeDiscoveryListener.class,
|
|
170
|
+ WallDesyncListener.class,
|
|
171
|
+ WallopListener.class,
|
|
172
|
+ WalluserListener.class,
|
|
173
|
+ ServerNoticeListener.class,
|
|
174
|
+ UnknownServerNoticeListener.class,
|
|
175
|
+ };
|
|
176
|
+
|
|
177
|
+ /** Hashtable used to store the different types of callback known. */
|
|
178
|
+ private final Map<Class<? extends CallbackInterface>, CallbackObject> callbackHash
|
|
179
|
+ = new HashMap<>();
|
|
180
|
+
|
|
181
|
+ /** A map of implementations to use for parser interfaces. */
|
|
182
|
+ private final Map<Class<?>, Class<?>> implementationMap;
|
|
183
|
+
|
|
184
|
+ /**
|
|
185
|
+ * Constructor to create a CallbackManager.
|
|
186
|
+ *
|
|
187
|
+ * @param implementationMap A map of implementations to use
|
|
188
|
+ */
|
|
189
|
+ public CallbackManager(final Map<Class<?>, Class<?>> implementationMap) {
|
|
190
|
+ this.implementationMap = Collections.unmodifiableMap(implementationMap);
|
|
191
|
+ }
|
|
192
|
+
|
33
|
193
|
/**
|
34
|
194
|
* Initialises this callback manager.
|
35
|
195
|
*
|
36
|
196
|
* @param parser The parser associated with this CallbackManager
|
37
|
197
|
*/
|
38
|
|
- void initialise(Parser parser);
|
|
198
|
+ public void initialise(final Parser parser) {
|
|
199
|
+ for (Class<?> type : CLASSES) {
|
|
200
|
+ if (type.isAnnotationPresent(SpecificCallback.class)) {
|
|
201
|
+ addCallbackType(getSpecificCallbackObject(parser, type));
|
|
202
|
+ } else {
|
|
203
|
+ addCallbackType(getCallbackObject(parser, type));
|
|
204
|
+ }
|
|
205
|
+ }
|
|
206
|
+ }
|
|
207
|
+
|
|
208
|
+ /**
|
|
209
|
+ * Retrieves a relevant {@link CallbackObject} for the specified type.
|
|
210
|
+ *
|
|
211
|
+ * @param parser The parser that this manager belongs to
|
|
212
|
+ * @param type The type of callback to create an object for
|
|
213
|
+ * @return The relevant CallbackObject
|
|
214
|
+ */
|
|
215
|
+ protected CallbackObject getCallbackObject(final Parser parser, final Class<?> type) {
|
|
216
|
+ return new CallbackObject(parser, this, type.asSubclass(CallbackInterface.class),
|
|
217
|
+ implementationMap);
|
|
218
|
+ }
|
|
219
|
+
|
|
220
|
+ /**
|
|
221
|
+ * Retrieves a relevant {@link CallbackObjectSpecific} for the specified type.
|
|
222
|
+ *
|
|
223
|
+ * @param parser The parser that this manager belongs to
|
|
224
|
+ * @param type The type of callback to create an object for
|
|
225
|
+ * @return The relevant CallbackObject
|
|
226
|
+ */
|
|
227
|
+ protected CallbackObjectSpecific getSpecificCallbackObject(
|
|
228
|
+ final Parser parser, final Class<?> type) {
|
|
229
|
+ return new CallbackObjectSpecific(parser, this, type.asSubclass(CallbackInterface.class),
|
|
230
|
+ implementationMap);
|
|
231
|
+ }
|
|
232
|
+
|
|
233
|
+ /**
|
|
234
|
+ * Add new callback type.
|
|
235
|
+ *
|
|
236
|
+ * @param callback CallbackObject subclass for the callback.
|
|
237
|
+ */
|
|
238
|
+ private void addCallbackType(final CallbackObject callback) {
|
|
239
|
+ if (!callbackHash.containsKey(callback.getType())) {
|
|
240
|
+ callbackHash.put(callback.getType(), callback);
|
|
241
|
+ }
|
|
242
|
+ }
|
|
243
|
+
|
|
244
|
+ /**
|
|
245
|
+ * Get reference to callback object.
|
|
246
|
+ *
|
|
247
|
+ * @param callback Name of type of callback object.
|
|
248
|
+ * @return CallbackObject returns the callback object for this type
|
|
249
|
+ */
|
|
250
|
+ private CallbackObject getCallbackType(final Class<? extends CallbackInterface> callback) {
|
|
251
|
+ if (!callbackHash.containsKey(callback)) {
|
|
252
|
+ throw new CallbackNotFoundException("Callback not found: " + callback.getName());
|
|
253
|
+ }
|
|
254
|
+
|
|
255
|
+ return callbackHash.get(callback);
|
|
256
|
+ }
|
39
|
257
|
|
40
|
258
|
/**
|
41
|
259
|
* Remove all callbacks associated with a specific object.
|
42
|
260
|
*
|
43
|
261
|
* @param o instance of ICallbackInterface to remove.
|
44
|
262
|
*/
|
45
|
|
- void delAllCallback(CallbackInterface o);
|
|
263
|
+ public void delAllCallback(final CallbackInterface o) {
|
|
264
|
+ callbackHash.values().stream()
|
|
265
|
+ .filter(cb -> cb != null && cb.getType().isInstance(o))
|
|
266
|
+ .forEach(cb -> cb.del(o));
|
|
267
|
+ }
|
46
|
268
|
|
47
|
269
|
/**
|
48
|
270
|
* Add all callbacks that this object implements.
|
49
|
271
|
*
|
50
|
272
|
* @param o instance of ICallbackInterface to add.
|
51
|
273
|
*/
|
52
|
|
- void addAllCallback(CallbackInterface o);
|
|
274
|
+ public void addAllCallback(final CallbackInterface o) {
|
|
275
|
+ callbackHash.values().stream()
|
|
276
|
+ .filter(cb -> cb != null && cb.getType().isInstance(o))
|
|
277
|
+ .forEach(cb -> cb.add(o));
|
|
278
|
+ }
|
53
|
279
|
|
54
|
280
|
/**
|
55
|
281
|
* Add a callback.
|
|
@@ -61,8 +287,18 @@ public interface CallbackManager {
|
61
|
287
|
* @throws CallbackNotFoundException If callback is not found.
|
62
|
288
|
* @throws NullPointerException If 'o' is null
|
63
|
289
|
*/
|
64
|
|
- <S extends CallbackInterface> void addCallback(Class<S> callback, S o)
|
65
|
|
- throws CallbackNotFoundException;
|
|
290
|
+ public <S extends CallbackInterface> void addCallback(
|
|
291
|
+ final Class<S> callback, final S o) throws CallbackNotFoundException {
|
|
292
|
+ if (o == null) {
|
|
293
|
+ throw new NullPointerException("CallbackInterface is null");
|
|
294
|
+ }
|
|
295
|
+
|
|
296
|
+ final CallbackObject cb = getCallbackType(callback);
|
|
297
|
+
|
|
298
|
+ if (cb != null) {
|
|
299
|
+ cb.add(o);
|
|
300
|
+ }
|
|
301
|
+ }
|
66
|
302
|
|
67
|
303
|
/**
|
68
|
304
|
* Add a callback with a specific target.
|
|
@@ -75,8 +311,15 @@ public interface CallbackManager {
|
75
|
311
|
* @throws CallbackNotFoundException If callback is not found.
|
76
|
312
|
* @throws NullPointerException If 'o' is null
|
77
|
313
|
*/
|
78
|
|
- <S extends CallbackInterface> void addCallback(Class<S> callback, S o, String target)
|
79
|
|
- throws CallbackNotFoundException;
|
|
314
|
+ public <S extends CallbackInterface> void addCallback(
|
|
315
|
+ final Class<S> callback,
|
|
316
|
+ final S o, final String target) throws CallbackNotFoundException {
|
|
317
|
+ if (o == null) {
|
|
318
|
+ throw new NullPointerException("CallbackInterface is null");
|
|
319
|
+ }
|
|
320
|
+
|
|
321
|
+ ((CallbackObjectSpecific) getCallbackType(callback)).add(o, target);
|
|
322
|
+ }
|
80
|
323
|
|
81
|
324
|
/**
|
82
|
325
|
* Remove a callback.
|
|
@@ -84,7 +327,10 @@ public interface CallbackManager {
|
84
|
327
|
* @param callback Type of callback object.
|
85
|
328
|
* @param o instance of ICallbackInterface to remove.
|
86
|
329
|
*/
|
87
|
|
- void delCallback(Class<? extends CallbackInterface> callback, CallbackInterface o);
|
|
330
|
+ public void delCallback(final Class<? extends CallbackInterface> callback,
|
|
331
|
+ final CallbackInterface o) {
|
|
332
|
+ getCallbackType(callback).del(o);
|
|
333
|
+ }
|
88
|
334
|
|
89
|
335
|
/**
|
90
|
336
|
* Gets a proxy object which can be used to despatch callbacks of the
|
|
@@ -97,5 +343,33 @@ public interface CallbackManager {
|
97
|
343
|
* @return A proxy object which can be used to call the specified callback
|
98
|
344
|
*/
|
99
|
345
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
100
|
|
- <T extends CallbackInterface> T getCallback(Class<T> callback);
|
|
346
|
+ public <T extends CallbackInterface> T getCallback(final Class<T> callback) {
|
|
347
|
+ return (T) Proxy.newProxyInstance(getClass().getClassLoader(),
|
|
348
|
+ new Class[]{ callback }, new CallbackHandler(callback));
|
|
349
|
+ }
|
|
350
|
+
|
|
351
|
+ /**
|
|
352
|
+ * A Proxy invocation handler for a specified parser callback.
|
|
353
|
+ */
|
|
354
|
+ private class CallbackHandler implements InvocationHandler {
|
|
355
|
+
|
|
356
|
+ /** The callback that should be called. */
|
|
357
|
+ private final Class<? extends CallbackInterface> callback;
|
|
358
|
+
|
|
359
|
+ /**
|
|
360
|
+ * Creates a new callback handler for the specified callback.
|
|
361
|
+ *
|
|
362
|
+ * @param callback The callback to handle
|
|
363
|
+ */
|
|
364
|
+ public CallbackHandler(final Class<? extends CallbackInterface> callback) {
|
|
365
|
+ this.callback = callback;
|
|
366
|
+ }
|
|
367
|
+
|
|
368
|
+ @Override
|
|
369
|
+ public Object invoke(final Object proxy, final Method method, final Object[] args) {
|
|
370
|
+ getCallbackType(callback).call(args);
|
|
371
|
+ return null;
|
|
372
|
+ }
|
|
373
|
+
|
|
374
|
+ }
|
101
|
375
|
}
|