Skip to contentPackage: MessageBusHelper$MethodAdapter
MessageBusHelper$MethodAdapter
Coverage
1: /*
2: * *********************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
23: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.messagebus;
28:
29: import java.lang.annotation.Annotation;
30: import java.lang.reflect.Method;
31: import javax.annotation.Nonnull;
32: import java.util.ArrayList;
33: import java.util.List;
34: import it.tidalwave.messagebus.annotation.ListensTo;
35: import it.tidalwave.messagebus.annotation.SimpleMessageSubscriber;
36: import lombok.RequiredArgsConstructor;
37: import lombok.extern.slf4j.Slf4j;
38: import static it.tidalwave.messagebus.spi.ReflectionUtils.*;
39: import static it.tidalwave.messagebus.spi.ReflectionUtils.MethodProcessor.FilterResult.*;
40:
41: /***********************************************************************************************************************
42: *
43: * @author Fabrizio Giudici
44: *
45: **********************************************************************************************************************/
46: @RequiredArgsConstructor @Slf4j
47: public class MessageBusHelper
48: {
49: /*******************************************************************************************************************
50: *
51: *
52: *
53: ******************************************************************************************************************/
54: public static interface Adapter
55: {
56: @Nonnull
57: public <TOPIC> MethodAdapter<TOPIC> createMethodAdapter (@Nonnull Object object,
58: @Nonnull Method method,
59: @Nonnull Class<TOPIC> topic);
60:
61: public void publish (@Nonnull Object message);
62:
63: public <TOPIC> void publish (Class<TOPIC> topic, @Nonnull TOPIC message);
64: }
65:
66: /*******************************************************************************************************************
67: *
68: *
69: *
70: ******************************************************************************************************************/
71: public static interface MethodAdapter<TOPIC>
72: {
73: public void subscribe();
74:
75: public void unsubscribe();
76: }
77:
78: @Nonnull
79: private final Object owner;
80:
81: @Nonnull
82: private final Adapter methodAdapterFactory;
83:
84: private final List<MethodAdapter<?>> methodAdapters = new ArrayList<>();
85:
86: /*******************************************************************************************************************
87: *
88: *
89: *
90: ******************************************************************************************************************/
91: public void subscribeAll()
92: {
93: forEachMethodInTopDownHierarchy(owner, new MethodProcessor()
94: {
95: @Override @Nonnull
96: public FilterResult filter (@Nonnull final Class<?> clazz)
97: {
98: return clazz.getAnnotation(SimpleMessageSubscriber.class) != null ? ACCEPT : IGNORE;
99: }
100:
101: @Override
102: public void process (@Nonnull final Method method)
103: {
104: final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
105:
106: if ((parameterAnnotations.length == 1) && containsAnnotation(parameterAnnotations[0], ListensTo.class))
107: {
108: registerMessageListener(method);
109: }
110: }
111: });
112: }
113:
114: /*******************************************************************************************************************
115: *
116: *
117: *
118: ******************************************************************************************************************/
119: public void unsubscribeAll()
120: {
121: for (final MethodAdapter<?> methodAdapter : methodAdapters)
122: {
123: methodAdapter.unsubscribe();
124: }
125: }
126:
127: /*******************************************************************************************************************
128: *
129: * Publishes a message.
130: *
131: * @param message the message to deliver
132: *
133: ******************************************************************************************************************/
134: public void publish (@Nonnull final Object message)
135: {
136: methodAdapterFactory.publish(message);
137: }
138:
139: /*******************************************************************************************************************
140: *
141: * Publishes a message.
142: *
143: * @param <TOPIC> the static type of the topic
144: * @param topicType the dynamic type of the topic
145: * @param topic the topic
146: *
147: ******************************************************************************************************************/
148: public <TOPIC> void publish (@Nonnull final Class<TOPIC> topicType, @Nonnull final TOPIC topic)
149: {
150: methodAdapterFactory.publish(topicType, topic);
151: }
152:
153: /*******************************************************************************************************************
154: *
155: ******************************************************************************************************************/
156: private <TOPIC> void registerMessageListener (@Nonnull final Method method)
157: {
158: log.trace("registerMessageListener({})", method);
159:
160: final Class<TOPIC> topic = (Class<TOPIC>)method.getParameterTypes()[0];
161: final MethodAdapter<TOPIC> methodAdapter = methodAdapterFactory.createMethodAdapter(owner, method, topic);
162: methodAdapters.add(methodAdapter);
163: methodAdapter.subscribe();
164: }
165: }