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.build;
019
020import java.io.IOException;
021import java.io.InputStream;
022import java.io.OutputStream;
023import java.io.Writer;
024import java.nio.charset.Charset;
025import java.nio.file.OpenOption;
026import java.nio.file.Path;
027
028import org.apache.commons.io.Charsets;
029import org.apache.commons.io.IOUtils;
030import org.apache.commons.io.file.PathUtils;
031
032/**
033 * Abstracts building a typed instance of {@code T}.
034 *
035 * @param <T> the type of instances to build.
036 * @param <B> the type of builder subclass.
037 * @since 2.12.0
038 */
039public abstract class AbstractStreamBuilder<T, B extends AbstractStreamBuilder<T, B>> extends AbstractOriginSupplier<T, B> {
040
041    private static final OpenOption[] DEFAULT_OPEN_OPTIONS = PathUtils.EMPTY_OPEN_OPTION_ARRAY;
042
043    /**
044     * The buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
045     */
046    private int bufferSize = IOUtils.DEFAULT_BUFFER_SIZE;
047
048    /**
049     * The buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
050     */
051    private int bufferSizeDefault = IOUtils.DEFAULT_BUFFER_SIZE;
052
053    /**
054     * The Charset, defaults to {@link Charset#defaultCharset()}.
055     */
056    private Charset charset = Charset.defaultCharset();
057
058    /**
059     * The Charset, defaults to {@link Charset#defaultCharset()}.
060     */
061    private Charset charsetDefault = Charset.defaultCharset();
062
063    private OpenOption[] openOptions = DEFAULT_OPEN_OPTIONS;
064
065    /**
066     * Gets the buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
067     *
068     * @return the buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
069     */
070    protected int getBufferSize() {
071        return bufferSize;
072    }
073
074    /**
075     * Gets the buffer size default, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
076     *
077     * @return the buffer size default, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
078     */
079    protected int getBufferSizeDefault() {
080        return bufferSizeDefault;
081    }
082
083    /**
084     * Gets a CharSequence from the origin with a Charset.
085     *
086     * @return An input stream
087     * @throws IOException                   if an I/O error occurs.
088     * @throws UnsupportedOperationException if the origin cannot be converted to a CharSequence.
089     * @throws IllegalStateException if the {@code origin} is {@code null}.
090     * @see AbstractOrigin#getCharSequence(Charset)
091     * @since 2.13.0
092     */
093    protected CharSequence getCharSequence() throws IOException {
094        return checkOrigin().getCharSequence(getCharset());
095    }
096
097    /**
098     * Gets the Charset, defaults to {@link Charset#defaultCharset()}.
099     *
100     * @return the Charset, defaults to {@link Charset#defaultCharset()}.
101     */
102    public Charset getCharset() {
103        return charset;
104    }
105
106    /**
107     * Gets the Charset default, defaults to {@link Charset#defaultCharset()}.
108     *
109     * @return the Charset default, defaults to {@link Charset#defaultCharset()}.
110     */
111    protected Charset getCharsetDefault() {
112        return charsetDefault;
113    }
114
115    /**
116     * Gets an input stream from the origin with open options.
117     *
118     * @return An input stream
119     * @throws IOException                   if an I/O error occurs.
120     * @throws UnsupportedOperationException if the origin cannot be converted to an InputStream.
121     * @see AbstractOrigin#getInputStream(OpenOption...)
122     * @throws IllegalStateException if the {@code origin} is {@code null}.
123     * @since 2.13.0
124     */
125    protected InputStream getInputStream() throws IOException {
126        return checkOrigin().getInputStream(getOpenOptions());
127    }
128
129    protected OpenOption[] getOpenOptions() {
130        return openOptions;
131    }
132
133    /**
134     * Gets an OutputStream from the origin with open options.
135     *
136     * @return An OutputStream
137     * @throws IOException                   if an I/O error occurs.
138     * @throws UnsupportedOperationException if the origin cannot be converted to an OututStream.
139     * @throws IllegalStateException if the {@code origin} is {@code null}.
140     * @see AbstractOrigin#getOutputStream(OpenOption...)
141     * @since 2.13.0
142     */
143    protected OutputStream getOutputStream() throws IOException {
144        return checkOrigin().getOutputStream(getOpenOptions());
145    }
146
147    /**
148     * Gets a Path from the origin.
149     *
150     * @return A Path
151     * @throws UnsupportedOperationException if the origin cannot be converted to a Path.
152     * @throws IllegalStateException if the {@code origin} is {@code null}.
153     * @see AbstractOrigin#getPath()
154     * @since 2.13.0
155     */
156    protected Path getPath() {
157        return checkOrigin().getPath();
158    }
159
160    /**
161     * Gets an writer from the origin with open options.
162     *
163     * @return An writer.
164     * @throws IOException                   if an I/O error occurs.
165     * @throws UnsupportedOperationException if the origin cannot be converted to a Writer.
166     * @throws IllegalStateException if the {@code origin} is {@code null}.
167     * @see AbstractOrigin#getOutputStream(OpenOption...)
168     * @since 2.13.0
169     */
170    protected Writer getWriter() throws IOException {
171        return checkOrigin().getWriter(getCharset(), getOpenOptions());
172    }
173
174    /**
175     * Sets the buffer size. Invalid input (bufferSize &lt;= 0) resets the value to its default.
176     * <p>
177     * Subclasses may ignore this setting.
178     * </p>
179     *
180     * @param bufferSize the buffer size.
181     * @return this.
182     */
183    public B setBufferSize(final int bufferSize) {
184        this.bufferSize = bufferSize > 0 ? bufferSize : bufferSizeDefault;
185        return asThis();
186    }
187
188    /**
189     * Sets the buffer size.
190     * <p>
191     * Subclasses may ignore this setting.
192     * </p>
193     *
194     * @param bufferSize the buffer size, null resets to the default.
195     * @return this.
196     */
197    public B setBufferSize(final Integer bufferSize) {
198        setBufferSize(bufferSize != null ? bufferSize : bufferSizeDefault);
199        return asThis();
200    }
201
202    /**
203     * Sets the buffer size for subclasses to initialize.
204     * <p>
205     * Subclasses may ignore this setting.
206     * </p>
207     *
208     * @param bufferSizeDefault the buffer size, null resets to the default.
209     * @return this.
210     */
211    protected B setBufferSizeDefault(final int bufferSizeDefault) {
212        this.bufferSizeDefault = bufferSizeDefault;
213        return asThis();
214    }
215
216    /**
217     * Sets the Charset.
218     * <p>
219     * Subclasses may ignore this setting.
220     * </p>
221     *
222     * @param charset the Charset, null resets to the default.
223     * @return this.
224     */
225    public B setCharset(final Charset charset) {
226        this.charset = Charsets.toCharset(charset, charsetDefault);
227        return asThis();
228    }
229
230    /**
231     * Sets the Charset.
232     * <p>
233     * Subclasses may ignore this setting.
234     * </p>
235     *
236     * @param charset the Charset name, null resets to the default.
237     * @return this.
238     */
239    public B setCharset(final String charset) {
240        return setCharset(Charsets.toCharset(charset, charsetDefault));
241    }
242
243    /**
244     * Sets the Charset default for subclasses to initialize.
245     * <p>
246     * Subclasses may ignore this setting.
247     * </p>
248     *
249     * @param defaultCharset the Charset name, null resets to the default.
250     * @return this.
251     */
252    protected B setCharsetDefault(final Charset defaultCharset) {
253        this.charsetDefault = defaultCharset;
254        return asThis();
255    }
256
257    /**
258     * Sets the OpenOption[].
259     * <p>
260     * Normally used with InputStream, OutputStream, and Writer.
261     * </p>
262     * <p>
263     * Subclasses may ignore this setting.
264     * </p>
265     *
266     * @param openOptions the OpenOption[] name, null resets to the default.
267     * @return this.
268     * @since 2.13.0
269     * @see #setInputStream(InputStream)
270     * @see #setOutputStream(OutputStream)
271     * @see #setWriter(Writer)
272     */
273    public B setOpenOptions(final OpenOption... openOptions) {
274        this.openOptions = openOptions != null ? openOptions : DEFAULT_OPEN_OPTIONS;
275        return asThis();
276    }
277}