package com.dhemery.publishing;
import java.lang.reflect.Method;
import java.util.*;
/**
* A channel through which subscribers receive publications via methods annotated by {@link Subscribe}.
*/
public class MethodSubscriptionChannel implements Channel {
private final Map<Class<?>,Set<Subscription>> subscriptionsByPublicationType = new HashMap<Class<?>, Set<Subscription>>();
private final SubscriberInspector discover = new SubscriberInspector();
/**
* Create a method subscription channel with no subscribers.
*/
public MethodSubscriptionChannel(){}
@Override
public void subscribe(Object subscriber) {
Set<Method> methods = discover.subscriptionsOn(subscriber);
for(Method method : methods) {
Class<?> publicationType = method.getParameterTypes()[0];
subscriptionsForPublicationType(publicationType).add(new MethodSubscription(subscriber, method));
}
}
@Override
public void subscribe(Object subscriber1, Object... others) {
subscribe(subscriber1);
for(Object subscriber : Arrays.asList(others)) {
subscribe(subscriber);
}
}
@Override
public void unsubscribe(Object subscriber) {
}
@Override
public void unsubscribe(Object subscriber1, Object... others) {
}
@Override
public void publish(Object publication) {
Set<Subscription> subscriptions = subscriptionsForPublication(publication);
for(Subscription subscription : subscriptions) {
subscription.deliver(publication);
}
}
private Set<Subscription> subscriptionsForPublication(Object publication) {
Class<?> publicationType = publication.getClass();
return subscriptionsForPublicationType(publicationType);
}
private Set<Subscription> subscriptionsForPublicationType(Class<?> publicationType) {
if(!subscriptionsByPublicationType.containsKey(publicationType)) {
Set<Subscription> subscriptions = new HashSet<Subscription>();
subscriptionsByPublicationType.put(publicationType, subscriptions);
}
return subscriptionsByPublicationType.get(publicationType);
}
}