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 */
017package org.apache.juneau.parser;
018
019import static org.apache.juneau.commons.utils.AssertionUtils.*;
020
021import java.io.*;
022import java.lang.reflect.*;
023import java.nio.charset.*;
024import java.util.*;
025import java.util.function.*;
026
027import org.apache.juneau.*;
028import org.apache.juneau.commons.collections.FluentMap;
029import org.apache.juneau.httppart.*;
030
031/**
032 * Subclass of parser session objects for character-based parsers.
033 *
034 * <h5 class='section'>Notes:</h5><ul>
035 *    <li class='warn'>This class is not thread safe and is typically discarded after one use.
036 * </ul>
037 *
038 * <h5 class='section'>See Also:</h5><ul>
039 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
040 * </ul>
041 */
042public class ReaderParserSession extends ParserSession {
043   /**
044    * Builder class.
045    */
046   public static class Builder extends ParserSession.Builder {
047
048      private Charset fileCharset;
049      private Charset streamCharset;
050      private ReaderParser ctx;
051
052      /**
053       * Constructor
054       *
055       * @param ctx The context creating this session.
056       *    <br>Cannot be <jk>null</jk>.
057       */
058      protected Builder(ReaderParser ctx) {
059         super(assertArgNotNull("ctx", ctx));
060         this.ctx = ctx;
061         fileCharset = ctx.getFileCharset();
062         streamCharset = ctx.getStreamCharset();
063      }
064
065      @Override /* Overridden from Builder */
066      public <T> Builder apply(Class<T> type, Consumer<T> apply) {
067         super.apply(type, apply);
068         return this;
069      }
070
071      @Override
072      public ReaderParserSession build() {
073         return new ReaderParserSession(this);
074      }
075
076      @Override /* Overridden from Builder */
077      public Builder debug(Boolean value) {
078         super.debug(value);
079         return this;
080      }
081
082      /**
083       * File charset.
084       *
085       * <p>
086       * The character set to use for reading Files from the file system.
087       *
088       * <p>
089       * Used when passing in files to {@link Parser#parse(Object, Class)}.
090       *
091       * <p>
092       * If not specified, defaults to the JVM system default charset.
093       *
094       * @param value
095       *    The new property value.
096       *    <br>Can be <jk>null</jk>.
097       * @return This object.
098       */
099      public Builder fileCharset(Charset value) {
100         fileCharset = value;
101         return this;
102      }
103
104      @Override /* Overridden from Builder */
105      public Builder javaMethod(Method value) {
106         super.javaMethod(value);
107         return this;
108      }
109
110      @Override /* Overridden from Builder */
111      public Builder locale(Locale value) {
112         super.locale(value);
113         return this;
114      }
115
116      @Override /* Overridden from Builder */
117      public Builder mediaType(MediaType value) {
118         super.mediaType(value);
119         return this;
120      }
121
122      @Override /* Overridden from Builder */
123      public Builder mediaTypeDefault(MediaType value) {
124         super.mediaTypeDefault(value);
125         return this;
126      }
127
128      @Override /* Overridden from Builder */
129      public Builder outer(Object value) {
130         super.outer(value);
131         return this;
132      }
133
134      @Override /* Overridden from Builder */
135      public Builder properties(Map<String,Object> value) {
136         super.properties(value);
137         return this;
138      }
139
140      @Override /* Overridden from Builder */
141      public Builder property(String key, Object value) {
142         super.property(key, value);
143         return this;
144      }
145
146      @Override /* Overridden from Builder */
147      public Builder schema(HttpPartSchema value) {
148         super.schema(value);
149         return this;
150      }
151
152      @Override /* Overridden from Builder */
153      public Builder schemaDefault(HttpPartSchema value) {
154         super.schemaDefault(value);
155         return this;
156      }
157
158      /**
159       * Input stream charset.
160       *
161       * <p>
162       * The character set to use for converting InputStreams and byte arrays to readers.
163       *
164       * <p>
165       * Used when passing in input streams and byte arrays to {@link Parser#parse(Object, Class)}.
166       *
167       * <p>
168       * If not specified, defaults to UTF-8.
169       *
170       * @param value
171       *    The new property value.
172       *    <br>Can be <jk>null</jk> (defaults to UTF-8).
173       * @return This object.
174       */
175      public Builder streamCharset(Charset value) {
176         streamCharset = value;
177         return this;
178      }
179
180      @Override /* Overridden from Builder */
181      public Builder timeZone(TimeZone value) {
182         super.timeZone(value);
183         return this;
184      }
185
186      @Override /* Overridden from Builder */
187      public Builder timeZoneDefault(TimeZone value) {
188         super.timeZoneDefault(value);
189         return this;
190      }
191
192      @Override /* Overridden from Builder */
193      public Builder unmodifiable() {
194         super.unmodifiable();
195         return this;
196      }
197   }
198
199   /**
200    * Creates a new builder for this object.
201    *
202    * @param ctx The context creating this session.
203    *    <br>Cannot be <jk>null</jk>.
204    * @return A new builder.
205    */
206   public static Builder create(ReaderParser ctx) {
207      return new Builder(assertArgNotNull("ctx", ctx));
208   }
209
210   private final ReaderParser ctx;
211   private final Charset fileCharset;
212   private final Charset streamCharset;
213
214   /**
215    * Constructor.
216    *
217    * @param builder The builder for this object.
218    */
219   protected ReaderParserSession(Builder builder) {
220      super(builder);
221      ctx = builder.ctx;
222      fileCharset = builder.fileCharset;
223      streamCharset = builder.streamCharset;
224   }
225
226   /**
227    * Wraps the specified input object into a {@link ParserPipe} object so that it can be easily converted into
228    * a stream or reader.
229    *
230    * @param input
231    *    The input.
232    *    <br>This can be any of the following types:
233    *    <ul>
234    *       <li><jk>null</jk>
235    *       <li>{@link Reader}
236    *       <li>{@link CharSequence}
237    *       <li>{@link InputStream} containing UTF-8 encoded text (or whatever the encoding specified by
238    *          {@link ReaderParser.Builder#streamCharset(Charset)}).
239    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or whatever the encoding specified by
240    *          {@link ReaderParser.Builder#streamCharset(Charset)}).
241    *       <li>{@link File} containing system encoded text (or whatever the encoding specified by
242    *          {@link ReaderParser.Builder#streamCharset(Charset)}).
243    *    </ul>
244    * @return
245    *    A new {@link ParserPipe} wrapper around the specified input object.
246    */
247   @SuppressWarnings("resource")
248   @Override /* Overridden from ParserSesson */
249   public final ParserPipe createPipe(Object input) {
250      return setPipe(new ParserPipe(input, isDebug(), ctx.isStrict(), ctx.isAutoCloseStreams(), ctx.isUnbuffered(), streamCharset, fileCharset));
251   }
252
253   /**
254    * Returns the file charset defined on this session.
255    *
256    * @return the file charset defined on this session.
257    */
258   public Charset getFileCharset() { return fileCharset; }
259
260   /**
261    * Returns the stream charset defined on this session.
262    *
263    * @return the stream charset defined on this session.
264    */
265   public Charset getStreamCharset() { return streamCharset; }
266
267   @Override /* Overridden from ParserSession */
268   public final boolean isReaderParser() { return true; }
269
270   @Override /* Overridden from ParserSession */
271   protected FluentMap<String,Object> properties() {
272      return super.properties()
273         .a("fileCharset", fileCharset)
274         .a("streamCharset", streamCharset);
275   }
276}