public byte[] build(boolean first, boolean withTcpHeader) {
        StringBuilder builder = new StringBuilder("Message built:");
        int length = first ? 2 : 1;
        if (!withTcpHeader) length--;
        for (MessagePart part : parts) {
            length += part.length;
        }
        if (length > 0x7e * 4) {
            length += 3;
        }

        ByteBuffer buffer = ByteBuffer.allocate(length);
        if (first) {
            builder.append("\nFirst message, added 0xEF");
            buffer.put((byte) 0xEF);
        }
        if (withTcpHeader) {
            if (length > 0x7e * 4) {
                length = length / 4 - 1;
                buffer.put((byte) 0x7f);
                buffer.put((byte) (length % 0x100));
                buffer.put((byte) (length / 0x100));
                buffer.put((byte) 0);
                builder.append("\nLength in 4-bytes format: 0x7e ");
                Message.appendHexBytes(builder, (byte) (length % 0x100), (byte) (length / 0x100));
            } else {
                byte header = (byte) (length / 4);
                builder.append("\nLength: 0x");
                Message.appendHexByte(builder, header);
                buffer.put(header);
            }
        }
        for (Iterator<MessagePart> iterator = parts.iterator(); iterator.hasNext(); ) {
            MessagePart part = iterator.next();
            iterator.remove();
            builder.append("\n").append(part.toString());
            part.put(buffer);
        }
        for (MessagePart part : parts) {
            builder.append("\n").append(part.toString());
            part.put(buffer);
        }
        byte[] array = buffer.array();
        builder.append(SocketMessenger.print(array, ""));
        log.info(builder.toString());
        return array;
    }