package mightypork.utils.patterns.subscription; import java.util.LinkedHashSet; import java.util.Set; import mightypork.utils.logging.Log; /** * An event bus, accommodating multiple {@link MessageChannel}s. * * @author MightyPork */ public class MessageBus implements Subscribable { private Set> channels = new LinkedHashSet>(); private Set clients = new LinkedHashSet(); private boolean warn_unsent = true; /** * Add a {@link MessageChannel} to this bus.
* If a channel of matching types is already added, it is returned instead. * * @param channel channel to be added * @return the channel that's now in the bus */ public MessageChannel addChannel(MessageChannel channel) { // if the channel already exists, return this instance instead. for (MessageChannel ch : channels) { if (ch.equals(channel)) { Log.w("Channel of type " + channel + " already registered."); return ch; } } channels.add(channel); for (Object c : clients) { channel.addSubscriber(c); } return channel; } /** * Remove a {@link MessageChannel} from this bus * * @param channel true if channel was removed */ public void removeChannel(MessageChannel channel) { channels.remove(channel); for (Object c : clients) { channel.removeSubscriber(c); } } /** * Broadcast a message * * @param message message * @return true if message was accepted by at least one channel */ public boolean broadcast(Object message) { boolean sent = false; for (MessageChannel b : channels) { sent |= b.broadcast(message); } if (!sent && warn_unsent) Log.w("Message not accepted by any channel: " + message); return sent; } /** * Subscribe a client to the bus. The client will be connected to all * current and future channels, until removed from the bus. * * @return true on success */ @Override public boolean addSubscriber(Object client) { if (client == null) return false; for (MessageChannel b : channels) { b.addSubscriber(client); } clients.add(client); return true; } @Override public void removeSubscriber(Object client) { for (MessageChannel b : channels) { b.removeSubscriber(client); } clients.remove(client); } /** * Enable logging of unsent messages * * @param enable */ public void enableLoggingUnsent(boolean enable) { this.warn_unsent = enable; } /** * Add a channel for given message and client type. * * @param messageClass message type * @param clientClass client type * @return the created channel instance */ public , F_CLIENT> MessageChannel createChannel(Class messageClass, Class clientClass) { MessageChannel bc = new MessageChannel(messageClass, clientClass); return addChannel(bc); } }