class PlatformAbstractQueryCursor<T> extends PlatformAbstractTarget implements AutoCloseable {
    /** Get multiple entries. */
    private static final int OP_GET_ALL = 1;

    /** Get all entries. */
    private static final int OP_GET_BATCH = 2;

    /** Get single entry. */
    private static final int OP_GET_SINGLE = 3;

    /** Start iterating. */
    private static final int OP_ITERATOR = 4;

    /** Close iterator. */
    private static final int OP_ITERATOR_CLOSE = 5;

    /** Close iterator. */
    private static final int OP_ITERATOR_HAS_NEXT = 6;

    /** Underlying cursor. */
    private final QueryCursorEx<T> cursor;

    /** Batch size size. */
    private final int batchSize;

    /** Underlying iterator. */
    private Iterator<T> iter;

    /**
     * Constructor.
     *
     * @param platformCtx Context.
     * @param cursor Underlying cursor.
     * @param batchSize Batch size.
     */
    PlatformAbstractQueryCursor(PlatformContext platformCtx, QueryCursorEx<T> cursor, int batchSize) {
        super(platformCtx);

        this.cursor = cursor;
        this.batchSize = batchSize;
    }

    /** {@inheritDoc} */
    @Override public void processOutStream(int type, final BinaryRawWriterEx writer) throws IgniteCheckedException {
        switch (type) {
            case OP_GET_BATCH: {
                assert iter != null : "iterator() has not been called";

                try {
                    int cntPos = writer.reserveInt();

                    int cnt = 0;

                    while (cnt < batchSize && iter.hasNext()) {
                        write(writer, iter.next());

                        cnt++;
                    }

                    writer.writeInt(cntPos, cnt);

                    writer.writeBoolean(iter.hasNext());

                    if (!iter.hasNext())
                        cursor.close();
                }
                catch (Exception err) {
                    throw PlatformUtils.unwrapQueryException(err);
                }

                break;
            }

            case OP_GET_SINGLE: {
                assert iter != null : "iterator() has not been called";

                try {
                    if (iter.hasNext()) {
                        write(writer, iter.next());

                        return;
                    }
                }
                catch (Exception err) {
                    throw PlatformUtils.unwrapQueryException(err);
                }

                throw new IgniteCheckedException("No more data available.");
            }

            case OP_GET_ALL: {
                try {
                    int pos = writer.reserveInt();

                    Consumer<T> consumer = new Consumer<>(this, writer);

                    cursor.getAll(consumer);

                    writer.writeInt(pos, consumer.cnt);
                }
                catch (Exception err) {
                    throw PlatformUtils.unwrapQueryException(err);
                }

                break;
            }

            default:
                super.processOutStream(type, writer);
        }
    }

    /** {@inheritDoc} */
    @Override public long processInLongOutLong(int type, long val) throws IgniteCheckedException {<FILL_FUNCTION_BODY>}

    /** {@inheritDoc} */
    @Override public void close() throws Exception {
        cursor.close();
    }

    /**
     * Write value to the stream. Extension point to perform conversions on the object before writing it.
     *
     * @param writer Writer.
     * @param val Value.
     */
    protected abstract void write(BinaryRawWriterEx writer, T val);

    /**
     * Gets the cursor.
     *
     * @return Cursor.
     */
    public QueryCursorEx<T> cursor() {
        return cursor;
    }

    /**
     * Query cursor consumer.
     */
    private static class Consumer<T> implements QueryCursorEx.Consumer<T> {
        /** Current query cursor. */
        private final PlatformAbstractQueryCursor<T> cursor;

        /** Writer. */
        private final BinaryRawWriterEx writer;

        /** Count. */
        private int cnt;

        /**
         * Constructor.
         *
         * @param writer Writer.
         */
        Consumer(PlatformAbstractQueryCursor<T> cursor, BinaryRawWriterEx writer) {
            this.cursor = cursor;
            this.writer = writer;
        }

        /** {@inheritDoc} */
        @Override public void consume(T val) throws IgniteCheckedException {
            cursor.write(writer, val);

            cnt++;
        }
    }
}

        switch (type) {
            case OP_ITERATOR:
                iter = cursor.iterator();

                return TRUE;

            case OP_ITERATOR_CLOSE:
                cursor.close();

                return TRUE;

            case OP_ITERATOR_HAS_NEXT:
                assert iter != null : "iterator() has not been called";

                return iter.hasNext() ? TRUE : FALSE;
        }

        return super.processInLongOutLong(type, val);
    
<methods>public java.lang.Exception convertException(java.lang.Exception) ,public org.apache.ignite.internal.processors.platform.PlatformContext platformContext() ,public long processInLongOutLong(int, long) throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.platform.PlatformTarget processInObjectStreamOutObjectStream(int, org.apache.ignite.internal.processors.platform.PlatformTarget, org.apache.ignite.internal.binary.BinaryRawReaderEx, org.apache.ignite.internal.binary.BinaryRawWriterEx) throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.platform.PlatformAsyncResult processInStreamAsync(int, org.apache.ignite.internal.binary.BinaryRawReaderEx) throws org.apache.ignite.IgniteCheckedException,public long processInStreamOutLong(int, org.apache.ignite.internal.binary.BinaryRawReaderEx) throws org.apache.ignite.IgniteCheckedException,public long processInStreamOutLong(int, org.apache.ignite.internal.binary.BinaryRawReaderEx, org.apache.ignite.internal.processors.platform.memory.PlatformMemory) throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.platform.PlatformTarget processInStreamOutObject(int, org.apache.ignite.internal.binary.BinaryRawReaderEx) throws org.apache.ignite.IgniteCheckedException,public void processInStreamOutStream(int, org.apache.ignite.internal.binary.BinaryRawReaderEx, org.apache.ignite.internal.binary.BinaryRawWriterEx) throws org.apache.ignite.IgniteCheckedException,public org.apache.ignite.internal.processors.platform.PlatformTarget processOutObject(int) throws org.apache.ignite.IgniteCheckedException,public void processOutStream(int, org.apache.ignite.internal.binary.BinaryRawWriterEx) throws org.apache.ignite.IgniteCheckedException,public static T throwUnsupported(int) throws org.apache.ignite.IgniteCheckedException<variables>protected static final int ERROR,protected static final int FALSE,protected static final int TRUE,protected final non-sealed org.apache.ignite.IgniteLogger log,protected final non-sealed org.apache.ignite.internal.processors.platform.PlatformContext platformCtx