private void generateComposite(final List<Token> tokens) throws IOException
    {
        final Token token = tokens.get(0);
        final String compositeName = token.applicableTypeName();
        final String decoderName = decoderName(compositeName);
        final String encoderName = encoderName(compositeName);

        registerTypesPackageName(token, ir);
        final Set<String> importedTypesPackages = scanPackagesToImport(tokens);

        try (Writer out = outputManager.createOutput(decoderName))
        {
            final String implementsString = implementsInterface(CompositeDecoderFlyweight.class.getSimpleName());
            generateCompositeFlyweightHeader(
                token, decoderName, out, readOnlyBuffer, fqReadOnlyBuffer, implementsString, importedTypesPackages);

            for (int i = 1, end = tokens.size() - 1; i < end;)
            {
                final Token encodingToken = tokens.get(i);
                final String propertyName = formatPropertyName(encodingToken.name());
                final String typeName = decoderName(encodingToken.applicableTypeName());

                final StringBuilder sb = new StringBuilder();
                generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT);
                generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT);
                generateFieldSinceVersionMethod(sb, encodingToken, BASE_INDENT);
                final String accessOrderListenerCall = "";

                switch (encodingToken.signal())
                {
                    case ENCODING:
                        generatePrimitiveDecoder(
                            sb, true, encodingToken.name(), "", encodingToken, encodingToken, BASE_INDENT);
                        break;

                    case BEGIN_ENUM:
                        generateEnumDecoder(sb, true, "", encodingToken, propertyName, encodingToken, BASE_INDENT);
                        break;

                    case BEGIN_SET:
                        generateBitSetProperty(
                            sb, true, DECODER, propertyName, accessOrderListenerCall,
                            encodingToken, encodingToken, BASE_INDENT, typeName);
                        break;

                    case BEGIN_COMPOSITE:
                        generateCompositeProperty(
                            sb, true, DECODER, propertyName, accessOrderListenerCall,
                            encodingToken, encodingToken, BASE_INDENT, typeName);
                        break;

                    default:
                        break;
                }

                out.append(sb);
                i += encodingToken.componentTokenCount();
            }

            out.append(generateCompositeDecoderDisplay(tokens));

            out.append("}\n");
        }

        registerTypesPackageName(token, ir);
        try (Writer out = outputManager.createOutput(encoderName))
        {
            final String implementsString = implementsInterface(CompositeEncoderFlyweight.class.getSimpleName());
            generateCompositeFlyweightHeader(
                token, encoderName, out, mutableBuffer, fqMutableBuffer, implementsString, importedTypesPackages);

            for (int i = 1, end = tokens.size() - 1; i < end;)
            {
                final Token encodingToken = tokens.get(i);
                final String propertyName = formatPropertyName(encodingToken.name());
                final String typeName = encoderName(encodingToken.applicableTypeName());

                final StringBuilder sb = new StringBuilder();
                generateEncodingOffsetMethod(sb, propertyName, encodingToken.offset(), BASE_INDENT);
                generateEncodingLengthMethod(sb, propertyName, encodingToken.encodedLength(), BASE_INDENT);
                final String accessOrderListenerCall = "";

                switch (encodingToken.signal())
                {
                    case ENCODING:
                        generatePrimitiveEncoder(sb, encoderName, encodingToken.name(),
                            accessOrderListenerCall, encodingToken, BASE_INDENT);
                        break;

                    case BEGIN_ENUM:
                        generateEnumEncoder(sb, encoderName, accessOrderListenerCall,
                            encodingToken, propertyName, encodingToken, BASE_INDENT);
                        break;

                    case BEGIN_SET:
                        generateBitSetProperty(
                            sb, true, ENCODER, propertyName, accessOrderListenerCall,
                            encodingToken, encodingToken, BASE_INDENT, typeName);
                        break;

                    case BEGIN_COMPOSITE:
                        generateCompositeProperty(
                            sb, true, ENCODER, propertyName, accessOrderListenerCall,
                            encodingToken, encodingToken, BASE_INDENT, typeName);
                        break;

                    default:
                        break;
                }

                out.append(sb);
                i += encodingToken.componentTokenCount();
            }

            out.append(generateCompositeEncoderDisplay(decoderName));
            out.append("}\n");
        }
    }
\n");
        sb.append("     * The states in which a encoder/decoder/codec can live.\n");
        sb.append("     *\n");
        sb.append("     * <p>The state machine diagram below, encoded in the dot language, describes\n");
        sb.append("     * the valid state transitions according to the order in which fields may be\n");
        sb.append("     * accessed safely. Tools such as PlantUML and Graphviz can render it.\n");
        sb.append("     *\n");
        sb.append("     * <pre>{@code\n");
        fieldPrecedenceModel.generateGraph(sb, "     *   ");
        sb.append("     * }</pre>\n");
        sb.append("
sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java