001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.parser;
014
015import java.nio.charset.*;
016
017import org.apache.juneau.*;
018import org.apache.juneau.annotation.*;
019import org.apache.juneau.internal.*;
020
021/**
022 * Subclass of {@link Parser} for characters-based parsers.
023 *
024 * <h5 class='topic'>Description</h5>
025 *
026 * This class is typically the parent class of all character-based parsers.
027 * It has 1 abstract method to implement...
028 * <ul>
029 *    <li><c>parse(ParserSession, ClassMeta)</c>
030 * </ul>
031 */
032@ConfigurableContext
033public abstract class ReaderParser extends Parser {
034
035   //-------------------------------------------------------------------------------------------------------------------
036   // Configurable properties
037   //-------------------------------------------------------------------------------------------------------------------
038
039   static final String PREFIX = "ReaderParser";
040
041   /**
042    * Configuration property:  File charset.
043    *
044    * <h5 class='section'>Property:</h5>
045    * <ul class='spaced-list'>
046    *    <li><b>ID:</b>  {@link org.apache.juneau.parser.ReaderParser#RPARSER_fileCharset RPARSER_fileCharset}
047    *    <li><b>Name:</b>  <js>"ReaderParser.fileCharset.s"</js>
048    *    <li><b>Data type:</b>  <c>String</c>
049    *    <li><b>System property:</b>  <c>ReaderParser.fileCharset</c>
050    *    <li><b>Environment variable:</b>  <c>READERPARSER_FILECHARSET</c>
051    *    <li><b>Default:</b>  <js>"DEFAULT"</js>
052    *    <li><b>Session property:</b>  <jk>false</jk>
053    *    <li><b>Annotations:</b>
054    *       <ul>
055    *          <li class='ja'>{@link org.apache.juneau.parser.annotation.ParserConfig#fileCharset()}
056    *       </ul>
057    *    <li><b>Methods:</b>
058    *       <ul>
059    *          <li class='jm'>{@link org.apache.juneau.parser.ReaderParserBuilder#fileCharset(Charset)}
060    *       </ul>
061    * </ul>
062    *
063    * <h5 class='section'>Description:</h5>
064    * <p>
065    * The character set to use for reading <c>Files</c> from the file system.
066    *
067    * <p>
068    * Used when passing in files to {@link Parser#parse(Object, Class)}.
069    *
070    * <p>
071    * <js>"DEFAULT"</js> can be used to indicate the JVM default file system charset.
072    *
073    * <h5 class='section'>Example:</h5>
074    * <p class='bcode w800'>
075    *    <jc>// Create a parser that reads UTF-8 files.</jc>
076    *    ReaderParser p = JsonParser.
077    *       .<jsm>create</jsm>()
078    *       .fileCharset(<js>"UTF-8"</js>)
079    *       .build();
080    *
081    *    <jc>// Same, but use property.</jc>
082    *    ReaderParser p = JsonParser.
083    *       .<jsm>create</jsm>()
084    *       .set(<jsf>RPARSER_fileCharset</jsf>, <js>"UTF-8"</js>)
085    *       .build();
086    *
087    *    <jc>// Use it to read a UTF-8 encoded file.</jc>
088    *    MyBean myBean = p.parse(<jk>new</jk> File(<js>"MyBean.txt"</js>), MyBean.<jk>class</jk>);
089    * </p>
090    */
091   public static final String RPARSER_fileCharset = PREFIX + ".fileCharset.s";
092
093   /**
094    * Configuration property:  Input stream charset.
095    *
096    * <h5 class='section'>Property:</h5>
097    * <ul class='spaced-list'>
098    *    <li><b>ID:</b>  {@link org.apache.juneau.parser.ReaderParser#RPARSER_streamCharset RPARSER_streamCharset}
099    *    <li><b>Name:</b>  <js>"ReaderParser.streamCharset.s"</js>
100    *    <li><b>Data type:</b>  <c>String</c>
101    *    <li><b>System property:</b>  <c>ReaderParser.streamCharset</c>
102    *    <li><b>Environment variable:</b>  <c>READERPARSER_STREAMCHARSET</c>
103    *    <li><b>Default:</b>  <js>"UTF-8"</js>
104    *    <li><b>Session property:</b>  <jk>false</jk>
105    *    <li><b>Annotations:</b>
106    *       <ul>
107    *          <li class='ja'>{@link org.apache.juneau.parser.annotation.ParserConfig#streamCharset()}
108    *       </ul>
109    *    <li><b>Methods:</b>
110    *       <ul>
111    *          <li class='jm'>{@link org.apache.juneau.parser.ReaderParserBuilder#streamCharset(Charset)}
112    *       </ul>
113    * </ul>
114    *
115    * <h5 class='section'>Description:</h5>
116    * <p>
117    * The character set to use for converting <c>InputStreams</c> and byte arrays to readers.
118    *
119    * <p>
120    * Used when passing in input streams and byte arrays to {@link Parser#parse(Object, Class)}.
121    *
122    * <h5 class='section'>Example:</h5>
123    * <p class='bcode w800'>
124    *    <jc>// Create a parser that reads UTF-8 files.</jc>
125    *    ReaderParser p = JsonParser.
126    *       .<jsm>create</jsm>()
127    *       .streamCharset(Charset.<jsm>forName</jsm>(<js>"UTF-8"</js>))
128    *       .build();
129    *
130    *    <jc>// Same, but use property.</jc>
131    *    ReaderParser p = JsonParser.
132    *       .<jsm>create</jsm>()
133    *       .set(<jsf>RPARSER_streamCharset</jsf>, <js>"UTF-8"</js>)
134    *       .build();
135    *
136    *    <jc>// Use it to read a UTF-8 encoded input stream.</jc>
137    *    MyBean myBean = p.parse(<jk>new</jk> FileInputStream(<js>"MyBean.txt"</js>), MyBean.<jk>class</jk>);
138    * </p>
139    */
140   public static final String RPARSER_streamCharset = PREFIX + ".streamCharset.s";
141
142   static final ReaderParser DEFAULT = new ReaderParser(PropertyStore.create().build(), "") {
143      @Override
144      public ReaderParserSession createSession(ParserSessionArgs args) {
145         throw new NoSuchMethodError();
146      }
147   };
148
149   //-------------------------------------------------------------------------------------------------------------------
150   // Instance
151   //-------------------------------------------------------------------------------------------------------------------
152
153   private final Charset streamCharset, fileCharset;
154
155   /**
156    * Constructor.
157    *
158    * @param ps The property store containing all the settings for this object.
159    * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>, <js>"*&#8203;/json"</js>).
160    */
161   protected ReaderParser(PropertyStore ps, String...consumes) {
162      super(ps, consumes);
163
164      streamCharset = getProperty(RPARSER_streamCharset, Charset.class, IOUtils.UTF8);
165      fileCharset = getProperty(RPARSER_fileCharset, Charset.class, Charset.defaultCharset());
166   }
167
168   @Override /* Parser */
169   public final boolean isReaderParser() {
170      return true;
171   }
172
173   //-----------------------------------------------------------------------------------------------------------------
174   // Properties
175   //-----------------------------------------------------------------------------------------------------------------
176
177   /**
178    * Configuration property:  File charset.
179    *
180    * @see #RPARSER_fileCharset
181    * @return
182    *    The character set to use for reading <c>Files</c> from the file system.
183    */
184   protected final Charset getFileCharset() {
185      return fileCharset;
186   }
187
188   /**
189    * Configuration property:  Input stream charset.
190    *
191    * @see #RPARSER_streamCharset
192    * @return
193    *    The character set to use for converting <c>InputStreams</c> and byte arrays to readers.
194    */
195   protected final Charset getStreamCharset() {
196      return streamCharset;
197   }
198
199   //-----------------------------------------------------------------------------------------------------------------
200   // Other methods
201   //-----------------------------------------------------------------------------------------------------------------
202
203   @Override /* Context */
204   public ObjectMap toMap() {
205      return super.toMap()
206         .append("ReaderParser", new DefaultFilteringObjectMap()
207            .append("fileCharset", fileCharset)
208            .append("streamCharset", streamCharset)
209         );
210   }
211}