package netflix.karyon.transport.interceptor;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author Nitesh Kant
*/
public abstract class AbstractInterceptorSupport<I, O, C extends KeyEvaluationContext,
A extends AbstractAttacher<I, O, C, S>,
S extends AbstractInterceptorSupport<I, O, C, A, S>> {
protected final Map<InterceptorKey<I, C>, A> attachers;
protected List<InterceptorHolder<I, C, InboundInterceptor<I, O>>> inboundInterceptors;
protected List<InterceptorHolder<I, C, OutboundInterceptor<O>>> outboundInterceptors;
protected boolean finished;
public AbstractInterceptorSupport() {
attachers = new HashMap<InterceptorKey<I, C>, A>();
inboundInterceptors = new LinkedList<InterceptorHolder<I, C, InboundInterceptor<I, O>>>();
outboundInterceptors = new LinkedList<InterceptorHolder<I, C, OutboundInterceptor<O>>>();
}
protected List<InterceptorHolder<I, C, InboundInterceptor<I, O>>> getInboundInterceptors() {
return inboundInterceptors;
}
protected List<InterceptorHolder<I, C, OutboundInterceptor<O>>> getOutboundInterceptors() {
return outboundInterceptors;
}
public A forKey(InterceptorKey<I, C> key) {
if (finished) {
throw new IllegalArgumentException("Interceptor support can not be modified after finishing.");
}
return getAttacherForKey(key);
}
protected A getAttacherForKey(InterceptorKey<I, C> key) {
A attacher = attachers.get(key);
if (null == attacher) {
attacher = newAttacher(key);
attachers.put(key, attacher);
}
return attacher;
}
protected abstract A newAttacher(InterceptorKey<I, C> key);
public boolean hasAtleastOneInterceptor() {
return !inboundInterceptors.isEmpty() || !outboundInterceptors.isEmpty();
}
public S finish() {
if (!finished) {
_finish();
finished = true;
}
return returnSupport();
}
protected void _finish() {
attachers.clear();
inboundInterceptors = Collections.unmodifiableList(inboundInterceptors);
outboundInterceptors = Collections.unmodifiableList(outboundInterceptors);
}
@SuppressWarnings("unchecked")
protected S returnSupport() {
return (S) this;
}
}