B3 SBE Sample

Description

This sample illustrates adjustment of the CME iLInk3 SBE XML template to satisfy SBE requirements. In particular the sample shows how to resolve conflict between zeros that can be defined in different ways: as character constant ‘0’ or as the binary constant 0.

Source Code

import biz.onixs.sbe.*;
import biz.onixs.sbe.def.FramingHeaderSpecification;
import biz.onixs.sbe.def.MessageSchema;
import net.sf.practicalxml.DomUtil;
import net.sf.practicalxml.ParseUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.bind.DatatypeConverter;
import java.io.File;

/**
 * Main sample class.
 */
public class iLink3Sample {

    /**
     * The messages obtained from:
     * https://cmegroupclientsite.atlassian.net/wiki/spaces/EPICSANDBOX/pages/457085070/Mandatory+Migration+-+iLink+3+Binary+Order+Entry+Protocol+for+CGW
     */
    static final String hexPartyDetailsDefinitionRequest518 =
            "E7,00,FE,CA,93,00,06,02,08,00,08,00,03,71,C6,00,00,00,00,00," +
            "80,BE,55,CB,6D,F6,CE,17,41,01,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FF,00,04,00,00," +
            "FF,FF,59,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,16," +
            "00,03,30,30,34,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,01,00,41,43,43,4F,55,4E,54,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,18,00,41,42,43,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,76,00,02,00,00";
    static final String hexQuoteCancelAck563 =
            "82,01,FE,CA,70,01,33,02,08,00,08,00,08,00,00,00,E1,CF,D3,70," +
            "8F,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "41,42,43,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00," +
            "32,73,C6,00,00,00,00,00,DD,45,EE,1C,DF,FB,CE,17,E8,E6,48,1D," +
            "DF,FB,CE,17,24,33,00,00,00,00,55,53,2C,49,4C,08,00,00,00,FF," +
            "FF,FF,FF,01,04,00,00,00,00,00,30,FF,FF,FF,00,FF,FF,FF,FF,FF," +
            "FF,FF,FF,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,FF," +
            "09,00,00,04,00,00";


    /**
     * The method modifies original CME iLink3 XML SBE template
     * to satisfy SBE standard requirements together with CME requirements.
     *
     * @param doc - Original XML document.
     * @return - The input document.
     */
    static Document adjustiLink3XmlSchema(Document doc) {
        for (Element typesItem : DomUtil.getChildren(doc.getDocumentElement(), "types")) {
            for (Element typeNode : DomUtil.getChildren(typesItem)) {
                // Sets nullValue to binary 0 for enumerations
                // that are encoded with the 'charNULL' type.
                if ("enum".equals(typeNode.getTagName())
                    && typeNode.hasAttribute("encodingType")
                    && "charNULL".equals(typeNode.getAttribute("encodingType"))) {
                    typeNode.setAttribute("nullValue", "\u0000");
                }
            }
        }
        return doc;
    }
    private static byte[] getBinaryData(String hex) {
        hex = hex.replace(",", "");
        return DatatypeConverter.parseHexBinary(hex);
    }

    private static void printCharFieldState(IMessage msg, int tag) {
        char value = msg.getChar(tag);
        System.out.print("The message \"" + msg.getMessageName() + "\", field <" + tag + ">: ");

        if (!msg.contains(tag)) {
            System.out.print("is null, ");
        } else {
            System.out.print("non-empty, ");
        }

        if ((int)value >= 32) {
            System.out.print("char value '" + value + "', ");
        }
        System.out.println("value code " + (int)value);
    }

    private static void runSample() throws Exception {
        final File testsXmlFolder = new File("config").getAbsoluteFile();
        final Document xmlSchema = adjustiLink3XmlSchema(ParseUtil.parse(new File(testsXmlFolder, "ilinkbinary87.xml")));
        final MessageSchema msgSchema = new MessageSchema(xmlSchema, FramingHeaderPolicy.getCustomPolicy(FramingHeaderSpecification.CMEILINK3_FRAMING_HEADER));
        final ByteDecoder codec = new ByteDecoderFactory().create(msgSchema);

        {
            final byte[] data = getBinaryData(hexPartyDetailsDefinitionRequest518);
            IMessage msg = codec.decode(data, 0, data.length);
            printCharFieldState(msg, 9708);
            printCharFieldState(msg, 8000);
        }

        {
            final byte[] data = getBinaryData(hexQuoteCancelAck563);
            IMessage msg = codec.decode(data, 0, data.length);
            printCharFieldState(msg, 9775);
        }
    }

    /**
     * Program entry point.
     * @param args arguments.
     */
    public static void main(String[] args) {
        try {
            runSample();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Usage

  • Run the sample:
    • win: runiLink3Sample.bat
    • linux: runiLink3Sample.sh
  • Clean everything:
    • win: clean.bat
    • linux: clean.sh