// Path: core/src/main/java/fixio/fixprotocol/FixMessage.java
// public interface FixMessage {
// 
//     String FIX_4_0 = "FIX.4.0";
//     String FIX_4_1 = "FIX.4.1";
//     String FIX_4_2 = "FIX.4.2";
//     String FIX_4_3 = "FIX.4.3";
//     String FIX_4_4 = "FIX.4.4";
//     String FIX_5_0 = "FIXT.1.1";
// 
//     FixMessageHeader getHeader();
// 
//     List<FixMessageFragment> getBody();
// 
//     Integer getInt(int tagNum);
// 
//     Integer getInt(FieldType field);
// 
//     String getString(int tagNum);
// 
//     @SuppressWarnings("unchecked")
//     <T> T getValue(int tagNum);
// 
//     String getString(FieldType field);
// 
//     <T> T getValue(FieldType field);
// 
//     Character getChar(int tagNum);
// 
//     Character getChar(FieldType fieldType);
// 
//     String getMessageType();
// 
//     default FixMessageFragment getFirst(int tagNum) {
//         final List<FixMessageFragment> body = getBody();
//         for (int i = 0; i < body.size(); i++) {
//             FixMessageFragment item = body.get(i);
//             if (item.getTagNum() == tagNum) {
//                 return item;
//             }
//         }
//         return null;
//     }
// 
//     default List<FixMessageFragment> getAll(int tagNum) {
//         final List<FixMessageFragment> body = getBody();
//         List<FixMessageFragment> result = new ArrayList<>(8);
//         for (int i = 0; i < body.size(); i++) {
//             FixMessageFragment item = body.get(i);
//             if (item.getTagNum() == tagNum) {
//                 result.add(item);
//             }
//         }
//         return result;
//     }
// 
//     default FixMessageFragment getLast(int tagNum) {
//         final List<FixMessageFragment> body = getBody();
//         for (int i = body.size() - 1; i >= 0; i--) {
//             FixMessageFragment item = body.get(i);
//             if (item.getTagNum() == tagNum) {
//                 return item;
//             }
//         }
//         return null;
//     }
// 
// }
// 
// Path: core/src/main/java/fixio/fixprotocol/FixMessageBuilder.java
// public interface FixMessageBuilder extends FieldListBuilder<FixMessageBuilder> {
//     FixMessageHeader getHeader();
// 
//     void copyHeader(FixMessageHeader header);
// 
//     List<? extends FixMessageFragment> getBody();
// 
//     void copyBody(List<? extends FixMessageFragment> body);
// }
// 
// Path: core/src/main/java/fixio/validator/BusinessRejectException.java
// public class BusinessRejectException extends Exception {
// 
//     /**
//      * MsgSeqNum of rejected message
//      */
//     private final int refSeqNum;
// 
//     /**
//      * The MsgType of the FIX message being referenced.
//      */
//     private final String refMsgType;
// 
//     /**
//      * The value of the business-level "ID" field on the message being referenced.
//      * Required unless the corresponding ID field (see list above) was not specified.
//      */
//     private final int businessRejectReason;
// 
//     /**
//      * Where possible, message to explain reason for rejection.
//      */
//     private final String text;
// 
//     public BusinessRejectException(int refSeqNum, String refMsgType, int businessRejectReason, String text) {
//         super(text);
//         this.refSeqNum = refSeqNum;
//         this.refMsgType = refMsgType;
//         this.businessRejectReason = businessRejectReason;
//         this.text = text;
//     }
// 
//     public int getRefSeqNum() {
//         return refSeqNum;
//     }
// 
//     public String getRefMsgType() {
//         return refMsgType;
//     }
// 
//     public int getBusinessRejectReason() {
//         return businessRejectReason;
//     }
// 
//     public String getText() {
//         return text;
//     }
// }
// 
// Path: core/src/main/java/fixio/validator/FixMessageValidator.java
// public interface FixMessageValidator {
// 
//     void validate(ChannelHandlerContext ctx, FixMessage msg);
// }


import fixio.fixprotocol.FixMessage;
import fixio.fixprotocol.FixMessageBuilder;
import fixio.validator.BusinessRejectException;
import fixio.validator.FixMessageValidator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;

    @Override
    public void onMessage(ChannelHandlerContext ctx, FixMessage msg, List<Object> out) throws BusinessRejectException {
        assert (msg != null) : "Message can't be null";
        LOGGER.info("Received : {}", msg);

        //Validate
        for (FixMessageValidator validator : validators) {
            validator.validate(ctx, msg);
        }

        //Business handler
        if (handlers != null) {
            boolean isHandled = false;
            for (FixMessageHandler handler : handlers) {
                try {
                    if (handler.handle(ctx, msg)) {
                        isHandled = true;
                    }
                } catch (Exception ex) {
                    LOGGER.error("on {} ", handler.getClass(), ex);
                }
            }
            if (!isHandled) {
                LOGGER.warn("no handler for this message. {} ", msg);
            }
        }
    }

    @Override
// Path: core/src/main/java/fixio/fixprotocol/FixMessage.java
// public interface FixMessage {
// 
//     String FIX_4_0 = "FIX.4.0";
//     String FIX_4_1 = "FIX.4.1";
//     String FIX_4_2 = "FIX.4.2";
//     String FIX_4_3 = "FIX.4.3";
//     String FIX_4_4 = "FIX.4.4";
//     String FIX_5_0 = "FIXT.1.1";
// 
//     FixMessageHeader getHeader();
// 
//     List<FixMessageFragment> getBody();
// 
//     Integer getInt(int tagNum);
// 
//     Integer getInt(FieldType field);
// 
//     String getString(int tagNum);
// 
//     @SuppressWarnings("unchecked")
//     <T> T getValue(int tagNum);
// 
//     String getString(FieldType field);
// 
//     <T> T getValue(FieldType field);
// 
//     Character getChar(int tagNum);
// 
//     Character getChar(FieldType fieldType);
// 
//     String getMessageType();
// 
//     default FixMessageFragment getFirst(int tagNum) {
//         final List<FixMessageFragment> body = getBody();
//         for (int i = 0; i < body.size(); i++) {
//             FixMessageFragment item = body.get(i);
//             if (item.getTagNum() == tagNum) {
//                 return item;
//             }
//         }
//         return null;
//     }
// 
//     default List<FixMessageFragment> getAll(int tagNum) {
//         final List<FixMessageFragment> body = getBody();
//         List<FixMessageFragment> result = new ArrayList<>(8);
//         for (int i = 0; i < body.size(); i++) {
//             FixMessageFragment item = body.get(i);
//             if (item.getTagNum() == tagNum) {
//                 result.add(item);
//             }
//         }
//         return result;
//     }
// 
//     default FixMessageFragment getLast(int tagNum) {
//         final List<FixMessageFragment> body = getBody();
//         for (int i = body.size() - 1; i >= 0; i--) {
//             FixMessageFragment item = body.get(i);
//             if (item.getTagNum() == tagNum) {
//                 return item;
//             }
//         }
//         return null;
//     }
// 
// }
// 
// Path: core/src/main/java/fixio/fixprotocol/FixMessageBuilder.java
// public interface FixMessageBuilder extends FieldListBuilder<FixMessageBuilder> {
//     FixMessageHeader getHeader();
// 
//     void copyHeader(FixMessageHeader header);
// 
//     List<? extends FixMessageFragment> getBody();
// 
//     void copyBody(List<? extends FixMessageFragment> body);
// }
// 
// Path: core/src/main/java/fixio/validator/BusinessRejectException.java
// public class BusinessRejectException extends Exception {
// 
//     /**
//      * MsgSeqNum of rejected message
//      */
//     private final int refSeqNum;
// 
//     /**
//      * The MsgType of the FIX message being referenced.
//      */
//     private final String refMsgType;
// 
//     /**
//      * The value of the business-level "ID" field on the message being referenced.
//      * Required unless the corresponding ID field (see list above) was not specified.
//      */
//     private final int businessRejectReason;
// 
//     /**
//      * Where possible, message to explain reason for rejection.
//      */
//     private final String text;
// 
//     public BusinessRejectException(int refSeqNum, String refMsgType, int businessRejectReason, String text) {
//         super(text);
//         this.refSeqNum = refSeqNum;
//         this.refMsgType = refMsgType;
//         this.businessRejectReason = businessRejectReason;
//         this.text = text;
//     }
// 
//     public int getRefSeqNum() {
//         return refSeqNum;
//     }
// 
//     public String getRefMsgType() {
//         return refMsgType;
//     }
// 
//     public int getBusinessRejectReason() {
//         return businessRejectReason;
//     }
// 
//     public String getText() {
//         return text;
//     }
// }
// 
// Path: core/src/main/java/fixio/validator/FixMessageValidator.java
// public interface FixMessageValidator {
// 
//     void validate(ChannelHandlerContext ctx, FixMessage msg);
// }


// Path: core/src/main/java/fixio/handlers/CompositeFixApplicationAdapter.java
import fixio.fixprotocol.FixMessage;
import fixio.fixprotocol.FixMessageBuilder;
import fixio.validator.BusinessRejectException;
import fixio.validator.FixMessageValidator;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;


    @Override
    public void onMessage(ChannelHandlerContext ctx, FixMessage msg, List<Object> out) throws BusinessRejectException {
        assert (msg != null) : "Message can't be null";
        LOGGER.info("Received : {}", msg);

        //Validate
        for (FixMessageValidator validator : validators) {
            validator.validate(ctx, msg);
        }

        //Business handler
        if (handlers != null) {
            boolean isHandled = false;
            for (FixMessageHandler handler : handlers) {
                try {
                    if (handler.handle(ctx, msg)) {
                        isHandled = true;
                    }
                } catch (Exception ex) {
                    LOGGER.error("on {} ", handler.getClass(), ex);
                }
            }
            if (!isHandled) {
                LOGGER.warn("no handler for this message. {} ", msg);
            }
        }
    }

    @Override
    public void beforeSendMessage(ChannelHandlerContext ctx, FixMessageBuilder msg) {