package org.jvalue.ods.notifications.sender; import com.google.common.base.Objects; import org.jvalue.ods.api.notifications.Client; import org.jvalue.ods.api.notifications.ClientVisitor; import org.jvalue.ods.api.notifications.GcmClient; import org.jvalue.ods.api.notifications.HttpClient; import org.jvalue.ods.api.sources.DataSource; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; /** * Cache for {@link Sender} instance while data * is being streamed to clients. */ public final class SenderCache { private final Map<SenderKey, Sender<?>> senderMap = new HashMap<>(); private final SenderCreatorVisitor senderCreatorVisitor; @Inject public SenderCache(SenderFactory senderFactory) { this.senderCreatorVisitor = new SenderCreatorVisitor(senderFactory); } @SuppressWarnings("unchecked") public <T extends Client> Sender<T> get(DataSource source, T client) { SenderKey key = new SenderKey(source, client); if (!senderMap.containsKey(key)) senderMap.put(key, client.accept(senderCreatorVisitor, source)); return (Sender<T>) senderMap.get(key); } public void release(DataSource source, Client client) { SenderKey key = new SenderKey(source, client); senderMap.remove(key); } private static final class SenderCreatorVisitor implements ClientVisitor<DataSource, Sender<?>> { private final SenderFactory senderFactory; public SenderCreatorVisitor(SenderFactory senderFactory) { this.senderFactory = senderFactory; } @Override public Sender<GcmClient> visit(GcmClient client, DataSource source) { return senderFactory.createGcmSender(source, client); } @Override public Sender<HttpClient> visit(HttpClient client, DataSource source) { return senderFactory.createHttpSender(source, client); } } private static final class SenderKey { private final Client client; private final DataSource source; public SenderKey(DataSource source, Client client) { this.source = source; this.client = client; } @Override public boolean equals(Object other) { if (other == null || !(other instanceof SenderKey)) return false; if (other == this) return true; SenderKey key = (SenderKey) other; return Objects.equal(client, key.client) && Objects.equal(source, key.source); } @Override public int hashCode() { return Objects.hashCode(client, source); } } }