All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.phantomthief.util.CursorIteratorEx Maven / Gradle / Ivy

The newest version!
/**
 * 
 */
package com.github.phantomthief.util;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * @author w.vela
 */
public class CursorIteratorEx implements Iterable {

    private final C initCursor;
    private final boolean checkFirstCursor;
    private final Function dataRetriever;
    private final Function cursorExtractor;
    private final Function> dataExtractor;
    private final Predicate endChecker;

    /**
     * @param initCursor
     * @param checkFirstCursor
     * @param dataRetriever
     * @param cursorExtractor
     * @param dataExtractor
     * @param endChecker
     */
    private CursorIteratorEx(C initCursor, boolean checkFirstCursor, Function dataRetriever,
            Function cursorExtractor, Function> dataExtractor,
            Predicate endChecker) {
        this.initCursor = initCursor;
        this.checkFirstCursor = checkFirstCursor;
        this.dataRetriever = dataRetriever;
        this.cursorExtractor = cursorExtractor;
        this.dataExtractor = dataExtractor;
        this.endChecker = endChecker;
    }

    private final class RollingIterator implements Iterator {

        private C currentCursor;
        private R currentData;
        private Iterator currentIterator;

        public RollingIterator() {
            currentCursor = initCursor;
            if (checkFirstCursor && endChecker.test(currentCursor)) {
                return;
            }
            currentData = dataRetriever.apply(currentCursor);
            if (currentData != null) {
                currentIterator = dataExtractor.apply(currentData);
                currentCursor = cursorExtractor.apply(currentData);
            }
        }

        /* (non-Javadoc)
         * @see java.util.Iterator#hasNext()
         */
        @Override
        public boolean hasNext() {
            if (currentIterator == null) {
                return false;
            }
            if (currentIterator.hasNext()) {
                return true;
            }
            roll();
            return currentIterator != null && currentIterator.hasNext();
        }

        private void roll() {
            if (endChecker.test(currentCursor)) {
                currentData = null;
                currentIterator = null;
                return;
            }
            currentData = dataRetriever.apply(currentCursor);
            if (currentData == null) {
                currentIterator = null;
            } else {
                currentCursor = cursorExtractor.apply(currentData);
                currentIterator = dataExtractor.apply(currentData);
            }
        }

        /* (non-Javadoc)
         * @see java.util.Iterator#next()
         */
        @Override
        public T next() {
            return currentIterator.next();
        }
    }

    /* (non-Javadoc)
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public Iterator iterator() {
        return new RollingIterator();
    }

    public Stream stream() {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator(),
                (Spliterator.NONNULL | Spliterator.IMMUTABLE)), false);
    }

    @SuppressWarnings("unchecked")
    public static final class Builder {

        private C initCursor;
        private boolean checkFirstCursor;
        private Function dataRetriever;
        private Function cursorExtractor;
        private Function> dataExtractor;
        private Predicate endChecker;

        public  Builder withInitCursor(C1 initCursor) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.initCursor = initCursor;
            return thisBuilder;
        }

        public Builder firstCursorCheckEnd(boolean check) {
            this.checkFirstCursor = check;
            return this;
        }

        public  Builder withDataRetriever(Function dataRetriever) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.dataRetriever = dataRetriever;
            return thisBuilder;
        }

        public  Builder withCursorExtractor(Function cursorExtractor) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.cursorExtractor = cursorExtractor;
            return thisBuilder;
        }

        public  Builder
                withDataExtractor(Function> dataExtractor) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.dataExtractor = dataExtractor;
            return thisBuilder;
        }

        public  Builder withEndChecker(Predicate endChecker) {
            Builder thisBuilder = (Builder) this;
            thisBuilder.endChecker = endChecker;
            return thisBuilder;
        }

        @SuppressWarnings("rawtypes")
        public  CursorIteratorEx build() {
            ensure();
            return new CursorIteratorEx(initCursor, checkFirstCursor, dataRetriever,
                    cursorExtractor, dataExtractor, endChecker);
        }

        private void ensure() {
            if (dataExtractor == null) {
                throw new NullPointerException("data extractor is null.");
            }
            if (dataRetriever == null) {
                throw new NullPointerException("data retriver is null.");
            }
            if (cursorExtractor == null) {
                throw new NullPointerException("data retriver is null.");
            }
            if (endChecker == null) {
                endChecker = Objects::isNull;
            }
        }

    }

    public static final Builder newBuilder() {
        return new Builder<>();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy