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