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

io.helidon.dbclient.AutoClosingStream Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2023 Oracle and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.helidon.dbclient;

import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.Function;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.LongConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collector;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * A {@link Stream} decorator that invokes {@link Stream#close()} on terminal operations.
 *
 * @param  the type of the stream elements
 */
class AutoClosingStream implements Stream {

    private final Stream delegate;
    private final Runnable closeHandler;

    private AutoClosingStream(Stream delegate, Runnable closeHandler) {
        this.delegate = delegate;
        this.closeHandler = closeHandler;
    }

    /**
     * Decorate a {@link Stream} to invoke {@link Stream#close()} on terminal operations.
     *
     * @param stream stream to decorate
     * @param     the type of the stream elements
     * @return decorated stream
     */
    static  Stream decorate(Stream stream) {
        return decorate(stream, stream::close);
    }

    /**
     * Decorate a {@link Stream} to invoke a {@link Runnable} on terminal operations.
     *
     * @param stream       stream to decorate
     * @param closeHandler runnable to invoke on terminal operations
     * @param           the type of the stream elements
     * @return decorated stream
     */
    static  Stream decorate(Stream stream, Runnable closeHandler) {
        if (stream instanceof AutoClosingStream) {
            return stream;
        }
        return new AutoClosingStream<>(stream, AutoClosingHandler.decorate(closeHandler));
    }

    @Override
    public Object[] toArray() {
        try {
            return delegate.toArray();
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public  A[] toArray(IntFunction generator) {
        try {
            return delegate.toArray(generator);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public T reduce(T identity, BinaryOperator accumulator) {
        try {
            return delegate.reduce(identity, accumulator);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public Optional reduce(BinaryOperator accumulator) {
        try {
            return delegate.reduce(accumulator);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public  U reduce(U identity, BiFunction accumulator, BinaryOperator combiner) {
        try {
            return delegate.reduce(identity, accumulator, combiner);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public  R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) {
        try {
            return delegate.collect(supplier, accumulator, combiner);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public  R collect(Collector collector) {
        try {
            return delegate.collect(collector);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public List toList() {
        try {
            return delegate.toList();
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public long count() {
        try {
            return delegate.count();
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public boolean anyMatch(Predicate predicate) {
        try {
            return delegate.anyMatch(predicate);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public boolean allMatch(Predicate predicate) {
        try {
            return delegate.allMatch(predicate);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public boolean noneMatch(Predicate predicate) {
        try {
            return delegate.noneMatch(predicate);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public Optional findFirst() {
        try {
            return delegate.findFirst();
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public Optional findAny() {
        try {
            return delegate.findAny();
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public Optional min(Comparator comparator) {
        try {
            return delegate.min(comparator);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public Optional max(Comparator comparator) {
        try {
            return delegate.max(comparator);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public void forEach(Consumer action) {
        try {
            delegate.forEach(action);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public void forEachOrdered(Consumer action) {
        try {
            delegate.forEachOrdered(action);
        } finally {
            closeHandler.run();
        }
    }

    @Override
    public Stream filter(Predicate predicate) {
        return decorate(delegate.filter(predicate), closeHandler);
    }

    @Override
    public  Stream map(Function mapper) {
        return decorate(delegate.map(mapper), closeHandler);
    }

    @Override
    public IntStream mapToInt(ToIntFunction mapper) {
        return AutoClosingIntStream.decorate(delegate.mapToInt(mapper), closeHandler);
    }

    @Override
    public LongStream mapToLong(ToLongFunction mapper) {
        return AutoClosingLongStream.decorate(delegate.mapToLong(mapper), closeHandler);
    }

    @Override
    public DoubleStream mapToDouble(ToDoubleFunction mapper) {
        return AutoClosingDoubleStream.decorate(delegate.mapToDouble(mapper), closeHandler);
    }

    @Override
    public  Stream flatMap(Function> mapper) {
        return decorate(delegate.flatMap(mapper), closeHandler);
    }

    @Override
    public IntStream flatMapToInt(Function mapper) {
        return AutoClosingIntStream.decorate(delegate.flatMapToInt(mapper), closeHandler);
    }

    @Override
    public LongStream flatMapToLong(Function mapper) {
        return AutoClosingLongStream.decorate(delegate.flatMapToLong(mapper), closeHandler);
    }

    @Override
    public DoubleStream flatMapToDouble(Function mapper) {
        return AutoClosingDoubleStream.decorate(delegate.flatMapToDouble(mapper), closeHandler);
    }

    @Override
    public  Stream mapMulti(BiConsumer> mapper) {
        return decorate(delegate.mapMulti(mapper), closeHandler);
    }

    @Override
    public IntStream mapMultiToInt(BiConsumer mapper) {
        return AutoClosingIntStream.decorate(delegate.mapMultiToInt(mapper), closeHandler);
    }

    @Override
    public LongStream mapMultiToLong(BiConsumer mapper) {
        return AutoClosingLongStream.decorate(delegate.mapMultiToLong(mapper), closeHandler);
    }

    @Override
    public DoubleStream mapMultiToDouble(BiConsumer mapper) {
        return AutoClosingDoubleStream.decorate(delegate.mapMultiToDouble(mapper), closeHandler);
    }

    @Override
    public Stream distinct() {
        return decorate(delegate.distinct(), closeHandler);
    }

    @Override
    public Stream sorted() {
        return decorate(delegate.sorted(), closeHandler);
    }

    @Override
    public Stream sorted(Comparator comparator) {
        return decorate(delegate.sorted(comparator), closeHandler);
    }

    @Override
    public Stream peek(Consumer action) {
        return decorate(delegate.peek(action), closeHandler);
    }

    @Override
    public Stream limit(long maxSize) {
        return decorate(delegate.limit(maxSize), closeHandler);
    }

    @Override
    public Stream skip(long n) {
        return decorate(delegate.skip(n), closeHandler);
    }

    @Override
    public Stream takeWhile(Predicate predicate) {
        return decorate(delegate.takeWhile(predicate), closeHandler);
    }

    @Override
    public Stream dropWhile(Predicate predicate) {
        return decorate(delegate.dropWhile(predicate), closeHandler);
    }

    @Override
    public Iterator iterator() {
        Iterator iterator = delegate.iterator();
        return new Iterator<>() {
            @Override
            public boolean hasNext() {
                if (iterator.hasNext()) {
                    return true;
                }
                closeHandler.run();
                return false;
            }

            @Override
            public T next() {
                return iterator.next();
            }
        };
    }

    @Override
    public Spliterator spliterator() {
        Spliterator spliterator = delegate.spliterator();
        return new Spliterator<>() {
            @Override
            public boolean tryAdvance(Consumer action) {
                if (spliterator.tryAdvance(action)) {
                    return true;
                }
                closeHandler.run();
                return false;
            }

            @Override
            public Spliterator trySplit() {
                return spliterator.trySplit();
            }

            @Override
            public long estimateSize() {
                return spliterator.estimateSize();
            }

            @Override
            public int characteristics() {
                return spliterator.characteristics();
            }
        };
    }

    @Override
    public boolean isParallel() {
        return delegate.isParallel();
    }

    @Override
    public Stream sequential() {
        return decorate(delegate.sequential(), closeHandler);
    }

    @Override
    public Stream parallel() {
        return decorate(delegate.parallel(), closeHandler);
    }

    @Override
    public Stream unordered() {
        return decorate(delegate.unordered(), closeHandler);
    }

    @Override
    public Stream onClose(Runnable closeHandler) {
        return decorate(delegate.onClose(closeHandler), this.closeHandler);
    }

    @Override
    public void close() {
        closeHandler.run();
    }
}