class IgniteMessageFactoryImpl implements IgniteMessageFactory {
    /** Offset. */
    private static final int OFF = -Short.MIN_VALUE;

    /** Array size. */
    private static final int ARR_SIZE = 1 << Short.SIZE;

    /** Message suppliers. */
    private final Supplier<Message>[] msgSuppliers = (Supplier<Message>[])Array.newInstance(Supplier.class, ARR_SIZE);

    /** Initialized flag. If {@code true} then new message type couldn't be registered. */
    private boolean initialized;

    /** Min index of registered message supplier. */
    private int minIdx = Integer.MAX_VALUE;

    /** Max index of registered message supplier. */
    private int maxIdx = -1;

    /** Count of registered message suppliers. */
    private int cnt;

    /**
     * Contructor.
     *
     * @param factories Concrete message factories or message factory providers. Cfn't be empty or {@code null}.
     */
    public IgniteMessageFactoryImpl(MessageFactory[] factories) {
        if (factories == null || factories.length == 0)
            throw new IllegalArgumentException("Message factory couldn't be initialized. Factories aren't provided.");

        List<MessageFactory> old = new ArrayList<>(factories.length);

        for (MessageFactory factory : factories) {
            if (factory instanceof MessageFactoryProvider) {
                MessageFactoryProvider p = (MessageFactoryProvider)factory;

                p.registerAll(this);
            }
            else
                old.add(factory);
        }

        if (!old.isEmpty()) {
            for (int i = 0; i < ARR_SIZE; i++) {
                Supplier<Message> curr = msgSuppliers[i];

                if (curr == null) {
                    short directType = indexToDirectType(i);

                    for (MessageFactory factory : old) {
                        Message msg = factory.create(directType);

                        if (msg != null)
                            register(directType, () -> factory.create(directType));
                    }
                }
            }
        }

        initialized = true;
    }

    /** {@inheritDoc} */
    @Override public void register(short directType, Supplier<Message> supplier) throws IgniteException {<FILL_FUNCTION_BODY>}

    /**
     * Creates new message instance of provided direct type.
     *
     * @param directType Message direct type.
     * @return Message instance.
     * @throws IgniteException If there are no any message factory for given {@code directType}.
     */
    @Override public @Nullable Message create(short directType) {
        Supplier<Message> supplier = msgSuppliers[directTypeToIndex(directType)];

        if (supplier == null)
            throw new IgniteException("Invalid message type: " + directType);

        return supplier.get();
    }

    /**
     * Returns direct types of all registered messages.
     *
     * @return Direct types of all registered messages.
     */
    public short[] registeredDirectTypes() {
        short[] res = new short[cnt];

        if (cnt > 0) {
            for (int i = minIdx, p = 0; i <= maxIdx; i++) {
                if (msgSuppliers[i] != null)
                    res[p++] = indexToDirectType(i);
            }
        }

        return res;
    }

    /**
     * @param directType Direct type.
     */
    private static int directTypeToIndex(short directType) {
        return directType + OFF;
    }

    /**
     * @param idx Index.
     */
    private static short indexToDirectType(int idx) {
        int res = idx - OFF;

        assert res >= Short.MIN_VALUE && res <= Short.MAX_VALUE;

        return (short)res;
    }
}

        if (initialized) {
            throw new IllegalStateException("Message factory is already initialized. " +
                    "Registration of new message types is forbidden.");
        }

        int idx = directTypeToIndex(directType);

        Supplier<Message> curr = msgSuppliers[idx];

        if (curr == null) {
            msgSuppliers[idx] = supplier;

            minIdx = Math.min(idx, minIdx);

            maxIdx = Math.max(idx, maxIdx);

            cnt++;
        }
        else
            throw new IgniteException("Message factory is already registered for direct type: " + directType);
    
<no_super_class>