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

internal.io.IOIterators Maven / Gradle / Ivy

/*
 * Copyright 2017 National Bank of Belgium
 * 
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved 
 * by the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 * 
 * http://ec.europa.eu/idabc/eupl
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and 
 * limitations under the Licence.
 */
package internal.io;

import lombok.NonNull;
import nbbrd.io.IOIterator;
import nbbrd.io.function.IOConsumer;
import nbbrd.io.function.IOPredicate;
import nbbrd.io.function.IOSupplier;
import nbbrd.io.function.IOUnaryOperator;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 *
 * @author Philippe Charles
 */
@lombok.experimental.UtilityClass
public class IOIterators {

    public enum Empty implements IOIterator {

        INSTANCE;

        @Override
        public boolean hasNextWithIO() {
            return false;
        }

        @Override
        public Object nextWithIO() throws NoSuchElementException {
            throw new NoSuchElementException();
        }

        @Override
        public @NonNull Stream asStream() {
            return Stream.empty();
        }

        @Override
        public @NonNull Iterator asUnchecked() {
            return Collections.emptyIterator();
        }
    }

    @lombok.RequiredArgsConstructor
    public static final class Singleton implements IOIterator {

        @Nullable
        private final E element;

        private boolean first = true;

        @Override
        public boolean hasNextWithIO() {
            return first;
        }

        @Override
        public E nextWithIO() throws NoSuchElementException {
            if (!hasNextWithIO()) {
                throw new NoSuchElementException();
            }
            first = false;
            return element;
        }
    }

    @lombok.RequiredArgsConstructor
    public static final class Checked implements IOIterator {

        @lombok.Getter
        @NonNull
        private final Iterator delegate;

        @Override
        public boolean hasNextWithIO() throws IOException {
            try {
                return delegate.hasNext();
            } catch (UncheckedIOException ex) {
                throw ex.getCause();
            }
        }

        @Override
        public E nextWithIO() throws IOException, NoSuchElementException {
            try {
                return delegate.next();
            } catch (UncheckedIOException ex) {
                throw ex.getCause();
            }
        }

        @Override
        public void removeWithIO() throws IOException {
            try {
                delegate.remove();
            } catch (UncheckedIOException ex) {
                throw ex.getCause();
            }
        }

        @Override
        public void forEachRemainingWithIO(@NonNull IOConsumer action) throws IOException {
            try {
                delegate.forEachRemaining(action.asUnchecked());
            } catch (UncheckedIOException ex) {
                throw ex.getCause();
            }
        }

        @Override
        public @NonNull Stream asStream() {
            return StreamSupport.stream(Spliterators.spliteratorUnknownSize(delegate, 0), false);
        }

        @Override
        public @NonNull Iterator asUnchecked() {
            return delegate;
        }
    }

    @lombok.RequiredArgsConstructor
    public static final class Unchecked implements Iterator {

        @lombok.Getter
        @NonNull
        private final IOIterator delegate;

        @Override
        public boolean hasNext() {
            try {
                return delegate.hasNextWithIO();
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }

        @Override
        public E next() {
            try {
                return delegate.nextWithIO();
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }

        @Override
        public void remove() {
            try {
                delegate.removeWithIO();
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }

        @Override
        public void forEachRemaining(Consumer action) {
            try {
                delegate.forEachRemainingWithIO(IOConsumer.checked(action));
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }
    }

    @lombok.RequiredArgsConstructor
    public static final class Functional implements IOIterator {

        @NonNull
        private final IOSupplier seed;

        @NonNull
        private final IOPredicate hasNext;

        @NonNull
        private final IOUnaryOperator next;

        private boolean seeded = false;
        private E nextValue = null;

        @Override
        public boolean hasNextWithIO() throws IOException {
            if (!seeded) {
                seeded = true;
                nextValue = seed.getWithIO();
            }
            return hasNext.testWithIO(nextValue);
        }

        @Override
        public E nextWithIO() throws IOException, NoSuchElementException {
            if (!hasNextWithIO()) {
                throw new NoSuchElementException();
            }
            E result = nextValue;
            nextValue = next.applyWithIO(nextValue);
            return result;
        }
    }
}