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 *      https://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.output;
019
020import java.io.FilterWriter;
021import java.io.IOException;
022import java.io.UncheckedIOException;
023import java.io.Writer;
024
025import org.apache.commons.io.build.AbstractStreamBuilder;
026import org.apache.commons.io.function.Uncheck;
027
028/**
029 * A {@link FilterWriter} that throws {@link UncheckedIOException} instead of {@link IOException}.
030 * <p>
031 * To build an instance, use {@link Builder}.
032 * </p>
033 *
034 * @see Builder
035 * @see FilterWriter
036 * @see IOException
037 * @see UncheckedIOException
038 * @since 2.12.0
039 */
040public final class UncheckedFilterWriter extends FilterWriter {
041
042    // @formatter:off
043    /**
044     * Builds a new {@link UncheckedFilterWriter}.
045     *
046     * <p>
047     * Using File IO:
048     * </p>
049     * <pre>{@code
050     * UncheckedFilterWriter s = UncheckedFilterWriter.builder()
051     *   .setFile(file)
052     *   .get();}
053     * </pre>
054     * <p>
055     * Using NIO Path:
056     * </p>
057     * <pre>{@code
058     * UncheckedFilterWriter s = UncheckedFilterWriter.builder()
059     *   .setPath(path)
060     *   .get();}
061     * </pre>
062     *
063     * @see #get()
064     */
065    // @formatter:on
066    public static class Builder extends AbstractStreamBuilder<UncheckedFilterWriter, Builder> {
067
068        /**
069         * Constructs a builder of {@link UncheckedFilterWriter}.
070         */
071        public Builder() {
072            // empty
073        }
074
075        /**
076         * Builds a new {@link UncheckedFilterWriter}.
077         * <p>
078         * You must set an aspect that supports {@link #getWriter()} on this builder, otherwise, this method throws an exception.
079         * </p>
080         * <p>
081         * This builder uses the following aspects:
082         * </p>
083         * <ul>
084         * <li>{@link #getWriter()}</li>
085         * </ul>
086         *
087         * @return a new instance.
088         * @throws UnsupportedOperationException if the origin cannot provide a {@link Writer}.
089         * @throws IOException                   if an I/O error occurs converting to an {@link Writer} using {@link #getWriter()}.
090         * @see #getWriter()
091         * @see #getUnchecked()
092         */
093        @Override
094        public UncheckedFilterWriter get() throws IOException {
095            return new UncheckedFilterWriter(this);
096        }
097
098    }
099
100    /**
101     * Constructs a new {@link Builder}.
102     *
103     * @return a new {@link Builder}.
104     */
105    public static Builder builder() {
106        return new Builder();
107    }
108
109    /**
110     * Constructs a new filtered writer.
111     *
112     * @param builder a Writer object providing the underlying stream.
113     * @throws IOException
114     * @throws NullPointerException if {@code builder} the its {@code Writer} is {@code null}.
115     * @throws IOException          if an I/O error occurs converting to an {@link Writer} using {@link #getWriter()}.
116     */
117    @SuppressWarnings("resource") // Caller closes.
118    private UncheckedFilterWriter(final Builder builder) throws IOException {
119        super(builder.getWriter());
120    }
121
122    /**
123     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
124     */
125    @Override
126    public Writer append(final char c) throws UncheckedIOException {
127        return Uncheck.apply(super::append, c);
128    }
129
130    /**
131     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
132     */
133    @Override
134    public Writer append(final CharSequence csq) throws UncheckedIOException {
135        return Uncheck.apply(super::append, csq);
136    }
137
138    /**
139     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
140     */
141    @Override
142    public Writer append(final CharSequence csq, final int start, final int end) throws UncheckedIOException {
143        return Uncheck.apply(super::append, csq, start, end);
144    }
145
146    /**
147     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
148     */
149    @Override
150    public void close() throws UncheckedIOException {
151        Uncheck.run(super::close);
152    }
153
154    /**
155     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
156     */
157    @Override
158    public void flush() throws UncheckedIOException {
159        Uncheck.run(super::flush);
160    }
161
162    /**
163     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
164     */
165    @Override
166    public void write(final char[] cbuf) throws UncheckedIOException {
167        Uncheck.accept(super::write, cbuf);
168    }
169
170    /**
171     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
172     */
173    @Override
174    public void write(final char[] cbuf, final int off, final int len) throws UncheckedIOException {
175        Uncheck.accept(super::write, cbuf, off, len);
176    }
177
178    /**
179     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
180     */
181    @Override
182    public void write(final int c) throws UncheckedIOException {
183        Uncheck.accept(super::write, c);
184    }
185
186    /**
187     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
188     */
189    @Override
190    public void write(final String str) throws UncheckedIOException {
191        Uncheck.accept(super::write, str);
192    }
193
194    /**
195     * Calls this method's super and rethrow {@link IOException} as {@link UncheckedIOException}.
196     */
197    @Override
198    public void write(final String str, final int off, final int len) throws UncheckedIOException {
199        Uncheck.accept(super::write, str, off, len);
200    }
201
202}