001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.io.function;
019
020import java.io.Closeable;
021import java.io.IOException;
022import java.io.UncheckedIOException;
023import java.util.stream.BaseStream;
024import java.util.stream.Stream;
025
026/**
027 * Like {@link BaseStream} but throws {@link IOException}.
028 *
029 * @param <T> the type of the stream elements.
030 * @param <S> the type of the IO stream extending {@code IOBaseStream}.
031 * @param <B> the type of the stream extending {@code BaseStream}.
032 * @since 2.12.0
033 */
034public interface IOBaseStream<T, S extends IOBaseStream<T, S, B>, B extends BaseStream<T, B>> extends Closeable {
035
036    /**
037     * Constructs a {@link BaseStream} for this instance that throws {@link UncheckedIOException} instead of
038     * {@link IOException}.
039     *
040     * @return an {@link UncheckedIOException} {@link BaseStream}.
041     */
042    @SuppressWarnings("unchecked")
043    default BaseStream<T, B> asBaseStream() {
044        return new UncheckedIOBaseStream<>((S) this);
045    }
046
047    /**
048     * Like {@link BaseStream#close()}.
049     *
050     * @see BaseStream#close()
051     */
052    @Override
053    default void close() {
054        unwrap().close();
055    }
056
057    /**
058     * Like {@link BaseStream#isParallel()}.
059     *
060     * @return See {@link BaseStream#isParallel() delegate}.
061     * @see BaseStream#isParallel()
062     */
063    @SuppressWarnings("resource") // for unwrap()
064    default boolean isParallel() {
065        return unwrap().isParallel();
066    }
067
068    /**
069     * Like {@link BaseStream#iterator()}.
070     *
071     * @return See {@link BaseStream#iterator() delegate}.
072     * @see BaseStream#iterator()
073     */
074    @SuppressWarnings("resource") // for unwrap()
075    default IOIterator<T> iterator() {
076        return IOIteratorAdapter.adapt(unwrap().iterator());
077    }
078
079    /**
080     * Like {@link BaseStream#onClose(Runnable)}.
081     *
082     * @param closeHandler See {@link BaseStream#onClose(Runnable) delegate}.
083     * @return See {@link BaseStream#onClose(Runnable) delegate}.
084     * @throws IOException if an I/O error occurs.
085     * @see BaseStream#onClose(Runnable)
086     */
087    @SuppressWarnings({"unused", "resource"}) // throws IOException, unwrap()
088    default S onClose(final IORunnable closeHandler) throws IOException {
089        return wrap(unwrap().onClose(() -> Erase.run(closeHandler)));
090    }
091
092    /**
093     * Like {@link BaseStream#parallel()}.
094     *
095     * @return See {@link BaseStream#parallel() delegate}.
096     * @see BaseStream#parallel()
097     */
098    @SuppressWarnings({"resource", "unchecked"}) // for unwrap(), this
099    default S parallel() {
100        return isParallel() ? (S) this : wrap(unwrap().parallel());
101    }
102
103    /**
104     * Like {@link BaseStream#sequential()}.
105     *
106     * @return See {@link BaseStream#sequential() delegate}.
107     * @see BaseStream#sequential()
108     */
109    @SuppressWarnings({"resource", "unchecked"}) // for unwrap(), this
110    default S sequential() {
111        return isParallel() ? wrap(unwrap().sequential()) : (S) this;
112    }
113
114    /**
115     * Like {@link BaseStream#spliterator()}.
116     *
117     * @return See {@link BaseStream#spliterator() delegate}.
118     * @see BaseStream#spliterator()
119     */
120    @SuppressWarnings("resource") // for unwrap()
121    default IOSpliterator<T> spliterator() {
122        return IOSpliteratorAdapter.adapt(unwrap().spliterator());
123    }
124
125    /**
126     * Like {@link BaseStream#unordered()}.
127     *
128     * @return See {@link BaseStream#unordered() delegate}.
129     * @see java.util.stream.BaseStream#unordered()
130     */
131    @SuppressWarnings("resource") // for unwrap()
132    default S unordered() {
133        return wrap(unwrap().unordered());
134    }
135
136    /**
137     * Unwraps this instance and returns the underlying {@link Stream}.
138     * <p>
139     * Implementations may not have anything to unwrap and that behavior is undefined for now.
140     * </p>
141     *
142     * @return the underlying stream.
143     */
144    B unwrap();
145
146    /**
147     * Wraps a {@link Stream}.
148     *
149     * @param delegate The delegate.
150     * @return An IO stream.
151     */
152    S wrap(B delegate);
153
154}