io.vlingo.actors.pubsub.Subscriptions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vlingo-actors Show documentation
Show all versions of vlingo-actors Show documentation
Type safe Actor Model toolkit for reactive concurrency and resiliency using Java and other JVM languages.
// Copyright © 2012-2020 VLINGO LABS. All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain
// one at https://mozilla.org/MPL/2.0/.
package io.vlingo.actors.pubsub;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Subscriptions {
private Map>> index = new HashMap<>();
public AffectedSubscriptions create(final Topic topic, final Subscriber> subscriber) {
if(!index.containsKey(topic)) {
index.put(topic, new HashSet<>());
}
return performOperation(topic, subscriber, defaultCondition(), insertOperation());
}
public AffectedSubscriptions cancel(final Topic topic, final Subscriber> subscriber) {
return performOperation(topic, subscriber, defaultCondition(), removalOperation());
}
public AffectedSubscriptions cancelAll(final Subscriber> subscriber) {
return performOperation(null, subscriber, noCondition(), removalOperation());
}
public Set> forTopic(final Topic topic) {
final Set> subscribers = new HashSet<>();
index.entrySet().forEach(subscription -> {
final Topic subscribedTopic = subscription.getKey();
if(subscribedTopic.equals(topic) || subscribedTopic.isSubTopic(topic)) {
subscribers.addAll(subscription.getValue());
}
});
return subscribers;
}
private Operation insertOperation() {
return (existingValues, givenValue) -> existingValues.add(givenValue);
}
private Operation removalOperation() {
return (existingValues, givenValue) -> existingValues.remove(givenValue);
}
private Condition defaultCondition() {
return (subscription, topic, subscriber) -> subscription.getKey().equals(topic);
}
private Condition noCondition() {
return (subscription, topic, subscriber) -> true;
}
private AffectedSubscriptions performOperation(final Topic topic, final Subscriber> subscriber, final Condition condition, final Operation operation) {
final AffectedSubscriptions affectedSubscriptions = new AffectedSubscriptions();
index.entrySet().forEach(subscription -> {
if(condition.should(subscription, topic, subscriber) &&
operation.perform(subscription.getValue(), subscriber)) {
affectedSubscriptions.add(topic, subscriber);
}
});
return affectedSubscriptions;
}
@FunctionalInterface
private interface Operation {
boolean perform(final Set> existingSubscriber, final Subscriber> givenSubscriber);
}
@FunctionalInterface
private interface Condition {
boolean should(final Entry>> subscription, final Topic topic, final Subscriber> subscriber);
}
}