package com.github.kpavlov.jreactive8583.netty.pipeline;
import com.github.kpavlov.jreactive8583.IsoMessageListener;
import com.solab.iso8583.IsoMessage;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Handles {@link IsoMessage} s with chain of {@link IsoMessageListener}s.
*/
@ChannelHandler.Sharable
public class CompositeIsoMessageHandler<T extends IsoMessage> extends ChannelInboundHandlerAdapter {
private final Logger logger = getLogger(CompositeIsoMessageHandler.class);
private final List<IsoMessageListener<T>> messageListeners = new CopyOnWriteArrayList<>();
private final boolean failOnError;
public CompositeIsoMessageHandler(boolean failOnError) {
this.failOnError = failOnError;
}
public CompositeIsoMessageHandler() {
this(true);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof IsoMessage) {
doHandleMessage(ctx, msg);
}
super.channelRead(ctx, msg);
}
private void doHandleMessage(ChannelHandlerContext ctx, Object msg) {
T isoMessage;
try {
//noinspection unchecked
isoMessage = (T) msg;
} catch (ClassCastException e) {
logger.debug("IsoMessage subclass {} is not supported by {}. Doing nothing.", msg.getClass(), getClass());
return;
}
boolean applyNextListener = true;
final int size = messageListeners.size();
for (int i = 0; applyNextListener && i < size; i++) {
IsoMessageListener<T> messageListener = messageListeners.get(i);
try {
if (messageListener.applies(isoMessage)) {
logger.debug(
"Handling IsoMessage[@type=0x{}] with {}",
String.format("%04X", isoMessage.getType()), messageListener);
applyNextListener = messageListener.onMessage(ctx, isoMessage);
if (!applyNextListener) {
logger.debug("Stopping further procession of message {} after handler {}", isoMessage, messageListener);
}
}
} catch (Exception e) {
logger.debug("Can't evaluate {}.apply({})", messageListener, isoMessage.getClass(), e);
if (failOnError) {
throw e;
}
}
}
}
public void addListener(IsoMessageListener<T> listener) {
Objects.requireNonNull(listener, "IsoMessageListener is required");
messageListeners.add(listener);
}
@SuppressWarnings("WeakerAccess")
@SafeVarargs
public final void addListeners(IsoMessageListener<T>... listeners) {
Objects.requireNonNull(listeners, "IsoMessageListeners must not be null");
for (IsoMessageListener<T> listener : listeners) {
addListener(listener);
}
}
public void removeListener(IsoMessageListener<T> listener) {
messageListeners.remove(listener);
}
}