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 static org.apache.juneau.collections.JsonMap.*;
016import static org.apache.juneau.common.internal.StringUtils.*;
017import static org.apache.juneau.internal.CollectionUtils.*;
018
019import java.io.*;
020import java.lang.annotation.*;
021import java.lang.reflect.*;
022import java.nio.charset.*;
023import java.util.*;
024
025import org.apache.juneau.*;
026import org.apache.juneau.collections.*;
027import org.apache.juneau.html.*;
028import org.apache.juneau.internal.*;
029import org.apache.juneau.json.*;
030import org.apache.juneau.msgpack.*;
031import org.apache.juneau.objecttools.*;
032import org.apache.juneau.swap.*;
033import org.apache.juneau.swaps.*;
034import org.apache.juneau.uon.*;
035import org.apache.juneau.utils.*;
036import org.apache.juneau.xml.*;
037
038/**
039 * Parent class for all Juneau parsers.
040 *
041 * <h5 class='topic'>Valid data conversions</h5>
042 * <p>
043 * Parsers can parse any parsable POJO types, as specified in the <a class="doclink" href="../../../../index.html#jm.PojoCategories">POJO Categories</a>.
044 *
045 * <p>
046 * Some examples of conversions are shown below...
047 * </p>
048 * <table class='styled'>
049 *    <tr>
050 *       <th>Data type</th>
051 *       <th>Class type</th>
052 *       <th>JSON example</th>
053 *       <th>XML example</th>
054 *       <th>Class examples</th>
055 *    </tr>
056 *    <tr>
057 *       <td>object</td>
058 *       <td>Maps, Java beans</td>
059 *       <td class='code'>{name:<js>'John Smith'</js>,age:21}</td>
060 *       <td class='code'><xt>&lt;object&gt;
061 *    &lt;name</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>John Smith<xt>&lt;/name&gt;
062 *    &lt;age</xt> <xa>type</xa>=<xs>'number'</xs><xt>&gt;</xt>21<xt>&lt;/age&gt;
063 * &lt;/object&gt;</xt></td>
064 *       <td class='code'>HashMap, TreeMap&lt;String,Integer&gt;</td>
065 *    </tr>
066 *    <tr>
067 *       <td>array</td>
068 *       <td>Collections, Java arrays</td>
069 *       <td class='code'>[1,2,3]</td>
070 *       <td class='code'><xt>&lt;array&gt;
071 *    &lt;number&gt;</xt>1<xt>&lt;/number&gt;
072 *    &lt;number&gt;</xt>2<xt>&lt;/number&gt;
073 *    &lt;number&gt;</xt>3<xt>&lt;/number&gt;
074 * &lt;/array&gt;</xt></td>
075 *       <td class='code'>List&lt;Integer&gt;, <jk>int</jk>[], Float[], Set&lt;Person&gt;</td>
076 *    </tr>
077 *    <tr>
078 *       <td>number</td>
079 *       <td>Numbers</td>
080 *       <td class='code'>123</td>
081 *       <td class='code'><xt>&lt;number&gt;</xt>123<xt>&lt;/number&gt;</xt></td>
082 *       <td class='code'>Integer, Long, Float, <jk>int</jk></td>
083 *    </tr>
084 *    <tr>
085 *       <td>boolean</td>
086 *       <td>Booleans</td>
087 *       <td class='code'><jk>true</jk></td>
088 *       <td class='code'><xt>&lt;boolean&gt;</xt>true<xt>&lt;/boolean&gt;</xt></td>
089 *       <td class='code'>Boolean</td>
090 *    </tr>
091 *    <tr>
092 *       <td>string</td>
093 *       <td>CharSequences</td>
094 *       <td class='code'><js>'foobar'</js></td>
095 *       <td class='code'><xt>&lt;string&gt;</xt>foobar<xt>&lt;/string&gt;</xt></td>
096 *       <td class='code'>String, StringBuilder</td>
097 *    </tr>
098 * </table>
099 *
100 * <p>
101 * In addition, any class types with {@link ObjectSwap ObjectSwaps} associated with them on the registered
102 * bean context can also be passed in.
103 *
104 * <p>
105 * For example, if the {@link TemporalCalendarSwap} transform is used to generalize {@code Calendar} objects to {@code String}
106 * objects.
107 * When registered with this parser, you can construct {@code Calendar} objects from {@code Strings} using the
108 * following syntax...
109 * <p class='bjava'>
110 *    Calendar <jv>calendar</jv> = <jv>parser</jv>.parse(<js>"'Sun Mar 03 04:05:06 EST 2001'"</js>, GregorianCalendar.<jk>class</jk>);
111 * </p>
112 *
113 * <p>
114 * If <code>Object.<jk>class</jk></code> is specified as the target type, then the parser automatically determines the
115 * data types and generates the following object types...
116 * <table class='styled'>
117 *    <tr><th>JSON type</th><th>Class type</th></tr>
118 *    <tr><td>object</td><td>{@link JsonMap}</td></tr>
119 *    <tr><td>array</td><td>{@link JsonList}</td></tr>
120 *    <tr><td>number</td><td>{@link Number}<br>(depending on length and format, could be {@link Integer},
121 *       {@link Double}, {@link Float}, etc...)</td></tr>
122 *    <tr><td>boolean</td><td>{@link Boolean}</td></tr>
123 *    <tr><td>string</td><td>{@link String}</td></tr>
124 * </table>
125 *
126 * <h5 class='section'>Notes:</h5><ul>
127 *    <li class='note'>This class is thread safe and reusable.
128 * </ul>
129 *
130 * <h5 class='section'>See Also:</h5><ul>
131 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.SerializersAndParsers">Serializers and Parsers</a>
132
133 * </ul>
134 */
135public class Parser extends BeanContextable {
136
137   //-------------------------------------------------------------------------------------------------------------------
138   // Static
139   //-------------------------------------------------------------------------------------------------------------------
140
141   /**
142    * Creates a new builder for this object.
143    *
144    * @return A new builder.
145    */
146   public static Builder create() {
147      return new Builder();
148   }
149
150   //-------------------------------------------------------------------------------------------------------------------
151   // Static
152   //-------------------------------------------------------------------------------------------------------------------
153
154   /**
155    * Represents no Parser.
156    */
157   public static abstract class Null extends Parser {
158      private Null(Builder builder) {
159         super(builder);
160      }
161   }
162
163   /**
164    * Instantiates a builder of the specified parser class.
165    *
166    * <p>
167    * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public
168    * or protected constructor of the class.
169    *
170    * @param c The builder to create.
171    * @return A new builder.
172    */
173   public static Builder createParserBuilder(Class<? extends Parser> c) {
174      return (Builder)Context.createBuilder(c);
175   }
176
177   //-------------------------------------------------------------------------------------------------------------------
178   // Builder
179   //-------------------------------------------------------------------------------------------------------------------
180
181   /**
182    * Builder class.
183    */
184   @FluentSetters
185   public static class Builder extends BeanContextable.Builder {
186
187      boolean autoCloseStreams, strict, trimStrings, unbuffered;
188      String consumes;
189      int debugOutputLines;
190      Class<? extends ParserListener> listener;
191
192      /**
193       * Constructor, default settings.
194       */
195      protected Builder() {
196         super();
197         autoCloseStreams = env("Parser.autoCloseStreams", false);
198         strict = env("Parser.strict", false);
199         trimStrings = env("Parser.trimStrings", false);
200         unbuffered = env("Parser.unbuffered", false);
201         debugOutputLines = env("Parser.debugOutputLines", 5);
202         listener = null;
203         consumes = null;
204      }
205
206      /**
207       * Copy constructor.
208       *
209       * @param copyFrom The bean to copy from.
210       */
211      protected Builder(Parser copyFrom) {
212         super(copyFrom);
213         autoCloseStreams = copyFrom.autoCloseStreams;
214         strict = copyFrom.strict;
215         trimStrings = copyFrom.trimStrings;
216         unbuffered = copyFrom.unbuffered;
217         debugOutputLines = copyFrom.debugOutputLines;
218         listener = copyFrom.listener;
219         consumes = copyFrom.consumes;
220      }
221
222      /**
223       * Copy constructor.
224       *
225       * @param copyFrom The builder to copy from.
226       */
227      protected Builder(Builder copyFrom) {
228         super(copyFrom);
229         autoCloseStreams = copyFrom.autoCloseStreams;
230         strict = copyFrom.strict;
231         trimStrings = copyFrom.trimStrings;
232         unbuffered = copyFrom.unbuffered;
233         debugOutputLines = copyFrom.debugOutputLines;
234         listener = copyFrom.listener;
235         consumes = copyFrom.consumes;
236      }
237
238      @Override /* Context.Builder */
239      public Builder copy() {
240         return new Builder(this);
241      }
242
243      @Override /* Context.Builder */
244      public Parser build() {
245         return build(Parser.class);
246      }
247
248      @Override /* Context.Builder */
249      public HashKey hashKey() {
250         return HashKey.of(
251            super.hashKey(),
252            autoCloseStreams,
253            strict,
254            trimStrings,
255            unbuffered,
256            debugOutputLines,
257            listener,
258            consumes
259         );
260      }
261
262      //-----------------------------------------------------------------------------------------------------------------
263      // Properties
264      //-----------------------------------------------------------------------------------------------------------------
265
266      /**
267       * Specifies the media type that this parser consumes.
268       *
269       * @param value The value for this setting.
270       * @return This object.
271       */
272      @FluentSetter
273      public Builder consumes(String value) {
274         this.consumes = value;
275         return this;
276      }
277
278      /**
279       * Returns the current value for the 'consumes' property.
280       *
281       * @return The current value for the 'consumes' property.
282       */
283      public String getConsumes() {
284         return consumes;
285      }
286
287      /**
288       * Auto-close streams.
289       *
290       * <p>
291       * When enabled, <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed
292       * after parsing is complete.
293       *
294       * <h5 class='section'>Example:</h5>
295       * <p class='bjava'>
296       *    <jc>// Create a parser using strict mode.</jc>
297       *    ReaderParser <jv>parser</jv> = JsonParser
298       *       .<jsm>create</jsm>()
299       *       .autoCloseStreams()
300       *       .build();
301       *
302       *    Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/myfile.json"</js>);
303       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<jv>myReader</jv>, MyBean.<jk>class</jk>);
304       *
305       *    <jsm>assertTrue</jsm>(<jv>myReader</jv>.isClosed());
306       * </p>
307       *
308       * @return This object.
309       */
310      @FluentSetter
311      public Builder autoCloseStreams() {
312         return autoCloseStreams(true);
313      }
314
315      /**
316       * Same as {@link #autoCloseStreams()} but allows you to explicitly specify the value.
317       *
318       * @param value The value for this setting.
319       * @return This object.
320       */
321      @FluentSetter
322      public Builder autoCloseStreams(boolean value) {
323         autoCloseStreams = value;
324         return this;
325      }
326
327      /**
328       * Debug output lines.
329       *
330       * <p>
331       * When parse errors occur, this specifies the number of lines of input before and after the
332       * error location to be printed as part of the exception message.
333       *
334       * <h5 class='section'>Example:</h5>
335       * <p class='bjava'>
336       *    <jc>// Create a parser whose exceptions print out 100 lines before and after the parse error location.</jc>
337       *    ReaderParser <jv>parser</jv> = JsonParser
338       *       .<jsm>create</jsm>()
339       *       .debug()  <jc>// Enable debug mode to capture Reader contents as strings.</jc>
340       *       .debugOuputLines(100)
341       *       .build();
342       *
343       *    Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/mybadfile.json"</js>);
344       *    <jk>try</jk> {
345       *       <jv>parser</jv>.parse(<jv>myReader</jv>, Object.<jk>class</jk>);
346       *    } <jk>catch</jk> (ParseException <jv>e</jv>) {
347       *       System.<jsf>err</jsf>.println(<jv>e</jv>.getMessage());  <jc>// Will display 200 lines of the output.</jc>
348       *    }
349       * </p>
350       *
351       * @param value
352       *    The new value for this property.
353       *    <br>The default value is <c>5</c>.
354       * @return This object.
355       */
356      @FluentSetter
357      public Builder debugOutputLines(int value) {
358         debugOutputLines = value;
359         return this;
360      }
361
362      /**
363       * Parser listener.
364       *
365       * <p>
366       * Class used to listen for errors and warnings that occur during parsing.
367       *
368       * <h5 class='section'>Example:</h5>
369       * <p class='bjava'>
370       *    <jc>// Define our parser listener.</jc>
371       *    <jc>// Simply captures all unknown bean property events.</jc>
372       *    <jk>public class</jk> MyParserListener <jk>extends</jk> ParserListener {
373       *
374       *       <jc>// A simple property to store our events.</jc>
375       *       <jk>public</jk> List&lt;String&gt; <jf>events</jf> = <jk>new</jk> LinkedList&lt;&gt;();
376       *
377       *       <ja>@Override</ja>
378       *       <jk>public</jk> &lt;T&gt; <jk>void</jk> onUnknownBeanProperty(ParserSession <jv>session</jv>, String <jv>propertyName</jv>, Class&lt;T&gt; <jv>beanClass</jv>, T <jv>bean</jv>) {
379       *          Position <jv>position</jv> = <jv>parser</jv>.getPosition();
380       *          <jf>events</jf>.add(<jv>propertyName</jv> + <js>","</js> + <jv>position</jv>.getLine() + <js>","</js> + <jv>position</jv>.getColumn());
381       *       }
382       *    }
383       *
384       *    <jc>// Create a parser using our listener.</jc>
385       *    ReaderParser <jv>parser</jv> = JsonParser
386       *       .<jsm>create</jsm>()
387       *       .listener(MyParserListener.<jk>class</jk>)
388       *       .build();
389       *
390       *    <jc>// Create a session object.</jc>
391       *    <jc>// Needed because listeners are created per-session.</jc>
392       *    <jk>try</jk> (ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession()) {
393       *
394       *       <jc>// Parse some JSON object.</jc>
395       *       MyBean <jv>myBean</jv> = <jv>session</jv>.parse(<js>"{...}"</js>, MyBean.<jk>class</jk>);
396       *
397       *       <jc>// Get the listener.</jc>
398       *       MyParserListener <jv>listener</jv> = <jv>session</jv>.getListener(MyParserListener.<jk>class</jk>);
399       *
400       *       <jc>// Dump the results to the console.</jc>
401       *       Json5.<jsf>DEFAULT</jsf>.println(<jv>listener</jv>.<jf>events</jf>);
402       *    }
403       * </p>
404       *
405       * @param value The new value for this property.
406       * @return This object.
407       */
408      @FluentSetter
409      public Builder listener(Class<? extends ParserListener> value) {
410         listener = value;
411         return this;
412      }
413
414      /**
415       * Strict mode.
416       *
417       * <p>
418       * When enabled, strict mode for the parser is enabled.
419       *
420       * <p>
421       * Strict mode can mean different things for different parsers.
422       *
423       * <table class='styled'>
424       *    <tr><th>Parser class</th><th>Strict behavior</th></tr>
425       *    <tr>
426       *       <td>All reader-based parsers</td>
427       *       <td>
428       *          When enabled, throws {@link ParseException ParseExceptions} on malformed charset input.
429       *          Otherwise, malformed input is ignored.
430       *       </td>
431       *    </tr>
432       *    <tr>
433       *       <td>{@link JsonParser}</td>
434       *       <td>
435       *          When enabled, throws exceptions on the following invalid JSON syntax:
436       *          <ul>
437       *             <li>Unquoted attributes.
438       *             <li>Missing attribute values.
439       *             <li>Concatenated strings.
440       *             <li>Javascript comments.
441       *             <li>Numbers and booleans when Strings are expected.
442       *             <li>Numbers valid in Java but not JSON (e.g. octal notation, etc...)
443       *          </ul>
444       *       </td>
445       *    </tr>
446       * </table>
447       *
448       * <h5 class='section'>Example:</h5>
449       * <p class='bjava'>
450       *    <jc>// Create a parser using strict mode.</jc>
451       *    ReaderParser <jv>parser</jv> = JsonParser
452       *       .<jsm>create</jsm>()
453       *       .strict()
454       *       .build();
455       *
456       *    <jc>// Use it.</jc>
457       *    <jk>try</jk> {
458       *       String <jv>json</jv> = <js>"{unquotedAttr:'value'}"</js>;
459       *       <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
460       *    } <jk>catch</jk> (ParseException <jv>e</jv>) {
461       *       <jsm>assertTrue</jsm>(<jv>e</jv>.getMessage().contains(<js>"Unquoted attribute detected."</js>);
462       *    }
463       * </p>
464       *
465       * @return This object.
466       */
467      @FluentSetter
468      public Builder strict() {
469         return strict(true);
470      }
471
472      /**
473       * Same as {@link #strict()} but allows you to explicitly specify the value.
474       *
475       * @param value The value for this setting.
476       * @return This object.
477       */
478      @FluentSetter
479      public Builder strict(boolean value) {
480         strict = value;
481         return this;
482      }
483
484      /**
485       * Trim parsed strings.
486       *
487       * <p>
488       * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to
489       * the POJO.
490       *
491       * <h5 class='section'>Example:</h5>
492       * <p class='bjava'>
493       *    <jc>// Create a parser with trim-strings enabled.</jc>
494       *    ReaderParser <jv>parser</jv> = JsonParser
495       *       .<jsm>create</jsm>()
496       *       .trimStrings()
497       *       .build();
498       *
499       *    <jc>// Use it.</jc>
500       *    String <jv>json</jv> = <js>"{' foo ':' bar '}"</js>;
501       *    Map&lt;String,String&gt; <jv>myMap</jv> = <jv>parser</jv>.parse(<jv>json</jv>, HashMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
502       *
503       *    <jc>// Make sure strings are parsed.</jc>
504       *    <jsm>assertEquals</jsm>(<js>"bar"</js>, <jv>myMap</jv>.get(<js>"foo"</js>));
505       * </p>
506       *
507       * @return This object.
508       */
509      @FluentSetter
510      public Builder trimStrings() {
511         return trimStrings(true);
512      }
513
514      /**
515       * Same as {@link #trimStrings()} but allows you to explicitly specify the value.
516       *
517       * @param value The value for this setting.
518       * @return This object.
519       */
520      @FluentSetter
521      public Builder trimStrings(boolean value) {
522         trimStrings = value;
523         return this;
524      }
525
526      /**
527       * Unbuffered.
528       *
529       * <p>
530       * When enabled, don't use internal buffering during parsing.
531       *
532       * <p>
533       * This is useful in cases when you want to parse the same input stream or reader multiple times
534       * because it may contain multiple independent POJOs to parse.
535       * <br>Buffering would cause the parser to read past the current POJO in the stream.
536       *
537       * <h5 class='section'>Example:</h5>
538       * <p class='bjava'>
539       *    <jc>// Create a parser using strict mode.</jc>
540       *    ReaderParser <jv>parser</jv> = JsonParser.
541       *       .<jsm>create</jsm>()
542       *       .unbuffered(<jk>true</jk>)
543       *       .build();
544       *
545       *    <jc>// If you're calling parse on the same input multiple times, use a session instead of the parser directly.</jc>
546       *    <jc>// It's more efficient because we don't need to recalc the session settings again. </jc>
547       *    ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession();
548       *
549       *    <jc>// Read input with multiple POJOs</jc>
550       *    Reader <jv>json</jv> = <jk>new</jk> StringReader(<js>"{foo:'bar'}{foo:'baz'}"</js>);
551       *    MyBean <jv>myBean1</jv> = <jv>session</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
552       *    MyBean <jv>myBean2</jv> = <jv>session</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
553       * </p>
554       *
555       * <h5 class='section'>Notes:</h5><ul>
556       *    <li class='note'>
557       *       This only allows for multi-input streams for the following parsers:
558       *       <ul>
559       *          <li class='jc'>{@link JsonParser}
560       *          <li class='jc'>{@link UonParser}
561       *       </ul>
562       *       It has no effect on the following parsers:
563       *       <ul>
564       *          <li class='jc'>{@link MsgPackParser} - It already doesn't use buffering.
565       *          <li class='jc'>{@link XmlParser}, {@link HtmlParser} - These use StAX which doesn't allow for more than one root element anyway.
566       *          <li>RDF parsers - These read everything into an internal model before any parsing begins.
567       *       </ul>
568       * </ul>
569       *
570       * @return This object.
571       */
572      @FluentSetter
573      public Builder unbuffered() {
574         return unbuffered(true);
575      }
576
577      /**
578       * Same as {@link #unbuffered()} but allows you to explicitly specify the value.
579       *
580       * @param value The value for this setting.
581       * @return This object.
582       */
583      @FluentSetter
584      public Builder unbuffered(boolean value) {
585         unbuffered = value;
586         return this;
587      }
588
589      // <FluentSetters>
590
591      @Override /* GENERATED - org.apache.juneau.Context.Builder */
592      public Builder annotations(Annotation...values) {
593         super.annotations(values);
594         return this;
595      }
596
597      @Override /* GENERATED - org.apache.juneau.Context.Builder */
598      public Builder apply(AnnotationWorkList work) {
599         super.apply(work);
600         return this;
601      }
602
603      @Override /* GENERATED - org.apache.juneau.Context.Builder */
604      public Builder applyAnnotations(java.lang.Class<?>...fromClasses) {
605         super.applyAnnotations(fromClasses);
606         return this;
607      }
608
609      @Override /* GENERATED - org.apache.juneau.Context.Builder */
610      public Builder applyAnnotations(Method...fromMethods) {
611         super.applyAnnotations(fromMethods);
612         return this;
613      }
614
615      @Override /* GENERATED - org.apache.juneau.Context.Builder */
616      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
617         super.cache(value);
618         return this;
619      }
620
621      @Override /* GENERATED - org.apache.juneau.Context.Builder */
622      public Builder debug() {
623         super.debug();
624         return this;
625      }
626
627      @Override /* GENERATED - org.apache.juneau.Context.Builder */
628      public Builder debug(boolean value) {
629         super.debug(value);
630         return this;
631      }
632
633      @Override /* GENERATED - org.apache.juneau.Context.Builder */
634      public Builder impl(Context value) {
635         super.impl(value);
636         return this;
637      }
638
639      @Override /* GENERATED - org.apache.juneau.Context.Builder */
640      public Builder type(Class<? extends org.apache.juneau.Context> value) {
641         super.type(value);
642         return this;
643      }
644
645      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
646      public Builder beanClassVisibility(Visibility value) {
647         super.beanClassVisibility(value);
648         return this;
649      }
650
651      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
652      public Builder beanConstructorVisibility(Visibility value) {
653         super.beanConstructorVisibility(value);
654         return this;
655      }
656
657      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
658      public Builder beanContext(BeanContext value) {
659         super.beanContext(value);
660         return this;
661      }
662
663      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
664      public Builder beanContext(BeanContext.Builder value) {
665         super.beanContext(value);
666         return this;
667      }
668
669      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
670      public Builder beanDictionary(java.lang.Class<?>...values) {
671         super.beanDictionary(values);
672         return this;
673      }
674
675      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
676      public Builder beanFieldVisibility(Visibility value) {
677         super.beanFieldVisibility(value);
678         return this;
679      }
680
681      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
682      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
683         super.beanInterceptor(on, value);
684         return this;
685      }
686
687      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
688      public Builder beanMapPutReturnsOldValue() {
689         super.beanMapPutReturnsOldValue();
690         return this;
691      }
692
693      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
694      public Builder beanMethodVisibility(Visibility value) {
695         super.beanMethodVisibility(value);
696         return this;
697      }
698
699      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
700      public Builder beanProperties(Map<String,Object> values) {
701         super.beanProperties(values);
702         return this;
703      }
704
705      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
706      public Builder beanProperties(Class<?> beanClass, String properties) {
707         super.beanProperties(beanClass, properties);
708         return this;
709      }
710
711      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
712      public Builder beanProperties(String beanClassName, String properties) {
713         super.beanProperties(beanClassName, properties);
714         return this;
715      }
716
717      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
718      public Builder beanPropertiesExcludes(Map<String,Object> values) {
719         super.beanPropertiesExcludes(values);
720         return this;
721      }
722
723      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
724      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
725         super.beanPropertiesExcludes(beanClass, properties);
726         return this;
727      }
728
729      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
730      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
731         super.beanPropertiesExcludes(beanClassName, properties);
732         return this;
733      }
734
735      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
736      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
737         super.beanPropertiesReadOnly(values);
738         return this;
739      }
740
741      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
742      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
743         super.beanPropertiesReadOnly(beanClass, properties);
744         return this;
745      }
746
747      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
748      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
749         super.beanPropertiesReadOnly(beanClassName, properties);
750         return this;
751      }
752
753      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
754      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
755         super.beanPropertiesWriteOnly(values);
756         return this;
757      }
758
759      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
760      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
761         super.beanPropertiesWriteOnly(beanClass, properties);
762         return this;
763      }
764
765      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
766      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
767         super.beanPropertiesWriteOnly(beanClassName, properties);
768         return this;
769      }
770
771      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
772      public Builder beansRequireDefaultConstructor() {
773         super.beansRequireDefaultConstructor();
774         return this;
775      }
776
777      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
778      public Builder beansRequireSerializable() {
779         super.beansRequireSerializable();
780         return this;
781      }
782
783      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
784      public Builder beansRequireSettersForGetters() {
785         super.beansRequireSettersForGetters();
786         return this;
787      }
788
789      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
790      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
791         super.dictionaryOn(on, values);
792         return this;
793      }
794
795      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
796      public Builder disableBeansRequireSomeProperties() {
797         super.disableBeansRequireSomeProperties();
798         return this;
799      }
800
801      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
802      public Builder disableIgnoreMissingSetters() {
803         super.disableIgnoreMissingSetters();
804         return this;
805      }
806
807      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
808      public Builder disableIgnoreTransientFields() {
809         super.disableIgnoreTransientFields();
810         return this;
811      }
812
813      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
814      public Builder disableIgnoreUnknownNullBeanProperties() {
815         super.disableIgnoreUnknownNullBeanProperties();
816         return this;
817      }
818
819      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
820      public Builder disableInterfaceProxies() {
821         super.disableInterfaceProxies();
822         return this;
823      }
824
825      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
826      public <T> Builder example(Class<T> pojoClass, T o) {
827         super.example(pojoClass, o);
828         return this;
829      }
830
831      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
832      public <T> Builder example(Class<T> pojoClass, String json) {
833         super.example(pojoClass, json);
834         return this;
835      }
836
837      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
838      public Builder findFluentSetters() {
839         super.findFluentSetters();
840         return this;
841      }
842
843      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
844      public Builder findFluentSetters(Class<?> on) {
845         super.findFluentSetters(on);
846         return this;
847      }
848
849      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
850      public Builder ignoreInvocationExceptionsOnGetters() {
851         super.ignoreInvocationExceptionsOnGetters();
852         return this;
853      }
854
855      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
856      public Builder ignoreInvocationExceptionsOnSetters() {
857         super.ignoreInvocationExceptionsOnSetters();
858         return this;
859      }
860
861      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
862      public Builder ignoreUnknownBeanProperties() {
863         super.ignoreUnknownBeanProperties();
864         return this;
865      }
866
867      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
868      public Builder ignoreUnknownEnumValues() {
869         super.ignoreUnknownEnumValues();
870         return this;
871      }
872
873      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
874      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
875         super.implClass(interfaceClass, implClass);
876         return this;
877      }
878
879      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
880      public Builder implClasses(Map<Class<?>,Class<?>> values) {
881         super.implClasses(values);
882         return this;
883      }
884
885      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
886      public Builder interfaceClass(Class<?> on, Class<?> value) {
887         super.interfaceClass(on, value);
888         return this;
889      }
890
891      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
892      public Builder interfaces(java.lang.Class<?>...value) {
893         super.interfaces(value);
894         return this;
895      }
896
897      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
898      public Builder locale(Locale value) {
899         super.locale(value);
900         return this;
901      }
902
903      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
904      public Builder mediaType(MediaType value) {
905         super.mediaType(value);
906         return this;
907      }
908
909      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
910      public Builder notBeanClasses(java.lang.Class<?>...values) {
911         super.notBeanClasses(values);
912         return this;
913      }
914
915      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
916      public Builder notBeanPackages(String...values) {
917         super.notBeanPackages(values);
918         return this;
919      }
920
921      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
922      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
923         super.propertyNamer(value);
924         return this;
925      }
926
927      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
928      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
929         super.propertyNamer(on, value);
930         return this;
931      }
932
933      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
934      public Builder sortProperties() {
935         super.sortProperties();
936         return this;
937      }
938
939      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
940      public Builder sortProperties(java.lang.Class<?>...on) {
941         super.sortProperties(on);
942         return this;
943      }
944
945      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
946      public Builder stopClass(Class<?> on, Class<?> value) {
947         super.stopClass(on, value);
948         return this;
949      }
950
951      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
952      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
953         super.swap(normalClass, swappedClass, swapFunction);
954         return this;
955      }
956
957      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
958      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
959         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
960         return this;
961      }
962
963      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
964      public Builder swaps(java.lang.Class<?>...values) {
965         super.swaps(values);
966         return this;
967      }
968
969      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
970      public Builder timeZone(TimeZone value) {
971         super.timeZone(value);
972         return this;
973      }
974
975      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
976      public Builder typeName(Class<?> on, String value) {
977         super.typeName(on, value);
978         return this;
979      }
980
981      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
982      public Builder typePropertyName(String value) {
983         super.typePropertyName(value);
984         return this;
985      }
986
987      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
988      public Builder typePropertyName(Class<?> on, String value) {
989         super.typePropertyName(on, value);
990         return this;
991      }
992
993      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
994      public Builder useEnumNames() {
995         super.useEnumNames();
996         return this;
997      }
998
999      @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
1000      public Builder useJavaBeanIntrospector() {
1001         super.useJavaBeanIntrospector();
1002         return this;
1003      }
1004
1005      // </FluentSetters>
1006   }
1007   //-------------------------------------------------------------------------------------------------------------------
1008   // Instance
1009   //-------------------------------------------------------------------------------------------------------------------
1010
1011   final boolean trimStrings, strict, autoCloseStreams, unbuffered;
1012   final int debugOutputLines;
1013   final String consumes;
1014   final Class<? extends ParserListener> listener;
1015
1016   /** General parser properties currently set on this parser. */
1017   private final MediaType[] consumesArray;
1018
1019   /**
1020    * Constructor.
1021    *
1022    * @param builder The builder this object.
1023    */
1024   protected Parser(Builder builder) {
1025      super(builder);
1026
1027      consumes = builder.consumes;
1028      trimStrings = builder.trimStrings;
1029      strict = builder.strict;
1030      autoCloseStreams = builder.autoCloseStreams;
1031      debugOutputLines = builder.debugOutputLines;
1032      unbuffered = builder.unbuffered;
1033      listener = builder.listener;
1034
1035      String[] _consumes = split(consumes != null ? consumes : "");
1036      this.consumesArray = new MediaType[_consumes.length];
1037      for (int i = 0; i < _consumes.length; i++) {
1038         this.consumesArray[i] = MediaType.of(_consumes[i]);
1039      }
1040   }
1041
1042   @Override /* Context */
1043   public Builder copy() {
1044      return new Builder(this);
1045   }
1046
1047   //-----------------------------------------------------------------------------------------------------------------
1048   // Abstract methods
1049   //-----------------------------------------------------------------------------------------------------------------
1050
1051   /**
1052    * Returns <jk>true</jk> if this parser subclasses from {@link ReaderParser}.
1053    *
1054    * @return <jk>true</jk> if this parser subclasses from {@link ReaderParser}.
1055    */
1056   public boolean isReaderParser() {
1057      return true;
1058   }
1059
1060   //-----------------------------------------------------------------------------------------------------------------
1061   // Other methods
1062   //-----------------------------------------------------------------------------------------------------------------
1063
1064   /**
1065    * Parses input into the specified object type.
1066    *
1067    * <p>
1068    * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
1069    *
1070    * <h5 class='section'>Examples:</h5>
1071    * <p class='bjava'>
1072    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
1073    *
1074    *    <jc>// Parse into a linked-list of strings.</jc>
1075    *    List <jv>list1</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
1076    *
1077    *    <jc>// Parse into a linked-list of beans.</jc>
1078    *    List <jv>list2</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
1079    *
1080    *    <jc>// Parse into a linked-list of linked-lists of strings.</jc>
1081    *    List <jv>list3</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
1082    *
1083    *    <jc>// Parse into a map of string keys/values.</jc>
1084    *    Map <jv>map1</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
1085    *
1086    *    <jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
1087    *    Map <jv>map2</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
1088    * </p>
1089    *
1090    * <p>
1091    * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
1092    *
1093    * <p>
1094    * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types.
1095    *
1096    * <p>
1097    * The array can be arbitrarily long to indicate arbitrarily complex data structures.
1098    *
1099    * <h5 class='section'>Notes:</h5><ul>
1100    *    <li class='note'>
1101    *       Use the {@link #parse(Object, Class)} method instead if you don't need a parameterized map/collection.
1102    * </ul>
1103    *
1104    * @param <T> The class type of the object to create.
1105    * @param input
1106    *    The input.
1107    *    <br>Character-based parsers can handle the following input class types:
1108    *    <ul>
1109    *       <li><jk>null</jk>
1110    *       <li>{@link Reader}
1111    *       <li>{@link CharSequence}
1112    *       <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
1113    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
1114    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
1115    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
1116    *       <li>{@link File} containing system encoded text (or charset defined by
1117    *          {@link ReaderParser.Builder#fileCharset(Charset)} property value).
1118    *    </ul>
1119    *    <br>Stream-based parsers can handle the following input class types:
1120    *    <ul>
1121    *       <li><jk>null</jk>
1122    *       <li>{@link InputStream}
1123    *       <li><code><jk>byte</jk>[]</code>
1124    *       <li>{@link File}
1125    *       <li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting.
1126    *    </ul>
1127    * @param type
1128    *    The object type to create.
1129    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
1130    * @param args
1131    *    The type arguments of the class if it's a collection or map.
1132    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
1133    *    <br>Ignored if the main type is not a map or collection.
1134    * @return The parsed object.
1135    * @throws ParseException Malformed input encountered.
1136    * @throws IOException Thrown by underlying stream.
1137    * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
1138    */
1139   public final <T> T parse(Object input, Type type, Type...args) throws ParseException, IOException {
1140      return getSession().parse(input, type, args);
1141   }
1142
1143   /**
1144    * Same as {@link #parse(Object, Type, Type...)} but since it's a {@link String} input doesn't throw an {@link IOException}.
1145    *
1146    * @param <T> The class type of the object being created.
1147    * @param input
1148    *    The input.
1149    *    See {@link #parse(Object, Type, Type...)} for details.
1150    * @param type
1151    *    The object type to create.
1152    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
1153    * @param args
1154    *    The type arguments of the class if it's a collection or map.
1155    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
1156    *    <br>Ignored if the main type is not a map or collection.
1157    * @return The parsed object.
1158    * @throws ParseException Malformed input encountered.
1159    */
1160   public final <T> T parse(String input, Type type, Type...args) throws ParseException {
1161      return getSession().parse(input, type, args);
1162   }
1163
1164   /**
1165    * Same as {@link #parse(Object, Type, Type...)} except optimized for a non-parameterized class.
1166    *
1167    * <p>
1168    * This is the preferred parse method for simple types since you don't need to cast the results.
1169    *
1170    * <h5 class='section'>Examples:</h5>
1171    * <p class='bjava'>
1172    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
1173    *
1174    *    <jc>// Parse into a string.</jc>
1175    *    String <jv>string</jv> = <jv>parser</jv>.parse(<jv>json</jv>, String.<jk>class</jk>);
1176    *
1177    *    <jc>// Parse into a bean.</jc>
1178    *    MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
1179    *
1180    *    <jc>// Parse into a bean array.</jc>
1181    *    MyBean[] <jv>beanArray</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean[].<jk>class</jk>);
1182    *
1183    *    <jc>// Parse into a linked-list of objects.</jc>
1184    *    List <jv>list</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>);
1185    *
1186    *    <jc>// Parse into a map of object keys/values.</jc>
1187    *    Map <jv>map</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>);
1188    * </p>
1189    *
1190    * @param <T> The class type of the object being created.
1191    * @param input
1192    *    The input.
1193    *    See {@link #parse(Object, Type, Type...)} for details.
1194    * @param type The object type to create.
1195    * @return The parsed object.
1196    * @throws ParseException Malformed input encountered.
1197    * @throws IOException Thrown by the underlying stream.
1198    */
1199   public final <T> T parse(Object input, Class<T> type) throws ParseException, IOException {
1200      return getSession().parse(input, type);
1201   }
1202
1203   /**
1204    * Same as {@link #parse(Object, Class)} but since it's a {@link String} input doesn't throw an {@link IOException}.
1205    *
1206    * @param <T> The class type of the object being created.
1207    * @param input
1208    *    The input.
1209    *    See {@link #parse(Object, Type, Type...)} for details.
1210    * @param type The object type to create.
1211    * @return The parsed object.
1212    * @throws ParseException Malformed input encountered.
1213    */
1214   public final <T> T parse(String input, Class<T> type) throws ParseException {
1215      return getSession().parse(input, type);
1216   }
1217
1218   /**
1219    * Same as {@link #parse(Object, Type, Type...)} except the type has already been converted into a {@link ClassMeta}
1220    * object.
1221    *
1222    * <p>
1223    * This is mostly an internal method used by the framework.
1224    *
1225    * @param <T> The class type of the object being created.
1226    * @param input
1227    *    The input.
1228    *    See {@link #parse(Object, Type, Type...)} for details.
1229    * @param type The object type to create.
1230    * @return The parsed object.
1231    * @throws ParseException Malformed input encountered.
1232    * @throws IOException Thrown by the underlying stream.
1233    */
1234   public final <T> T parse(Object input, ClassMeta<T> type) throws ParseException, IOException {
1235      return getSession().parse(input, type);
1236   }
1237
1238   /**
1239    * Same as {@link #parse(Object, ClassMeta)} but since it's a {@link String} input doesn't throw an {@link IOException}.
1240    *
1241    * @param <T> The class type of the object being created.
1242    * @param input
1243    *    The input.
1244    *    See {@link #parse(Object, Type, Type...)} for details.
1245    * @param type The object type to create.
1246    * @return The parsed object.
1247    * @throws ParseException Malformed input encountered.
1248    */
1249   public final <T> T parse(String input, ClassMeta<T> type) throws ParseException {
1250      return getSession().parse(input, type);
1251   }
1252
1253   @Override /* Context */
1254   public ParserSession.Builder createSession() {
1255      return ParserSession.create(this);
1256   }
1257
1258   @Override /* Context */
1259   public ParserSession getSession() {
1260      return createSession().build();
1261   }
1262
1263   /**
1264    * Workhorse method.
1265    *
1266    * <p>
1267    * Subclasses are expected to either implement this method or {@link ParserSession#doParse(ParserPipe, ClassMeta)}.
1268    *
1269    * @param session The current session.
1270    * @param pipe Where to get the input from.
1271    * @param type
1272    *    The class type of the object to create.
1273    *    If <jk>null</jk> or <code>Object.<jk>class</jk></code>, object type is based on what's being parsed.
1274    *    For example, when parsing JSON text, it may return a <c>String</c>, <c>Number</c>,
1275    *    <c>JsonMap</c>, etc...
1276    * @param <T> The class type of the object to create.
1277    * @return The parsed object.
1278    * @throws IOException Thrown by underlying stream.
1279    * @throws ParseException Malformed input encountered.
1280    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
1281    */
1282   public <T> T doParse(ParserSession session, ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException {
1283      throw new UnsupportedOperationException();
1284   }
1285
1286   //-----------------------------------------------------------------------------------------------------------------
1287   // Optional methods
1288   //-----------------------------------------------------------------------------------------------------------------
1289
1290   /**
1291    * Parses the contents of the specified reader and loads the results into the specified map.
1292    *
1293    * <p>
1294    * Reader must contain something that serializes to a map (such as text containing a JSON object).
1295    *
1296    * <p>
1297    * Used in the following locations:
1298    * <ul class='spaced-list'>
1299    *    <li>
1300    *       The various character-based constructors in {@link JsonMap} (e.g.
1301    *       {@link JsonMap#JsonMap(CharSequence,Parser)}).
1302    * </ul>
1303    *
1304    * @param <K> The key class type.
1305    * @param <V> The value class type.
1306    * @param input The input.  See {@link #parse(Object, ClassMeta)} for supported input types.
1307    * @param m The map being loaded.
1308    * @param keyType The class type of the keys, or <jk>null</jk> to default to <code>String.<jk>class</jk></code>.
1309    * @param valueType The class type of the values, or <jk>null</jk> to default to whatever is being parsed.
1310    * @return The same map that was passed in to allow this method to be chained.
1311    * @throws ParseException Malformed input encountered.
1312    * @throws UnsupportedOperationException If not implemented.
1313    */
1314   public final <K,V> Map<K,V> parseIntoMap(Object input, Map<K,V> m, Type keyType, Type valueType) throws ParseException {
1315      return getSession().parseIntoMap(input, m, keyType, valueType);
1316   }
1317
1318   /**
1319    * Parses the contents of the specified reader and loads the results into the specified collection.
1320    *
1321    * <p>
1322    * Used in the following locations:
1323    * <ul class='spaced-list'>
1324    *    <li>
1325    *       The various character-based constructors in {@link JsonList} (e.g.
1326    *       {@link JsonList#JsonList(CharSequence,Parser)}.
1327    * </ul>
1328    *
1329    * @param <E> The element class type.
1330    * @param input The input.  See {@link #parse(Object, ClassMeta)} for supported input types.
1331    * @param c The collection being loaded.
1332    * @param elementType The class type of the elements, or <jk>null</jk> to default to whatever is being parsed.
1333    * @return The same collection that was passed in to allow this method to be chained.
1334    * @throws ParseException Malformed input encountered.
1335    * @throws UnsupportedOperationException If not implemented.
1336    */
1337   public final <E> Collection<E> parseIntoCollection(Object input, Collection<E> c, Type elementType) throws ParseException {
1338      return getSession().parseIntoCollection(input, c, elementType);
1339   }
1340
1341   /**
1342    * Parses the specified array input with each entry in the object defined by the {@code argTypes}
1343    * argument.
1344    *
1345    * <p>
1346    * Used for converting arrays (e.g. <js>"[arg1,arg2,...]"</js>) into an {@code Object[]} that can be passed
1347    * to the {@code Method.invoke(target, args)} method.
1348    *
1349    * <p>
1350    * Used in the following locations:
1351    * <ul class='spaced-list'>
1352    *    <li>
1353    *       Used to parse argument strings in the {@link ObjectIntrospector#invokeMethod(Method, Reader)} method.
1354    * </ul>
1355    *
1356    * @param input The input.  Subclasses can support different input types.
1357    * @param argTypes Specifies the type of objects to create for each entry in the array.
1358    * @return An array of parsed objects.
1359    * @throws ParseException Malformed input encountered.
1360    */
1361   public final Object[] parseArgs(Object input, Type[] argTypes) throws ParseException {
1362      if (argTypes == null || argTypes.length == 0)
1363         return new Object[0];
1364      return getSession().parseArgs(input, argTypes);
1365   }
1366
1367
1368   //-----------------------------------------------------------------------------------------------------------------
1369   // Other methods
1370   //-----------------------------------------------------------------------------------------------------------------
1371
1372   /**
1373    * Returns the media types handled based on the values passed to the <c>consumes</c> constructor parameter.
1374    *
1375    * @return The list of media types.  Never <jk>null</jk>.
1376    */
1377   public final List<MediaType> getMediaTypes() {
1378      return ulist(consumesArray);
1379   }
1380
1381   /**
1382    * Returns the first media type handled based on the values passed to the <c>consumes</c> constructor parameter.
1383    *
1384    * @return The media type.
1385    */
1386   public final MediaType getPrimaryMediaType() {
1387      return consumesArray == null || consumesArray.length == 0 ? null : consumesArray[0];
1388   }
1389
1390   /**
1391    * Returns <jk>true</jk> if this parser can handle the specified content type.
1392    *
1393    * @param contentType The content type to test.
1394    * @return <jk>true</jk> if this parser can handle the specified content type.
1395    */
1396   public boolean canHandle(String contentType) {
1397      if (contentType != null)
1398         for (MediaType mt : getMediaTypes())
1399            if (contentType.equals(mt.toString()))
1400               return true;
1401      return false;
1402   }
1403
1404   //-----------------------------------------------------------------------------------------------------------------
1405   // Properties
1406   //-----------------------------------------------------------------------------------------------------------------
1407
1408   /**
1409    * Auto-close streams.
1410    *
1411    * @see Parser.Builder#autoCloseStreams()
1412    * @return
1413    *    <jk>true</jk> if <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed
1414    *    after parsing is complete.
1415    */
1416   protected final boolean isAutoCloseStreams() {
1417      return autoCloseStreams;
1418   }
1419
1420   /**
1421    * Debug output lines.
1422    *
1423    * @see Parser.Builder#debugOutputLines(int)
1424    * @return
1425    *    The number of lines of input before and after the error location to be printed as part of the exception message.
1426    */
1427   protected final int getDebugOutputLines() {
1428      return debugOutputLines;
1429   }
1430
1431   /**
1432    * Parser listener.
1433    *
1434    * @see Parser.Builder#listener(Class)
1435    * @return
1436    *    Class used to listen for errors and warnings that occur during parsing.
1437    */
1438   protected final Class<? extends ParserListener> getListener() {
1439      return listener;
1440   }
1441
1442   /**
1443    * Strict mode.
1444    *
1445    * @see Parser.Builder#strict()
1446    * @return
1447    *    <jk>true</jk> if strict mode for the parser is enabled.
1448    */
1449   protected final boolean isStrict() {
1450      return strict;
1451   }
1452
1453   /**
1454    * Trim parsed strings.
1455    *
1456    * @see Parser.Builder#trimStrings()
1457    * @return
1458    *    <jk>true</jk> if string values will be trimmed of whitespace using {@link String#trim()} before being added to
1459    *    the POJO.
1460    */
1461   protected final boolean isTrimStrings() {
1462      return trimStrings;
1463   }
1464
1465   /**
1466    * Unbuffered.
1467    *
1468    * @see Parser.Builder#unbuffered()
1469    * @return
1470    *    <jk>true</jk> if parsers don't use internal buffering during parsing.
1471    */
1472   protected final boolean isUnbuffered() {
1473      return unbuffered;
1474   }
1475
1476   //-----------------------------------------------------------------------------------------------------------------
1477   // Other methods
1478   //-----------------------------------------------------------------------------------------------------------------
1479
1480   @Override /* Context */
1481   protected JsonMap properties() {
1482      return filteredMap()
1483         .append("autoCloseStreams", autoCloseStreams)
1484         .append("debugOutputLines", debugOutputLines)
1485         .append("listener", listener)
1486         .append("strict", strict)
1487         .append("trimStrings", trimStrings)
1488         .append("unbuffered", unbuffered);
1489   }
1490}