class FIXCodec extends AbstractCodec {

    @Override
    public void init(IServiceContext serviceContext, ICommonSettings settings, IMessageFactory msgFactory, IDictionaryStructure dictionary) {
        if (!(settings instanceof TCPIPSettings)) {
            throw new IllegalStateException("settings is not TCPIPSettings. settings is " + settings.getClass().getName());
        }

        this.settings = (TCPIPSettings)settings;

        FixPropertiesReader.loadAndSetCharset(serviceContext);

        this.msgFactory = msgFactory;

        this.dictionary = Objects.requireNonNull(dictionary, "dictionary cannot be null");
        this.fieldConverter = new FixFieldConverter();
        fieldConverter.init(dictionary, dictionary.getNamespace());
        QFJIMessageConverterSettings qfjiMessageConverterSettings = new QFJIMessageConverterSettings(dictionary, this.msgFactory);
        this.qfjConverter = new DirtyQFJIMessageConverter(qfjiMessageConverterSettings);

        this.msgStructures = new HashMap<>();

        messagesWithXmlField.clear();

        for(IMessageStructure messageStructure : dictionary.getMessages().values()) {
            String msgType = getAttributeValue(messageStructure, FixMessageHelper.MESSAGE_TYPE_ATTR_NAME);
            if(msgType != null) {
                msgStructures.put(msgType, messageStructure);

                Boolean hasXmlFields = getAttributeValue(messageStructure, FixMessageHelper.HAS_XML_FIELDS_ATTR_NAME);
                if (Boolean.TRUE.equals(hasXmlFields)) {
                    messagesWithXmlField.add(msgType);
                }
            }
        }
        this.dataDict = new QFJDictionaryAdapter(dictionary);
        dataDict.setAllowUnknownMessageFields(true);

        String filterValues = this.settings.getFilterMessages();
        messageFilter = isNotEmpty(filterValues) ? new TagValueFilter(filterValues) : new FakeFilter();

        String fieldSeparator = this.settings.getFieldSeparator();
        if (isNotEmpty(fieldSeparator) ) {
            this.fieldSeparator = fieldSeparator;
            this.separatorReplacePattern = format("\\%s+(\\d+=)|\\%s+$", fieldSeparator, fieldSeparator);
        } else {
            this.fieldSeparator = SOH;
            this.separatorReplacePattern = null;
        }
    }

}