class ReduceResultPage {
    /** */
    private final UUID src;

    /** */
    private final GridQueryNextPageResponse res;

    /** */
    private final int rowsInPage;

    /** */
    private Iterator<Value[]> rows;

    /** */
    private boolean last;

    /**
     * @param ctx Kernal context.
     * @param src Source.
     * @param res Response.
     */
    @SuppressWarnings("unchecked")
    public ReduceResultPage(final GridKernalContext ctx, UUID src, GridQueryNextPageResponse res) {
        assert src != null;

        this.src = src;
        this.res = res;

        // res == null means that it is a terminating dummy page for the given source node ID.
        if (res != null) {
            Collection<?> plainRows = res.plainRows();

            if (plainRows != null) {
                assert plainRows instanceof RandomAccess : "instance of " + plainRows.getClass();

                rowsInPage = plainRows.size();

                rows = (Iterator<Value[]>)plainRows.iterator();
            }
            else {
                final int cols = res.columns();

                rowsInPage = res.values().size() / cols;

                final Iterator<Message> valsIter = res.values().iterator();

                rows = new Iterator<Value[]>() {
                    /** */
                    int rowIdx;

                    @Override public boolean hasNext() {
                        return rowIdx < rowsInPage;
                    }

                    @Override public Value[] next() {
                        if (!hasNext())
                            throw new NoSuchElementException();

                        rowIdx++;

                        try {
                            return fillArray(valsIter, new Value[cols], ctx);
                        }
                        catch (IgniteCheckedException e) {
                            throw new CacheException(e);
                        }
                    }

                    @Override public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        }
        else {
            rowsInPage = 0;

            rows = Collections.emptyIterator();
        }
    }

    /**
     * @return {@code true} If this is a dummy fail page.
     */
    public boolean isFail() {
        return false;
    }

    /**
     * @return {@code true} If this is either a real last page for a source or
     *      a dummy terminating page with no rows.
     */
    public boolean isLast() {
        return last;
    }

    /**
     * @return {@code true} If it is a dummy last page.
     */
    public boolean isDummyLast() {
        return last && res == null;
    }

    /**
     * @param last Last page for a source.
     * @return {@code this}.
     */
    public ReduceResultPage setLast(boolean last) {
        this.last = last;

        return this;
    }

    /**
     * @return Number on rows in this page.
     */
    public int rowsInPage() {
        return rowsInPage;
    }

    /**
     * @return Rows.
     */
    public Iterator<Value[]> rows() {<FILL_FUNCTION_BODY>}

    /**
     * @return Result source node ID.
     */
    public UUID source() {
        return src;
    }

    /**
     * @return Segment ID.
     */
    public int segmentId() {
        return res.segmentId();
    }

    /**
     * @return Response.
     */
    public GridQueryNextPageResponse response() {
        return res;
    }

    /**
     * Request next page.
     */
    public void fetchNextPage() {
        throw new CacheException("Failed to fetch data from node: " + src);
    }

    /** {@inheritDoc} */
    @Override public String toString() {
        return S.toString(ReduceResultPage.class, this);
    }
}

        Iterator<Value[]> r = rows;

        assert r != null;

        rows = null;

        return r;
    
<no_super_class>