Skip to contentPackage: MessageSupport$Exclusions
MessageSupport$Exclusions
Coverage
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2024 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 the License.
12: * 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 an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.actor;
27:
28: import javax.annotation.Nonnegative;
29: import javax.annotation.Nonnull;
30: import javax.inject.Provider;
31: import java.util.Optional;
32: import java.util.Timer;
33: import java.util.TimerTask;
34: import java.util.concurrent.TimeUnit;
35: import java.io.Serializable;
36: import it.tidalwave.actor.impl.DefaultCollaboration;
37: import it.tidalwave.actor.impl.Locator;
38: import it.tidalwave.actor.spi.CollaborationAwareMessageBus;
39: import it.tidalwave.util.As;
40: import lombok.EqualsAndHashCode;
41: import lombok.experimental.Delegate;
42: import lombok.extern.slf4j.Slf4j;
43: import static it.tidalwave.actor.MessageDecorator._MessageDecorator_;
44:
45: /***************************************************************************************************************************************************************
46: *
47: * A support class for implementing messages.
48: *
49: * @stereotype Message
50: *
51: * @author Fabrizio Giudici
52: *
53: **************************************************************************************************************************************************************/
54: @Slf4j @EqualsAndHashCode(of = "collaboration")
55: public abstract class MessageSupport implements Collaboration.Provider, As, Serializable
56: {
57: // TODO: @Inject
58: private final Provider<CollaborationAwareMessageBus> messageBus =
59: Locator.createProviderFor(CollaborationAwareMessageBus.class);
60:
61: @Nonnull
62: protected final DefaultCollaboration collaboration;
63:
64: private final MessageDecorator sameMessageDecorator = new MessageDecorator.Same<>(this);
65:
66: interface Exclusions
67: {
68: public <T> T maybeAs (Class<? extends T> type);
69: }
70:
71: @Delegate(excludes = Exclusions.class)
72: private final As as = As.forObject(this);
73:
74: /***********************************************************************************************************************************************************
75: *
76: **********************************************************************************************************************************************************/
77: protected MessageSupport()
78: {
79: this.collaboration = DefaultCollaboration.getOrCreateCollaboration(this);
80: }
81:
82: /***********************************************************************************************************************************************************
83: * @param collaboration the collaboration
84: **********************************************************************************************************************************************************/
85: protected MessageSupport (@Nonnull final Collaboration collaboration)
86: {
87: this.collaboration = (DefaultCollaboration)collaboration;
88: }
89:
90: /***********************************************************************************************************************************************************
91: * Returns the {@link Collaboration} that this message is part of.
92: *
93: * @return the {@code Collaboration}
94: **********************************************************************************************************************************************************/
95: @Override @Nonnull
96: public Collaboration getCollaboration()
97: {
98: return collaboration;
99: }
100:
101: /***********************************************************************************************************************************************************
102: * Sends this message, eventually performing a replacement (see {@link MessageDecorator} for further info).
103: *
104: * @return the {@code Collaboration} that this message is part of
105: **********************************************************************************************************************************************************/
106: @Nonnull @SuppressWarnings("UnusedReturnValue")
107: public Collaboration send()
108: {
109: log.debug("send() - {}", this);
110: return findDecoratedMessage().sendDirectly();
111: }
112:
113: /***********************************************************************************************************************************************************
114: * Sends this message directly, not performing any replacement (see {@link MessageDecorator} for further info).
115: *
116: * @return the {@code Collaboration} that this message is part of
117: **********************************************************************************************************************************************************/
118: @Nonnull
119: public Collaboration sendDirectly()
120: {
121: log.debug("sendDirectly() - {}", this);
122: collaboration.registerDeliveringMessage(this);
123: messageBus.get().publish(this);
124: return collaboration;
125: }
126:
127: /***********************************************************************************************************************************************************
128: * Sends this message after a delay, eventually performing a replacement (see {@link MessageDecorator} for
129: * further info).
130: *
131: * @param delay the delay
132: * @param timeUnit the {@link TimeUnit} for the delay
133: * @return the {@code Collaboration} that this message is part of
134: **********************************************************************************************************************************************************/
135: @Nonnull
136: public Collaboration sendLater (@Nonnegative final int delay, @Nonnull final TimeUnit timeUnit)
137: {
138: log.debug("sendLater({}, {}) - {}", delay, timeUnit, this);
139: final var message = findDecoratedMessage();
140: collaboration.registerDeliveringMessage(message);
141:
142: new Timer().schedule(new TimerTask()
143: {
144: @Override
145: public void run()
146: {
147: messageBus.get().publish(message);
148: }
149: }, TimeUnit.MILLISECONDS.convert(delay, timeUnit));
150:
151: return collaboration;
152: }
153:
154: /***********************************************************************************************************************************************************
155: * {@inheritDoc}
156: **********************************************************************************************************************************************************/
157: @Override @Nonnull
158: public <T> Optional<T> maybeAs (@Nonnull final Class<? extends T> type)
159: {
160: final Optional<T> t = as.maybeAs(type);
161:
162: return t.isPresent()
163: ? t
164: : type.equals(MessageDecorator.class) ? Optional.of(type.cast(sameMessageDecorator)) : Optional.empty();
165: }
166:
167: /***********************************************************************************************************************************************************
168: *
169: **********************************************************************************************************************************************************/
170: @Nonnull
171: private MessageSupport findDecoratedMessage()
172: {
173: final var decoratedMessage = this.as(_MessageDecorator_).getDecoratedMessage();
174: return (decoratedMessage == this) ? this : decoratedMessage.findDecoratedMessage();
175: // MessageSupport decoratedMessage = this.as(_MessageDecorator_).getDecoratedMessage();
176: //
177: // if (decoratedMessage != this)
178: // {
179: // log.info("MESSAGE HAS BEEN DECORATED: {} -> {}", this, decoratedMessage);
180: // decoratedMessage = decoratedMessage.findDecoratedMessage();
181: // }
182: //
183: // return decoratedMessage;
184: }
185: }