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.marshall.parser;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021import static org.apache.juneau.commons.utils.StringUtils.*;
022import static org.apache.juneau.commons.utils.SystemUtils.*;
023
024import java.io.*;
025import java.lang.reflect.*;
026import java.nio.charset.*;
027import java.util.*;
028
029import org.apache.juneau.commons.collections.*;
030import org.apache.juneau.commons.http.*;
031import org.apache.juneau.commons.reflect.*;
032import org.apache.juneau.marshall.*;
033import org.apache.juneau.marshall.collections.*;
034import org.apache.juneau.marshall.html.*;
035import org.apache.juneau.marshall.json.*;
036import org.apache.juneau.marshall.msgpack.*;
037import org.apache.juneau.marshall.objecttools.*;
038import org.apache.juneau.marshall.stream.*;
039import org.apache.juneau.marshall.swap.spi.*;
040import org.apache.juneau.marshall.uon.*;
041import org.apache.juneau.marshall.xml.*;
042
043/**
044 * Parent class for all Juneau parsers.
045 *
046 * <h5 class='topic'>Valid data conversions</h5>
047 * <p>
048 * Parsers can parse any parsable POJO types, as specified in the <a class="doclink" href="https://juneau.apache.org/docs/topics/PojoCategories">POJO Categories</a>.
049 *
050 * <p>
051 * Some examples of conversions are shown below...
052 * </p>
053 * <table class='styled'>
054 *    <tr>
055 *       <th>Data type</th>
056 *       <th>Class type</th>
057 *       <th>JSON example</th>
058 *       <th>XML example</th>
059 *       <th>Class examples</th>
060 *    </tr>
061 *    <tr>
062 *       <td>object</td>
063 *       <td>Maps, Java beans</td>
064 *       <td class='code'>{name:<js>'John Smith'</js>,age:21}</td>
065 *       <td class='code'><xt>&lt;object&gt;
066 *    &lt;name</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>John Smith<xt>&lt;/name&gt;
067 *    &lt;age</xt> <xa>type</xa>=<xs>'number'</xs><xt>&gt;</xt>21<xt>&lt;/age&gt;
068 * &lt;/object&gt;</xt></td>
069 *       <td class='code'>HashMap, TreeMap&lt;String,Integer&gt;</td>
070 *    </tr>
071 *    <tr>
072 *       <td>array</td>
073 *       <td>Collections, Java arrays</td>
074 *       <td class='code'>[1,2,3]</td>
075 *       <td class='code'><xt>&lt;array&gt;
076 *    &lt;number&gt;</xt>1<xt>&lt;/number&gt;
077 *    &lt;number&gt;</xt>2<xt>&lt;/number&gt;
078 *    &lt;number&gt;</xt>3<xt>&lt;/number&gt;
079 * &lt;/array&gt;</xt></td>
080 *       <td class='code'>List&lt;Integer&gt;, <jk>int</jk>[], Float[], Set&lt;Person&gt;</td>
081 *    </tr>
082 *    <tr>
083 *       <td>number</td>
084 *       <td>Numbers</td>
085 *       <td class='code'>123</td>
086 *       <td class='code'><xt>&lt;number&gt;</xt>123<xt>&lt;/number&gt;</xt></td>
087 *       <td class='code'>Integer, Long, Float, <jk>int</jk></td>
088 *    </tr>
089 *    <tr>
090 *       <td>boolean</td>
091 *       <td>Booleans</td>
092 *       <td class='code'><jk>true</jk></td>
093 *       <td class='code'><xt>&lt;boolean&gt;</xt>true<xt>&lt;/boolean&gt;</xt></td>
094 *       <td class='code'>Boolean</td>
095 *    </tr>
096 *    <tr>
097 *       <td>string</td>
098 *       <td>CharSequences</td>
099 *       <td class='code'><js>'foobar'</js></td>
100 *       <td class='code'><xt>&lt;string&gt;</xt>foobar<xt>&lt;/string&gt;</xt></td>
101 *       <td class='code'>String, StringBuilder</td>
102 *    </tr>
103 * </table>
104 *
105 * <p>
106 * In addition, any class types with {@link ObjectSwap ObjectSwaps} associated with them on the registered
107 * bean context can also be passed in.
108 *
109 * <p>
110 * For example, if a {@link CalendarFormat}-driven swap is used to generalize {@code Calendar} objects to {@code String}
111 * objects.
112 * When registered with this parser, you can construct {@code Calendar} objects from {@code Strings} using the
113 * following syntax...
114 * <p class='bjava'>
115 *    Calendar <jv>calendar</jv> = <jv>parser</jv>.read(<js>"'Sun Mar 03 04:05:06 EST 2001'"</js>, GregorianCalendar.<jk>class</jk>);
116 * </p>
117 *
118 * <p>
119 * If <code>Object.<jk>class</jk></code> is specified as the target type, then the parser automatically determines the
120 * data types and generates the following object types...
121 * <table class='styled'>
122 *    <tr><th>JSON type</th><th>Class type</th></tr>
123 *    <tr><td>object</td><td>{@link JsonMap}</td></tr>
124 *    <tr><td>array</td><td>{@link JsonList}</td></tr>
125 *    <tr><td>number</td><td>{@link Number}<br>(depending on length and format, could be {@link Integer},
126 *       {@link Double}, {@link Float}, etc...)</td></tr>
127 *    <tr><td>boolean</td><td>{@link Boolean}</td></tr>
128 *    <tr><td>string</td><td>{@link String}</td></tr>
129 * </table>
130 *
131 * <h5 class='section'>Notes:</h5><ul>
132 *    <li class='note'>This class is thread safe and reusable.
133 * </ul>
134 *
135 * <h5 class='section'>See Also:</h5><ul>
136 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
137
138 * </ul>
139 */
140@SuppressWarnings({
141   "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants
142   "rawtypes" // createParserBuilder() returns the raw Builder because the builder subtype is only known reflectively.
143})
144public class Parser extends MarshallingContextable {
145
146   /**
147    * Builder class.
148    */
149   @SuppressWarnings({
150      "java:S119" // 'SELF' (CRTP self-type) is intentional and clearer than a single-letter name.
151   })
152   public abstract static class Builder<SELF extends Builder<SELF>> extends MarshallingContextable.Builder<SELF> {
153
154      private boolean autoCloseStreams;
155      private boolean trimStrings;
156      private boolean unbuffered;
157      private Class<? extends ParserListener> listener;
158      private int debugOutputLines;
159      private String consumes;
160      private Nulls nulls;
161
162      /**
163       * Constructor, default settings.
164       */
165      protected Builder() {
166         autoCloseStreams = env("Parser.autoCloseStreams", false);
167         trimStrings = env("Parser.trimStrings", false);
168         unbuffered = env("Parser.unbuffered", false);
169         debugOutputLines = env("Parser.debugOutputLines", 5);
170         listener = null;
171         consumes = null;
172         nulls = Nulls.NOT_SET;
173      }
174
175      /**
176       * Copy constructor.
177       *
178       * @param copyFrom The builder to copy from.
179       *    <br>Cannot be <jk>null</jk>.
180       */
181      protected Builder(Builder<?> copyFrom) {
182         super(copyFrom);
183         autoCloseStreams = copyFrom.autoCloseStreams;
184         trimStrings = copyFrom.trimStrings;
185         unbuffered = copyFrom.unbuffered;
186         debugOutputLines = copyFrom.debugOutputLines;
187         listener = copyFrom.listener;
188         consumes = copyFrom.consumes;
189         nulls = copyFrom.nulls;
190      }
191
192      /**
193       * Copy constructor.
194       *
195       * @param copyFrom The bean to copy from.
196       *    <br>Cannot be <jk>null</jk>.
197       */
198      protected Builder(Parser copyFrom) {
199         super(copyFrom);
200         autoCloseStreams = copyFrom.autoCloseStreams;
201         trimStrings = copyFrom.trimStrings;
202         unbuffered = copyFrom.unbuffered;
203         debugOutputLines = copyFrom.debugOutputLines;
204         listener = copyFrom.listener;
205         consumes = copyFrom.consumes;
206         nulls = copyFrom.nulls;
207      }
208
209      /**
210       * Auto-close streams.
211       *
212       * <p>
213       * When enabled, <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed
214       * after parsing is complete.
215       *
216       * <h5 class='section'>Example:</h5>
217       * <p class='bjava'>
218       *    <jc>// Create a parser using strict mode.</jc>
219       *    ReaderParser <jv>parser</jv> = JsonParser
220       *       .<jsm>create</jsm>()
221       *       .autoCloseStreams()
222       *       .build();
223       *
224       *    Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/myfile.json"</js>);
225       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.read(<jv>myReader</jv>, MyBean.<jk>class</jk>);
226       *
227       *    <jsm>assertTrue</jsm>(<jv>myReader</jv>.isClosed());
228       * </p>
229       *
230       * @return This object.
231       */
232      public SELF autoCloseStreams() {
233         return autoCloseStreams(true);
234      }
235
236      /**
237       * Same as {@link #autoCloseStreams()} but allows you to explicitly specify the value.
238       *
239       * @param value The value for this setting.
240       * @return This object.
241       */
242      public SELF autoCloseStreams(boolean value) {
243         autoCloseStreams = value;
244         return self();
245      }
246
247      @Override /* Overridden from Context.Builder<?> */
248      public Parser build() {
249         return build(Parser.class);
250      }
251
252      /**
253       * Specifies the media type that this parser consumes.
254       *
255       * <p>
256       * <b>Token streams:</b> this setting is not honored by {@link TokenReadable#readTokens(Object) readTokens}
257       * &mdash; media-type metadata is informational, not behavioral.
258       *
259       * @param value The value for this setting.
260       *    <br>Can be <jk>null</jk> (treated as empty string, no media types will be specified).
261       * @return This object.
262       */
263      public SELF consumes(String value) {
264         consumes = value;
265         return self();
266      }
267
268      @Override /* Overridden from Context.Builder<?> */
269      public abstract SELF copy();
270
271      /**
272       * Debug output lines.
273       *
274       * <p>
275       * When parse errors occur, this specifies the number of lines of input before and after the
276       * error location to be printed as part of the exception message.
277       *
278       * <h5 class='section'>Example:</h5>
279       * <p class='bjava'>
280       *    <jc>// Create a parser whose exceptions print out 100 lines before and after the parse error location.</jc>
281       *    ReaderParser <jv>parser</jv> = JsonParser
282       *       .<jsm>create</jsm>()
283       *       .debug()  <jc>// Enable debug mode to capture Reader contents as strings.</jc>
284       *       .debugOuputLines(100)
285       *       .build();
286       *
287       *    Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/mybadfile.json"</js>);
288       *    <jk>try</jk> {
289       *       <jv>parser</jv>.read(<jv>myReader</jv>, Object.<jk>class</jk>);
290       *    } <jk>catch</jk> (ParseException <jv>e</jv>) {
291       *       System.<jsf>err</jsf>.println(<jv>e</jv>.getMessage());  <jc>// Will display 200 lines of the output.</jc>
292       *    }
293       * </p>
294       *
295       * <p>
296       * <b>Token streams:</b> this setting is not honored by {@link TokenReadable#readTokens(Object) readTokens}
297       * &mdash; it controls error-message formatting on the POJO databind path; the cursor uses its own
298       * exception text.
299       *
300       * @param value
301       *    The new value for this property.
302       *    <br>The default value is <c>5</c>.
303       * @return This object.
304       */
305      public SELF debugOutputLines(int value) {
306         debugOutputLines = value;
307         return self();
308      }
309
310      /**
311       * Returns the current value for the 'consumes' property.
312       *
313       * @return The current value for the 'consumes' property, or <jk>null</jk> if not specified.
314       */
315      public String getConsumes() { return consumes; }
316
317      @Override /* Overridden from Context.Builder<?> */
318      public HashKey hashKey() {
319         // @formatter:off
320         return HashKey.of(
321            super.hashKey(),
322            autoCloseStreams,
323            trimStrings,
324            unbuffered,
325            debugOutputLines,
326            listener,
327            consumes,
328            nulls
329         );
330         // @formatter:on
331      }
332
333      /**
334       * Parser listener.
335       *
336       * <p>
337       * Class used to listen for errors and warnings that occur during parsing.
338       *
339       * <h5 class='section'>Example:</h5>
340       * <p class='bjava'>
341       *    <jc>// Define our parser listener.</jc>
342       *    <jc>// Simply captures all unknown bean property events.</jc>
343       *    <jk>public class</jk> MyParserListener <jk>extends</jk> ParserListener {
344       *
345       *       <jc>// A simple property to store our events.</jc>
346       *       <jk>public</jk> List&lt;String&gt; <jf>events</jf> = <jk>new</jk> LinkedList&lt;&gt;();
347       *
348       *       <ja>@Override</ja>
349       *       <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>) {
350       *          Position <jv>position</jv> = <jv>parser</jv>.getPosition();
351       *          <jf>events</jf>.add(<jv>propertyName</jv> + <js>","</js> + <jv>position</jv>.getLine() + <js>","</js> + <jv>position</jv>.getColumn());
352       *       }
353       *    }
354       *
355       *    <jc>// Create a parser using our listener.</jc>
356       *    ReaderParser <jv>parser</jv> = JsonParser
357       *       .<jsm>create</jsm>()
358       *       .listener(MyParserListener.<jk>class</jk>)
359       *       .build();
360       *
361       *    <jc>// Create a session object.</jc>
362       *    <jc>// Needed because listeners are created per-session.</jc>
363       *    <jk>try</jk> (ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession()) {
364       *
365       *       <jc>// Parse some JSON object.</jc>
366       *       MyBean <jv>myBean</jv> = <jv>session</jv>.read(<js>"{...}"</js>, MyBean.<jk>class</jk>);
367       *
368       *       <jc>// Get the listener.</jc>
369       *       MyParserListener <jv>listener</jv> = <jv>session</jv>.getListener(MyParserListener.<jk>class</jk>);
370       *
371       *       <jc>// Dump the results to the console.</jc>
372       *       Json5.<jsf>DEFAULT</jsf>.println(<jv>listener</jv>.<jf>events</jf>);
373       *    }
374       * </p>
375       *
376       * <p>
377       * <b>Token streams:</b> this setting is not honored by {@link TokenReadable#readTokens(Object) readTokens}
378       * &mdash; listeners are POJO-level observers with no token-layer analog.
379       *
380       * @param value The new value for this property.
381       *    <br>Can be <jk>null</jk> (no listener will be used, listener methods will not be called).
382       * @return This object.
383       */
384      public SELF listener(Class<? extends ParserListener> value) {
385         listener = value;
386         return self();
387      }
388
389      /**
390       * Sets the default per-property null-coercion policy applied during parsing.
391       *
392       * <p>
393       * Juneau's analog of Jackson's
394       * <c>ObjectMapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(...))</c>.
395       * Applied as the fallback when no per-property
396       * {@link MarshalledProp#nulls() @MarshalledProp(nulls=…)} is configured.
397       *
398       * <h5 class='section'>Example:</h5>
399       * <p class='bjava'>
400       *    <jc>// Substitute the empty value for any property whose wire value is null.</jc>
401       *    ReaderParser <jv>parser</jv> = JsonParser
402       *       .<jsm>create</jsm>()
403       *       .nulls(Nulls.<jsf>EMPTY</jsf>)
404       *       .build();
405       * </p>
406       *
407       * @param value The new value for this property.
408       *    <br>{@code null} or {@link Nulls#NOT_SET} disables the default (each property falls back to
409       *    {@link Nulls#LEAVE}).
410       * @return This object.
411       * @since 10.0.0
412       */
413      public SELF nulls(Nulls value) {
414         nulls = value == null ? Nulls.NOT_SET : value;
415         return self();
416      }
417
418      /**
419       * Returns the current context-level {@link Nulls} default configured on this builder.
420       *
421       * @return The current value (never <jk>null</jk>; {@link Nulls#NOT_SET} when unconfigured).
422       * @since 10.0.0
423       */
424      public Nulls getNulls() { return nulls == null ? Nulls.NOT_SET : nulls; }
425
426      /**
427       * Trim parsed strings.
428       *
429       * <p>
430       * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to
431       * the POJO.
432       *
433       * <h5 class='section'>Example:</h5>
434       * <p class='bjava'>
435       *    <jc>// Create a parser with trim-strings enabled.</jc>
436       *    ReaderParser <jv>parser</jv> = JsonParser
437       *       .<jsm>create</jsm>()
438       *       .trimStrings()
439       *       .build();
440       *
441       *    <jc>// Use it.</jc>
442       *    String <jv>json</jv> = <js>"{' foo ':' bar '}"</js>;
443       *    Map&lt;String,String&gt; <jv>myMap</jv> = <jv>parser</jv>.read(<jv>json</jv>, HashMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
444       *
445       *    <jc>// Make sure strings are parsed.</jc>
446       *    <jsm>assertEquals</jsm>(<js>"bar"</js>, <jv>myMap</jv>.get(<js>"foo"</js>));
447       * </p>
448       *
449       * @return This object.
450       */
451      public SELF trimStrings() {
452         return trimStrings(true);
453      }
454
455      /**
456       * Same as {@link #trimStrings()} but allows you to explicitly specify the value.
457       *
458       * @param value The value for this setting.
459       * @return This object.
460       */
461      public SELF trimStrings(boolean value) {
462         trimStrings = value;
463         return self();
464      }
465
466      /**
467       * Unbuffered.
468       *
469       * <p>
470       * When enabled, don't use internal buffering during parsing.
471       *
472       * <p>
473       * This is useful in cases when you want to parse the same input stream or reader multiple times
474       * because it may contain multiple independent POJOs to parse.
475       * <br>Buffering would cause the parser to read past the current POJO in the stream.
476       *
477       * <h5 class='section'>Example:</h5>
478       * <p class='bjava'>
479       *    <jc>// Create a parser using strict mode.</jc>
480       *    ReaderParser <jv>parser</jv> = JsonParser.
481       *       .<jsm>create</jsm>()
482       *       .unbuffered(<jk>true</jk>)
483       *       .build();
484       *
485       *    <jc>// If you're calling parse on the same input multiple times, use a session instead of the parser directly.</jc>
486       *    <jc>// It's more efficient because we don't need to recalc the session settings again. </jc>
487       *    ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession();
488       *
489       *    <jc>// Read input with multiple POJOs</jc>
490       *    Reader <jv>json</jv> = <jk>new</jk> StringReader(<js>"{foo:'bar'}{foo:'baz'}"</js>);
491       *    MyBean <jv>myBean1</jv> = <jv>session</jv>.read(<jv>json</jv>, MyBean.<jk>class</jk>);
492       *    MyBean <jv>myBean2</jv> = <jv>session</jv>.read(<jv>json</jv>, MyBean.<jk>class</jk>);
493       * </p>
494       *
495       * <h5 class='section'>Notes:</h5><ul>
496       *    <li class='note'>
497       *       This only allows for multi-input streams for the following parsers:
498       *       <ul>
499       *          <li class='jc'>{@link JsonParser}
500       *          <li class='jc'>{@link UonParser}
501       *       </ul>
502       *       It has no effect on the following parsers:
503       *       <ul>
504       *          <li class='jc'>{@link MsgPackParser} - It already doesn't use buffering.
505       *          <li class='jc'>{@link XmlParser}, {@link HtmlParser} - These use StAX which doesn't allow for more than one root element anyway.
506       *          <li>RDF parsers - These read everything into an internal model before any parsing begins.
507       *       </ul>
508       * </ul>
509       *
510       * @return This object.
511       */
512      public SELF unbuffered() {
513         return unbuffered(true);
514      }
515
516      /**
517       * Same as {@link #unbuffered()} but allows you to explicitly specify the value.
518       *
519       * @param value The value for this setting.
520       * @return This object.
521       */
522      public SELF unbuffered(boolean value) {
523         unbuffered = value;
524         return self();
525      }
526
527
528   }
529
530   /**
531    * Concrete default builder leaf for the non-subclassed {@link Parser#create()} / {@link Parser#copy()} path.
532    */
533   public static final class DefaultBuilder extends Builder<DefaultBuilder> {
534
535      DefaultBuilder() {}
536
537      DefaultBuilder(Parser copyFrom) {
538         super(copyFrom);
539      }
540
541      DefaultBuilder(Builder<?> copyFrom) {
542         super(copyFrom);
543      }
544
545      @Override /* Overridden from Context.Builder<?> */
546      public DefaultBuilder copy() {
547         return new DefaultBuilder(this);
548      }
549   }
550
551   /**
552    * Represents no Parser.
553    */
554   public abstract static class Null extends Parser {
555      @SuppressWarnings({
556         "java:S1186" // Constructor required by Parser parent class, even though Null is abstract and never instantiated directly
557      })
558      private Null(Builder<?> builder) {
559         super(builder);
560      }
561   }
562
563   /**
564    * Creates a new builder for this object.
565    *
566    * @return A new builder.
567    */
568   @SuppressWarnings({
569      "java:S1452" // Self-typed builder: Builder<?> is the only non-raw, leaf-free return; chaining + build() unaffected.
570   })
571   public static Builder<?> create() {
572      return new DefaultBuilder();
573   }
574
575   /**
576    * Instantiates a builder of the specified parser class.
577    *
578    * <p>
579    * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public
580    * or protected constructor of the class.
581    *
582    * @param c The builder to create.
583    *    <br>Must not be <jk>null</jk>.
584    * @return A new builder.
585    */
586   public static Builder createParserBuilder(Class<? extends Parser> c) {
587      return (Builder)Context.createBuilder(c);
588   }
589
590   protected final boolean autoCloseStreams;
591   protected final boolean trimStrings;
592   protected final boolean unbuffered;
593   protected final int debugOutputLines;
594   protected final Class<? extends ParserListener> listener;
595   protected final String consumes;
596   protected final Nulls nulls;
597   private final List<MediaType> consumesArray;
598
599   /**
600    * Constructor.
601    *
602    * @param builder The builder for this object.
603    *    <br>Cannot be <jk>null</jk>.
604    */
605   protected Parser(Builder<?> builder) {
606      super(builder);
607
608      autoCloseStreams = builder.autoCloseStreams;
609      consumes = builder.consumes;
610      debugOutputLines = builder.debugOutputLines;
611      listener = builder.listener;
612      trimStrings = builder.trimStrings;
613      unbuffered = builder.unbuffered;
614      nulls = builder.nulls == null ? Nulls.NOT_SET : builder.nulls;
615
616   String[] consumesParts = splita(nn(consumes) ? consumes : "");
617   List<MediaType> consumesList = l();
618   for (var consume : consumesParts) {
619      consumesList.add(MediaType.of(consume));
620   }
621   this.consumesArray = u(consumesList);
622   }
623
624   /**
625    * Returns <jk>true</jk> if this parser can handle the specified content type.
626    *
627    * @param contentType The content type to test.
628    *    <br>Can be <jk>null</jk> (returns <jk>false</jk>).
629    * @return <jk>true</jk> if this parser can handle the specified content type.
630    */
631   public boolean canHandle(String contentType) {
632      if (nn(contentType))
633         for (var mt : getMediaTypes())
634            if (eq(contentType, mt.toString()))
635               return true;
636      return false;
637   }
638
639   @Override /* Overridden from Context */
640   public Builder<?> copy() {
641      return new DefaultBuilder(this);
642   }
643
644   @Override /* Overridden from Context */
645   public ParserSession.Builder<?> createSession() {
646      return ParserSession.create(this);
647   }
648
649   /**
650    * Workhorse method.
651    *
652    * <p>
653    * Subclasses are expected to either implement this method or {@link ParserSession#doRead(ParserPipe, ClassMeta)}.
654    *
655    * @param session The current session.
656    * @param pipe Where to get the input from.
657    * @param type
658    *    The class type of the object to create.
659    *    If <jk>null</jk> or <code>Object.<jk>class</jk></code>, object type is based on what's being parsed.
660    *    For example, when parsing JSON text, it may return a <c>String</c>, <c>Number</c>,
661    *    <c>JsonMap</c>, etc...
662    * @param <T> The class type of the object to create.
663    * @return The parsed object.
664    * @throws IOException Thrown by underlying stream.
665    * @throws ParseException Malformed input encountered.
666    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
667    */
668   public <T> T doRead(ParserSession session, ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException {
669      throw uoex();
670   }
671
672   /**
673    * Returns the media types handled based on the values passed to the <c>consumes</c> constructor parameter.
674    *
675    * @return The list of media types.  Never <jk>null</jk>.
676    */
677   public final List<MediaType> getMediaTypes() { return consumesArray; }
678
679   /**
680    * Returns the first media type handled based on the values passed to the <c>consumes</c> constructor parameter.
681    *
682    * @return The media type, or <jk>null</jk> if no media types are handled by this parser.
683    */
684   public final MediaType getPrimaryMediaType() { return first(consumesArray).orElse(null); }
685
686   @Override /* Overridden from Context */
687   public ParserSession getSession() { return createSession().build(); }
688
689   /**
690    * Returns <jk>true</jk> if this parser subclasses from {@link ReaderParser}.
691    *
692    * @return <jk>true</jk> if this parser subclasses from {@link ReaderParser}.
693    */
694   public boolean isReaderParser() { return true; }
695
696   /**
697    * Same as {@link #read(Object, Type, Type...)} except optimized for a non-parameterized class.
698    *
699    * <p>
700    * This is the preferred parse method for simple types since you don't need to cast the results.
701    *
702    * <h5 class='section'>Examples:</h5>
703    * <p class='bjava'>
704    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
705    *
706    *    <jc>// Parse into a string.</jc>
707    *    String <jv>string</jv> = <jv>parser</jv>.read(<jv>json</jv>, String.<jk>class</jk>);
708    *
709    *    <jc>// Parse into a bean.</jc>
710    *    MyBean <jv>bean</jv> = <jv>parser</jv>.read(<jv>json</jv>, MyBean.<jk>class</jk>);
711    *
712    *    <jc>// Parse into a bean array.</jc>
713    *    MyBean[] <jv>beanArray</jv> = <jv>parser</jv>.read(<jv>json</jv>, MyBean[].<jk>class</jk>);
714    *
715    *    <jc>// Parse into a linked-list of objects.</jc>
716    *    List <jv>list</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>);
717    *
718    *    <jc>// Parse into a map of object keys/values.</jc>
719    *    Map <jv>map</jv> = <jv>parser</jv>.read(<jv>json</jv>, TreeMap.<jk>class</jk>);
720    * </p>
721    *
722    * @param <T> The class type of the object being created.
723    * @param input
724    *    The input.
725    *    See {@link #read(Object, Type, Type...)} for details.
726    * @param type The object type to create.
727    * @return The parsed object.
728    * @throws ParseException Malformed input encountered.
729    * @throws IOException Thrown by the underlying stream.
730    */
731   public final <T> T read(Object input, Class<T> type) throws ParseException, IOException {
732      return getSession().read(input, type);
733   }
734
735   /**
736    * Same as {@link #read(Object, Type, Type...)} except the type has already been converted into a {@link ClassMeta}
737    * object.
738    *
739    * <p>
740    * This is mostly an internal method used by the framework.
741    *
742    * @param <T> The class type of the object being created.
743    * @param input
744    *    The input.
745    *    See {@link #read(Object, Type, Type...)} for details.
746    * @param type The object type to create.
747    * @return The parsed object.
748    * @throws ParseException Malformed input encountered.
749    * @throws IOException Thrown by the underlying stream.
750    */
751   public final <T> T read(Object input, ClassMeta<T> type) throws ParseException, IOException {
752      return getSession().read(input, type);
753   }
754
755   /**
756    * Parses input into the specified object type.
757    *
758    * <p>
759    * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
760    *
761    * <h5 class='section'>Examples:</h5>
762    * <p class='bjava'>
763    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
764    *
765    *    <jc>// Parse into a linked-list of strings.</jc>
766    *    List <jv>list1</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
767    *
768    *    <jc>// Parse into a linked-list of beans.</jc>
769    *    List <jv>list2</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
770    *
771    *    <jc>// Parse into a linked-list of linked-lists of strings.</jc>
772    *    List <jv>list3</jv> = <jv>parser</jv>.read(<jv>json</jv>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
773    *
774    *    <jc>// Parse into a map of string keys/values.</jc>
775    *    Map <jv>map1</jv> = <jv>parser</jv>.read(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
776    *
777    *    <jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
778    *    Map <jv>map2</jv> = <jv>parser</jv>.read(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
779    * </p>
780    *
781    * <p>
782    * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
783    *
784    * <p>
785    * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types.
786    *
787    * <p>
788    * The array can be arbitrarily long to indicate arbitrarily complex data structures.
789    *
790    * <h5 class='section'>Notes:</h5><ul>
791    *    <li class='note'>
792    *       Use the {@link #read(Object, Class)} method instead if you don't need a parameterized map/collection.
793    * </ul>
794    *
795    * @param <T> The class type of the object to create.
796    * @param input
797    *    The input.
798    *    <br>Character-based parsers can handle the following input class types:
799    *    <ul>
800    *       <li><jk>null</jk>
801    *       <li>{@link Reader}
802    *       <li>{@link CharSequence}
803    *       <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
804    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
805    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
806    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
807    *    </ul>
808    *    <br>Stream-based parsers can handle the following input class types:
809    *    <ul>
810    *       <li><jk>null</jk>
811    *       <li>{@link InputStream}
812    *       <li><code><jk>byte</jk>[]</code>
813    *       <li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting.
814    *    </ul>
815    * @param type
816    *    The object type to create.
817    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
818    * @param args
819    *    The type arguments of the class if it's a collection or map.
820    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
821    *    <br>Ignored if the main type is not a map or collection.
822    * @return The parsed object.
823    * @throws ParseException Malformed input encountered.
824    * @throws IOException Thrown by underlying stream.
825    * @see MarshallingSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
826    */
827   public final <T> T read(Object input, Type type, Type...args) throws ParseException, IOException {
828      return getSession().read(input, type, args);
829   }
830
831   /**
832    * Same as {@link #read(Object, Class)} but since it's a {@link String} input doesn't throw an {@link IOException}.
833    *
834    * @param <T> The class type of the object being created.
835    * @param input
836    *    The input.
837    *    See {@link #read(Object, Type, Type...)} for details.
838    * @param type The object type to create.
839    * @return The parsed object.
840    * @throws ParseException Malformed input encountered.
841    */
842   public final <T> T read(String input, Class<T> type) throws ParseException {
843      return getSession().read(input, type);
844   }
845
846   /**
847    * Same as {@link #read(Object, ClassMeta)} but since it's a {@link String} input doesn't throw an {@link IOException}.
848    *
849    * @param <T> The class type of the object being created.
850    * @param input
851    *    The input.
852    *    See {@link #read(Object, Type, Type...)} for details.
853    * @param type The object type to create.
854    * @return The parsed object.
855    * @throws ParseException Malformed input encountered.
856    */
857   public final <T> T read(String input, ClassMeta<T> type) throws ParseException {
858      return getSession().read(input, type);
859   }
860
861   /**
862    * Same as {@link #read(String, ClassMeta)} but creates the parser session with a specific outer object.
863    *
864    * <p>
865    * The outer object is used when instantiating top-level non-static inner classes and when setting
866    * {@link ParentProperty @ParentProperty} fields on parsed beans.
867    * This is important when a parser is used to parse inline content (e.g. JSON5 embedded in a Markdown
868    * table cell) where the parent bean context must be preserved.
869    *
870    * @param <T> The class type of the object being created.
871    * @param input The input string to parse.
872    * @param type The object type to create.
873    * @param outer
874    *    The outer object to associate with this parse session.
875    *    Used for {@link ParentProperty @ParentProperty} injection and
876    *    non-static inner class construction.
877    *    Can be <jk>null</jk> (no outer object is associated; <ja>@ParentProperty</ja> injection and non-static inner-class construction are skipped).
878    * @return The parsed object.
879    * @throws ParseException Malformed input encountered.
880    */
881   public final <T> T readWithOuter(String input, ClassMeta<T> type, Object outer) throws ParseException {
882      return createSession().outer(outer).build().read(input, type);
883   }
884
885   /**
886    * Same as {@link #read(Object, Type, Type...)} but since it's a {@link String} input doesn't throw an {@link IOException}.
887    *
888    * @param <T> The class type of the object being created.
889    * @param input
890    *    The input.
891    *    See {@link #read(Object, Type, Type...)} for details.
892    * @param type
893    *    The object type to create.
894    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
895    * @param args
896    *    The type arguments of the class if it's a collection or map.
897    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
898    *    <br>Ignored if the main type is not a map or collection.
899    * @return The parsed object.
900    * @throws ParseException Malformed input encountered.
901    */
902   public final <T> T read(String input, Type type, Type...args) throws ParseException {
903      return getSession().read(input, type, args);
904   }
905
906   /**
907    * Parses the specified array input with each entry in the object defined by the {@code argTypes}
908    * argument.
909    *
910    * <p>
911    * Used for converting arrays (e.g. <js>"[arg1,arg2,...]"</js>) into an {@code Object[]} that can be passed
912    * to the {@code Method.invoke(target, args)} method.
913    *
914    * <p>
915    * Used in the following locations:
916    * <ul class='spaced-list'>
917    *    <li>
918    *       Used to parse argument strings in the {@link ObjectIntrospector#invokeMethod(Method, Reader)} method.
919    * </ul>
920    *
921    * @param input The input.  Subclasses can support different input types.
922    * @param argTypes Specifies the type of objects to create for each entry in the array.
923    * @return An array of parsed objects.
924    * @throws ParseException Malformed input encountered.
925    */
926   public final Object[] readArgs(Object input, Type[] argTypes) throws ParseException {
927      if (argTypes == null || argTypes.length == 0)
928         return new Object[0];
929      return getSession().readArgs(input, argTypes);
930   }
931
932   /**
933    * Parses the contents of the specified reader and loads the results into the specified collection.
934    *
935    * <p>
936    * Used in the following locations:
937    * <ul class='spaced-list'>
938    *    <li>
939    *       The various character-based constructors in {@link JsonList} (e.g.
940    *       {@link JsonList#JsonList(CharSequence,Parser)}.
941    * </ul>
942    *
943    * @param <E> The element class type.
944    * @param input The input.  See {@link #read(Object, ClassMeta)} for supported input types.
945    * @param c The collection being loaded.
946    * @param elementType The class type of the elements, or <jk>null</jk> to default to whatever is being parsed.
947    * @return The same collection that was passed in to allow this method to be chained.
948    * @throws ParseException Malformed input encountered.
949    * @throws UnsupportedOperationException If not implemented.
950    */
951   public final <E> Collection<E> readIntoCollection(Object input, Collection<E> c, Type elementType) throws ParseException {
952      return getSession().readIntoCollection(input, c, elementType);
953   }
954
955   /**
956    * Parses the contents of the specified reader and loads the results into the specified map.
957    *
958    * <p>
959    * Reader must contain something that serializes to a map (such as text containing a JSON object).
960    *
961    * <p>
962    * Used in the following locations:
963    * <ul class='spaced-list'>
964    *    <li>
965    *       The various character-based constructors in {@link JsonMap} (e.g.
966    *       {@link JsonMap#JsonMap(CharSequence,Parser)}).
967    * </ul>
968    *
969    * @param <K> The key class type.
970    * @param <V> The value class type.
971    * @param input The input.  See {@link #read(Object, ClassMeta)} for supported input types.
972    * @param m The map being loaded.
973    * @param keyType The class type of the keys, or <jk>null</jk> to default to <code>String.<jk>class</jk></code>.
974    * @param valueType The class type of the values, or <jk>null</jk> to default to whatever is being parsed.
975    * @return The same map that was passed in to allow this method to be chained.
976    * @throws ParseException Malformed input encountered.
977    * @throws UnsupportedOperationException If not implemented.
978    */
979   public final <K,V> Map<K,V> readIntoMap(Object input, Map<K,V> m, Type keyType, Type valueType) throws ParseException {
980      return getSession().readIntoMap(input, m, keyType, valueType);
981   }
982
983   /**
984    * Debug output lines.
985    *
986    * @see Parser.Builder#debugOutputLines(int)
987    * @return
988    *    The number of lines of input before and after the error location to be printed as part of the exception message.
989    */
990   protected final int getDebugOutputLines() { return debugOutputLines; }
991
992   /**
993    * Parser listener.
994    *
995    * @see Parser.Builder#listener(Class)
996    * @return
997    *    Class used to listen for errors and warnings that occur during parsing, or <jk>null</jk> if none was configured.
998    */
999   protected final Class<? extends ParserListener> getListener() { return listener; }
1000
1001   /**
1002    * Auto-close streams.
1003    *
1004    * @see Parser.Builder#autoCloseStreams()
1005    * @return
1006    *    <jk>true</jk> if <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed
1007    *    after parsing is complete.
1008    */
1009   protected final boolean isAutoCloseStreams() { return autoCloseStreams; }
1010
1011   /**
1012    * Trim parsed strings.
1013    *
1014    * @see Parser.Builder#trimStrings()
1015    * @return
1016    *    <jk>true</jk> if string values will be trimmed of whitespace using {@link String#trim()} before being added to
1017    *    the POJO.
1018    */
1019   protected final boolean isTrimStrings() { return trimStrings; }
1020
1021   /**
1022    * Returns the context-level {@link Nulls} default consulted at parse-time when no per-property
1023    * {@link MarshalledProp#nulls() @MarshalledProp(nulls=…)} is configured.
1024    *
1025    * @return The current value (never <jk>null</jk>; {@link Nulls#NOT_SET} when unconfigured).
1026    * @see Parser.Builder#nulls(Nulls)
1027    * @since 10.0.0
1028    */
1029   public final Nulls getNulls() { return nulls; }
1030
1031   /**
1032    * Unbuffered.
1033    *
1034    * @see Parser.Builder#unbuffered()
1035    * @return
1036    *    <jk>true</jk> if parsers don't use internal buffering during parsing.
1037    */
1038   protected final boolean isUnbuffered() { return unbuffered; }
1039
1040   @Override /* Overridden from MarshallingContextable */
1041   protected FluentMap<String,Object> properties() {
1042      return super.properties()
1043         .a("autoCloseStreams", autoCloseStreams)
1044         .a("debugOutputLines", debugOutputLines)
1045         .a("listener", listener)
1046         .a("nulls", nulls)
1047         .a("trimStrings", trimStrings)
1048         .a("unbuffered", unbuffered);
1049   }
1050}