001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.parser;
018
019import static org.apache.juneau.collections.JsonMap.*;
020import static org.apache.juneau.common.utils.StringUtils.*;
021import static org.apache.juneau.internal.ClassUtils.*;
022
023import java.io.*;
024import java.lang.reflect.*;
025import java.nio.charset.*;
026import java.util.*;
027import java.util.function.*;
028
029import org.apache.juneau.*;
030import org.apache.juneau.annotation.*;
031import org.apache.juneau.collections.*;
032import org.apache.juneau.cp.*;
033import org.apache.juneau.httppart.*;
034import org.apache.juneau.internal.*;
035import org.apache.juneau.objecttools.*;
036import org.apache.juneau.swap.*;
037
038/**
039 * Session object that lives for the duration of a single use of {@link Parser}.
040 *
041 * <h5 class='section'>Notes:</h5><ul>
042 *    <li class='warn'>This class is not thread safe and is typically discarded after one use.
043 * </ul>
044 *
045 * <h5 class='section'>See Also:</h5><ul>
046 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a>
047
048 * </ul>
049 */
050public class ParserSession extends BeanSession {
051
052   //-------------------------------------------------------------------------------------------------------------------
053   // Static
054   //-------------------------------------------------------------------------------------------------------------------
055
056   /**
057    * Creates a new builder for this object.
058    *
059    * @param ctx The context creating this session.
060    * @return A new builder.
061    */
062   public static Builder create(Parser ctx) {
063      return new Builder(ctx);
064   }
065
066   //-------------------------------------------------------------------------------------------------------------------
067   // Builder
068   //-------------------------------------------------------------------------------------------------------------------
069
070   /**
071    * Builder class.
072    */
073   public static class Builder extends BeanSession.Builder {
074
075      Parser ctx;
076      Method javaMethod;
077      Object outer;
078      HttpPartSchema schema;
079
080      /**
081       * Constructor
082       *
083       * @param ctx The context creating this session.
084       */
085      protected Builder(Parser ctx) {
086         super(ctx.getBeanContext());
087         this.ctx = ctx;
088         mediaTypeDefault(ctx.getPrimaryMediaType());
089      }
090
091      @Override
092      public ParserSession build() {
093         return new ParserSession(this);
094      }
095
096      /**
097       * The java method that called this serializer, usually the method in a REST servlet.
098       *
099       * @param value
100       *    The new property value.
101       *    <br>Can be <jk>null</jk>.
102       * @return This object.
103       */
104      public Builder javaMethod(Method value) {
105         this.javaMethod = value;
106         return this;
107      }
108
109      /**
110       * The outer object for instantiating top-level non-static inner classes.
111       *
112       * @param value
113       *    The new property value.
114       *    <br>Can be <jk>null</jk>.
115       * @return This object.
116       */
117      public Builder outer(Object value) {
118         this.outer = value;
119         return this;
120      }
121
122      /**
123       * HTTP-part schema.
124       *
125       * <p>
126       * Used for schema-based serializers and parsers to define additional formatting.
127       *
128       * @param value
129       *    The new value for this property.
130       *    <br>Can be <jk>null</jk>.
131       * @return This object.
132       */
133      public Builder schema(HttpPartSchema value) {
134         if (value != null)
135            this.schema = value;
136         return this;
137      }
138
139      /**
140       * Same as {@link #schema(HttpPartSchema)} but doesn't overwrite the value if it is already set.
141       *
142       * @param value
143       *    The new value for this property.
144       *    <br>If <jk>null</jk>, then the locale defined on the context is used.
145       * @return This object.
146       */
147      public Builder schemaDefault(HttpPartSchema value) {
148         if (value != null && schema == null)
149            this.schema = value;
150         return this;
151      }
152      @Override /* Overridden from Builder */
153      public <T> Builder apply(Class<T> type, Consumer<T> apply) {
154         super.apply(type, apply);
155         return this;
156      }
157
158      @Override /* Overridden from Builder */
159      public Builder debug(Boolean value) {
160         super.debug(value);
161         return this;
162      }
163
164      @Override /* Overridden from Builder */
165      public Builder properties(Map<String,Object> value) {
166         super.properties(value);
167         return this;
168      }
169
170      @Override /* Overridden from Builder */
171      public Builder property(String key, Object value) {
172         super.property(key, value);
173         return this;
174      }
175
176      @Override /* Overridden from Builder */
177      public Builder unmodifiable() {
178         super.unmodifiable();
179         return this;
180      }
181
182      @Override /* Overridden from Builder */
183      public Builder locale(Locale value) {
184         super.locale(value);
185         return this;
186      }
187
188      @Override /* Overridden from Builder */
189      public Builder localeDefault(Locale value) {
190         super.localeDefault(value);
191         return this;
192      }
193
194      @Override /* Overridden from Builder */
195      public Builder mediaType(MediaType value) {
196         super.mediaType(value);
197         return this;
198      }
199
200      @Override /* Overridden from Builder */
201      public Builder mediaTypeDefault(MediaType value) {
202         super.mediaTypeDefault(value);
203         return this;
204      }
205
206      @Override /* Overridden from Builder */
207      public Builder timeZone(TimeZone value) {
208         super.timeZone(value);
209         return this;
210      }
211
212      @Override /* Overridden from Builder */
213      public Builder timeZoneDefault(TimeZone value) {
214         super.timeZoneDefault(value);
215         return this;
216      }
217   }
218
219   //-------------------------------------------------------------------------------------------------------------------
220   // Instance
221   //-------------------------------------------------------------------------------------------------------------------
222
223   private final Parser ctx;
224   private final Method javaMethod;
225   private final Object outer;
226   private final Stack<StringBuilder> sbStack;
227   private final HttpPartSchema schema;
228
229   // Writable properties.
230   private BeanPropertyMeta currentProperty;
231   private ClassMeta<?> currentClass;
232   private final ParserListener listener;
233
234   private Position mark = new Position(-1);
235
236   private ParserPipe pipe;
237
238   /**
239    * Constructor.
240    *
241    * @param builder The builder for this object.
242    */
243   protected ParserSession(Builder builder) {
244      super(builder);
245      ctx = builder.ctx;
246      javaMethod = builder.javaMethod;
247      outer = builder.outer;
248      schema = builder.schema;
249      listener = BeanCreator.of(ParserListener.class).type(ctx.getListener()).orElse(null);
250      sbStack = new Stack<>();
251   }
252
253   //-----------------------------------------------------------------------------------------------------------------
254   // Abstract methods
255   //-----------------------------------------------------------------------------------------------------------------
256
257   /**
258    * Workhorse method.
259    *
260    * <p>
261    * Subclasses are expected to implement this method or {@link Parser#doParse(ParserSession,ParserPipe,ClassMeta)}.
262    *
263    * <p>
264    * The default implementation of this method simply calls {@link Parser#doParse(ParserSession,ParserPipe,ClassMeta)}.
265    *
266    * @param pipe Where to get the input from.
267    * @param type
268    *    The class type of the object to create.
269    *    If <jk>null</jk> or <code>Object.<jk>class</jk></code>, object type is based on what's being parsed.
270    *    For example, when parsing JSON text, it may return a <c>String</c>, <c>Number</c>,
271    *    <c>JsonMap</c>, etc...
272    * @param <T> The class type of the object to create.
273    * @return The parsed object.
274    * @throws IOException Thrown by underlying stream.
275    * @throws ParseException Malformed input encountered.
276    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
277    */
278   protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {
279      return ctx.doParse(this, pipe, type);
280   }
281
282   /**
283    * Returns <jk>true</jk> if this parser subclasses from {@link ReaderParser}.
284    *
285    * @return <jk>true</jk> if this parser subclasses from {@link ReaderParser}.
286    */
287   public boolean isReaderParser() {
288      return false;
289   }
290
291
292   //-----------------------------------------------------------------------------------------------------------------
293   // Other methods
294   //-----------------------------------------------------------------------------------------------------------------
295
296   /**
297    * Wraps the specified input object into a {@link ParserPipe} object so that it can be easily converted into
298    * a stream or reader.
299    *
300    * @param input
301    *    The input.
302    *    <br>For character-based parsers, this can be any of the following types:
303    *    <ul>
304    *       <li><jk>null</jk>
305    *       <li>{@link Reader}
306    *       <li>{@link CharSequence}
307    *       <li>{@link InputStream} containing UTF-8 encoded text (or whatever the encoding specified by
308    *          {@link ReaderParser.Builder#streamCharset(Charset)}).
309    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or whatever the encoding specified by
310    *          {@link ReaderParser.Builder#streamCharset(Charset)}).
311    *       <li>{@link File} containing system encoded text (or whatever the encoding specified by
312    *          {@link ReaderParser.Builder#fileCharset(Charset)}).
313    *    </ul>
314    *    <br>For byte-based parsers, this can be any of the following types:
315    *    <ul>
316    *       <li><jk>null</jk>
317    *       <li>{@link InputStream}
318    *       <li><code><jk>byte</jk>[]</code>
319    *       <li>{@link File}
320    *       <li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting.
321    *    </ul>
322    * @return
323    *    A new {@link ParserPipe} wrapper around the specified input object.
324    */
325   protected ParserPipe createPipe(Object input) {
326      return null;
327   }
328
329   /**
330    * Returns information used to determine at what location in the parse a failure occurred.
331    *
332    * @return A map, typically containing something like <c>{line:123,column:456,currentProperty:"foobar"}</c>
333    */
334   public final JsonMap getLastLocation() {
335      JsonMap m = new JsonMap();
336      if (currentClass != null)
337         m.put("currentClass", currentClass.toString(true));
338      if (currentProperty != null)
339         m.put("currentProperty", currentProperty);
340      return m;
341   }
342
343   /**
344    * Returns the Java method that invoked this parser.
345    *
346    * <p>
347    * When using the REST API, this is the Java method invoked by the REST call.
348    * Can be used to access annotations defined on the method or class.
349    *
350    * @return The Java method that invoked this parser.
351   */
352   protected final Method getJavaMethod() {
353      return javaMethod;
354   }
355
356   /**
357    * Returns the outer object used for instantiating top-level non-static member classes.
358    *
359    * <p>
360    * When using the REST API, this is the servlet object.
361    *
362    * @return The outer object.
363   */
364   protected final Object getOuter() {
365      return outer;
366   }
367
368   /**
369    * Sets the current bean property being parsed for proper error messages.
370    *
371    * @param currentProperty The current property being parsed.
372    */
373   protected final void setCurrentProperty(BeanPropertyMeta currentProperty) {
374      this.currentProperty = currentProperty;
375   }
376
377   /**
378    * Sets the current class being parsed for proper error messages.
379    *
380    * @param currentClass The current class being parsed.
381    */
382   protected final void setCurrentClass(ClassMeta<?> currentClass) {
383      this.currentClass = currentClass;
384   }
385
386   /**
387    * Trims the specified object if it's a <c>String</c> and {@link #isTrimStrings()} returns <jk>true</jk>.
388    *
389    * @param <K> The object type.
390    * @param o The object to trim.
391    * @return The trimmed string if it's a string.
392    */
393   @SuppressWarnings("unchecked")
394   protected final <K> K trim(K o) {
395      if (isTrimStrings() && o instanceof String)
396         return (K)o.toString().trim();
397      return o;
398
399   }
400
401   /**
402    * Trims the specified string if {@link ParserSession#isTrimStrings()} returns <jk>true</jk>.
403    *
404    * @param s The input string to trim.
405    * @return The trimmed string, or <jk>null</jk> if the input was <jk>null</jk>.
406    */
407   protected final String trim(String s) {
408      if (isTrimStrings() && s != null)
409         return s.trim();
410      return s;
411   }
412
413   /**
414    * Converts the specified <c>JsonMap</c> into a bean identified by the <js>"_type"</js> property in the map.
415    *
416    * @param m The map to convert to a bean.
417    * @param pMeta The current bean property being parsed.
418    * @param eType The current expected type being parsed.
419    * @return
420    *    The converted bean, or the same map if the <js>"_type"</js> entry wasn't found or didn't resolve to a bean.
421    */
422   protected final Object cast(JsonMap m, BeanPropertyMeta pMeta, ClassMeta<?> eType) {
423
424      String btpn = getBeanTypePropertyName(eType);
425
426      Object o = m.get(btpn);
427      if (o == null)
428         return m;
429      String typeName = o.toString();
430
431      ClassMeta<?> cm = getClassMeta(typeName, pMeta, eType);
432
433      if (cm != null) {
434         BeanMap<?> bm = m.getBeanSession().newBeanMap(cm.getInnerClass());
435
436         // Iterate through all the entries in the map and set the individual field values.
437         m.forEach((k,v) -> {
438            if (! k.equals(btpn)) {
439               // Attempt to recursively cast child maps.
440               if (v instanceof JsonMap)
441                  v = cast((JsonMap)v, pMeta, eType);
442               bm.put(k, v);
443            }
444         });
445         return bm.getBean();
446      }
447
448      return m;
449   }
450
451   /**
452    * Give the specified dictionary name, resolve it to a class.
453    *
454    * @param typeName The dictionary name to resolve.
455    * @param pMeta The bean property we're currently parsing.
456    * @param eType The expected type we're currently parsing.
457    * @return The resolved class, or <jk>null</jk> if the type name could not be resolved.
458    */
459   protected final ClassMeta<?> getClassMeta(String typeName, BeanPropertyMeta pMeta, ClassMeta<?> eType) {
460      BeanRegistry br = null;
461
462      // Resolve via @Beanp(dictionary={})
463      if (pMeta != null) {
464         br = pMeta.getBeanRegistry();
465         if (br != null && br.hasName(typeName))
466            return br.getClassMeta(typeName);
467      }
468
469      // Resolve via @Bean(dictionary={}) on the expected type where the
470      // expected type is an interface with subclasses.
471      if (eType != null) {
472         br = eType.getBeanRegistry();
473         if (br != null && br.hasName(typeName))
474            return br.getClassMeta(typeName);
475      }
476
477      // Last resort, resolve using the session registry.
478      return getBeanRegistry().getClassMeta(typeName);
479   }
480
481   /**
482    * Specialized warning when an exception is thrown while executing a bean setter.
483    *
484    * @param p The bean map entry representing the bean property.
485    * @param t The throwable that the bean setter threw.
486    */
487   protected final void onBeanSetterException(BeanPropertyMeta p, Throwable t) {
488      if (listener != null)
489         listener.onBeanSetterException(this, t, p);
490      String prefix = "";
491      addWarning("{0}Could not call setValue() on property ''{1}'' of class ''{2}'', exception = {3}", prefix,
492         p.getName(), p.getBeanMeta().getClassMeta(), t.getLocalizedMessage());
493   }
494
495   /**
496    * Method that gets called when an unknown bean property name is encountered.
497    *
498    * @param propertyName The unknown bean property name.
499    * @param beanMap The bean that doesn't have the expected property.
500    * @param value The parsed value.
501    * @throws ParseException
502    *    Automatically thrown if {@link org.apache.juneau.BeanContext.Builder#ignoreUnknownBeanProperties()} setting on this parser is
503    *    <jk>false</jk>
504    * @param <T> The class type of the bean map that doesn't have the expected property.
505    */
506   protected final <T> void onUnknownProperty(String propertyName, BeanMap<T> beanMap, Object value) throws ParseException {
507      if (propertyName.equals(getBeanTypePropertyName(beanMap.getClassMeta())))
508         return;
509      if (! isIgnoreUnknownBeanProperties())
510         if (value != null || ! isIgnoreUnknownNullBeanProperties())
511            throw new ParseException(this,
512               "Unknown property ''{0}'' encountered while trying to parse into class ''{1}''", propertyName,
513               beanMap.getClassMeta());
514      if (listener != null)
515         listener.onUnknownBeanProperty(this, propertyName, beanMap.getClassMeta().getInnerClass(), beanMap.getBean());
516   }
517
518   /**
519    * Parses input into the specified object type.
520    *
521    * <p>
522    * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
523    *
524    * <h5 class='section'>Examples:</h5>
525    * <p class='bjava'>
526    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
527    *
528    *    <jc>// Parse into a linked-list of strings.</jc>
529    *    List <jv>list1</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
530    *
531    *    <jc>// Parse into a linked-list of beans.</jc>
532    *    List <jv>list2</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
533    *
534    *    <jc>// Parse into a linked-list of linked-lists of strings.</jc>
535    *    List <jv>list3</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
536    *
537    *    <jc>// Parse into a map of string keys/values.</jc>
538    *    Map <jv>map1</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
539    *
540    *    <jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
541    *    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>);
542    * </p>
543    *
544    * <p>
545    * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
546    *
547    * <p>
548    * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types.
549    *
550    * <p>
551    * The array can be arbitrarily long to indicate arbitrarily complex data structures.
552    *
553    * <h5 class='section'>Notes:</h5><ul>
554    *    <li class='note'>
555    *       Use the {@link #parse(Object, Class)} method instead if you don't need a parameterized map/collection.
556    * </ul>
557    *
558    * @param <T> The class type of the object to create.
559    * @param input
560    *    The input.
561    *    <br>Character-based parsers can handle the following input class types:
562    *    <ul>
563    *       <li><jk>null</jk>
564    *       <li>{@link Reader}
565    *       <li>{@link CharSequence}
566    *       <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
567    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
568    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
569    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
570    *       <li>{@link File} containing system encoded text (or charset defined by
571    *          {@link ReaderParser.Builder#fileCharset(Charset)} property value).
572    *    </ul>
573    *    <br>Stream-based parsers can handle the following input class types:
574    *    <ul>
575    *       <li><jk>null</jk>
576    *       <li>{@link InputStream}
577    *       <li><code><jk>byte</jk>[]</code>
578    *       <li>{@link File}
579    *    </ul>
580    * @param type
581    *    The object type to create.
582    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
583    * @param args
584    *    The type arguments of the class if it's a collection or map.
585    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
586    *    <br>Ignored if the main type is not a map or collection.
587    * @return The parsed object.
588    * @throws ParseException Malformed input encountered.
589    * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
590    * @throws IOException Thrown by the underlying stream.
591    */
592   @SuppressWarnings("unchecked")
593   public final <T> T parse(Object input, Type type, Type...args) throws ParseException, IOException {
594      try (ParserPipe pipe = createPipe(input)) {
595         return (T)parseInner(pipe, getClassMeta(type, args));
596      }
597   }
598
599   /**
600    * Same as {@link #parse(Object,Type,Type...)} but parses from a string and doesn't throw an {@link IOException}.
601    *
602    * @param <T> The class type of the object to create.
603    * @param input
604    *    The input.
605    *    <br>Character-based parsers can handle the following input class types:
606    *    <ul>
607    *       <li><jk>null</jk>
608    *       <li>{@link Reader}
609    *       <li>{@link CharSequence}
610    *       <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
611    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
612    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
613    *          {@link ReaderParser.Builder#streamCharset(Charset)} property value).
614    *       <li>{@link File} containing system encoded text (or charset defined by
615    *          {@link ReaderParser.Builder#fileCharset(Charset)} property value).
616    *    </ul>
617    *    <br>Stream-based parsers can handle the following input class types:
618    *    <ul>
619    *       <li><jk>null</jk>
620    *       <li>{@link InputStream}
621    *       <li><code><jk>byte</jk>[]</code>
622    *       <li>{@link File}
623    *    </ul>
624    * @param type
625    *    The object type to create.
626    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
627    * @param args
628    *    The type arguments of the class if it's a collection or map.
629    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
630    *    <br>Ignored if the main type is not a map or collection.
631    * @return The parsed object.
632    * @throws ParseException Malformed input encountered.
633    * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
634    */
635   @SuppressWarnings("unchecked")
636   public final <T> T parse(String input, Type type, Type...args) throws ParseException {
637      try (ParserPipe pipe = createPipe(input)) {
638         return (T)parseInner(pipe, getClassMeta(type, args));
639      } catch (IOException e) {
640         throw new ParseException(e); // Shouldn't happen.
641      }
642   }
643
644   /**
645    * Same as {@link #parse(Object, Type, Type...)} except optimized for a non-parameterized class.
646    *
647    * <p>
648    * This is the preferred parse method for simple types since you don't need to cast the results.
649    *
650    * <h5 class='section'>Examples:</h5>
651    * <p class='bjava'>
652    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
653    *
654    *    <jc>// Parse into a string.</jc>
655    *    String <jv>string</jv> = <jv>parser</jv>.parse(<jv>json</jv>, String.<jk>class</jk>);
656    *
657    *    <jc>// Parse into a bean.</jc>
658    *    MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
659    *
660    *    <jc>// Parse into a bean array.</jc>
661    *    MyBean[] <jv>beanArray</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean[].<jk>class</jk>);
662    *
663    *    <jc>// Parse into a linked-list of objects.</jc>
664    *    List <jv>list</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>);
665    *
666    *    <jc>// Parse into a map of object keys/values.</jc>
667    *    Map <jv>map</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>);
668    * </p>
669    *
670    * @param <T> The class type of the object being created.
671    * @param input
672    *    The input.
673    *    See {@link #parse(Object, Type, Type...)} for details.
674    * @param type The object type to create.
675    * @return The parsed object.
676    * @throws ParseException Malformed input encountered.
677    * @throws IOException Thrown by the underlying stream.
678    */
679   public final <T> T parse(Object input, Class<T> type) throws ParseException, IOException {
680      try (ParserPipe pipe = createPipe(input)) {
681         return parseInner(pipe, getClassMeta(type));
682      }
683   }
684
685   /**
686    * Same as {@link #parse(Object, Class)} but parses from a string and doesn't throw an {@link IOException}.
687    *
688    * <p>
689    * This is the preferred parse method for simple types since you don't need to cast the results.
690    *
691    * <h5 class='section'>Examples:</h5>
692    * <p class='bjava'>
693    *    ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
694    *
695    *    <jc>// Parse into a string.</jc>
696    *    String <jv>string</jv> = <jv>parser</jv>.parse(<jv>json</jv>, String.<jk>class</jk>);
697    *
698    *    <jc>// Parse into a bean.</jc>
699    *    MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
700    *
701    *    <jc>// Parse into a bean array.</jc>
702    *    MyBean[] <jv>beanArray</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean[].<jk>class</jk>);
703    *
704    *    <jc>// Parse into a linked-list of objects.</jc>
705    *    List <jv>list</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>);
706    *
707    *    <jc>// Parse into a map of object keys/values.</jc>
708    *    Map <jv>map</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>);
709    * </p>
710    *
711    * @param <T> The class type of the object being created.
712    * @param input
713    *    The input.
714    *    See {@link #parse(Object, Type, Type...)} for details.
715    * @param type The object type to create.
716    * @return The parsed object.
717    * @throws ParseException Malformed input encountered.
718    */
719   public final <T> T parse(String input, Class<T> type) throws ParseException {
720      try (ParserPipe pipe = createPipe(input)) {
721         return parseInner(pipe, getClassMeta(type));
722      } catch (IOException e) {
723         throw new ParseException(e); // Shouldn't happen.
724      }
725   }
726
727   /**
728    * Same as {@link #parse(Object, Type, Type...)} except the type has already been converted into a {@link ClassMeta}
729    * object.
730    *
731    * <p>
732    * This is mostly an internal method used by the framework.
733    *
734    * @param <T> The class type of the object being created.
735    * @param input
736    *    The input.
737    *    See {@link #parse(Object, Type, Type...)} for details.
738    * @param type The object type to create.
739    * @return The parsed object.
740    * @throws ParseException Malformed input encountered.
741    * @throws IOException Thrown by the underlying stream.
742    */
743   public final <T> T parse(Object input, ClassMeta<T> type) throws ParseException, IOException {
744      try (ParserPipe pipe = createPipe(input)) {
745         return parseInner(pipe, type);
746      }
747   }
748
749   /**
750    * Same as {@link #parse(Object, ClassMeta)} except parses from a string and doesn't throw an {@link IOException}.
751    *
752    * <p>
753    * This is mostly an internal method used by the framework.
754    *
755    * @param <T> The class type of the object being created.
756    * @param input
757    *    The input.
758    *    See {@link #parse(Object, Type, Type...)} for details.
759    * @param type The object type to create.
760    * @return The parsed object.
761    * @throws ParseException Malformed input encountered.
762    */
763   public final <T> T parse(String input, ClassMeta<T> type) throws ParseException {
764      try (ParserPipe pipe = createPipe(input)) {
765         return parseInner(pipe, type);
766      } catch (IOException e) {
767         throw new ParseException(e); // Shouldn't happen.
768      }
769   }
770
771   /**
772    * Entry point for all parsing calls.
773    *
774    * <p>
775    * Calls the {@link #doParse(ParserPipe, ClassMeta)} implementation class and catches/re-wraps any exceptions
776    * thrown.
777    *
778    * @param pipe The parser input.
779    * @param type The class type of the object to create.
780    * @param <T> The class type of the object to create.
781    * @return The parsed object.
782    * @throws ParseException Malformed input encountered.
783    * @throws IOException Thrown by the underlying stream.
784    */
785   private <T> T parseInner(ParserPipe pipe, ClassMeta<T> type) throws ParseException, IOException {
786      if (type.isVoid())
787         return null;
788      try {
789         return doParse(pipe, type);
790      } catch (ParseException | IOException e) {
791         throw e;
792      } catch (StackOverflowError e) {
793         throw new ParseException(this, "Depth too deep.  Stack overflow occurred.");
794      } catch (Exception e) {
795         throw new ParseException(this, e, "Exception occurred.  exception={0}, message={1}.",
796            e.getClass().getSimpleName(), e.getLocalizedMessage());
797      } finally {
798         checkForWarnings();
799      }
800   }
801
802   /**
803    * Parses the contents of the specified reader and loads the results into the specified map.
804    *
805    * <p>
806    * Reader must contain something that serializes to a map (such as text containing a JSON object).
807    *
808    * <p>
809    * Used in the following locations:
810    * <ul class='spaced-list'>
811    *    <li>
812    *       The various character-based constructors in {@link JsonMap} (e.g.
813    *       {@link JsonMap#JsonMap(CharSequence,Parser)}).
814    * </ul>
815    *
816    * @param <K> The key class type.
817    * @param <V> The value class type.
818    * @param input The input.  See {@link #parse(Object, ClassMeta)} for supported input types.
819    * @param m The map being loaded.
820    * @param keyType The class type of the keys, or <jk>null</jk> to default to <code>String.<jk>class</jk></code>.
821    * @param valueType The class type of the values, or <jk>null</jk> to default to whatever is being parsed.
822    * @return The same map that was passed in to allow this method to be chained.
823    * @throws ParseException Malformed input encountered.
824    * @throws UnsupportedOperationException If not implemented.
825    */
826   public final <K,V> Map<K,V> parseIntoMap(Object input, Map<K,V> m, Type keyType, Type valueType) throws ParseException {
827      try (ParserPipe pipe = createPipe(input)) {
828         return doParseIntoMap(pipe, m, keyType, valueType);
829      } catch (ParseException e) {
830         throw e;
831      } catch (Exception e) {
832         throw new ParseException(this, e);
833      } finally {
834         checkForWarnings();
835      }
836   }
837
838   /**
839    * Implementation method.
840    *
841    * <p>
842    * Default implementation throws an {@link UnsupportedOperationException}.
843    *
844    * @param <K> The key type.
845    * @param <V> The value type.
846    * @param pipe The parser input.
847    * @param m The map being loaded.
848    * @param keyType The class type of the keys, or <jk>null</jk> to default to <code>String.<jk>class</jk></code>.
849    * @param valueType The class type of the values, or <jk>null</jk> to default to whatever is being parsed.
850    * @return The same map that was passed in to allow this method to be chained.
851    * @throws Exception If thrown from underlying stream, or if the input contains a syntax error or is malformed.
852    */
853   protected <K,V> Map<K,V> doParseIntoMap(ParserPipe pipe, Map<K,V> m, Type keyType, Type valueType) throws Exception {
854      throw new UnsupportedOperationException("Parser '"+className(getClass())+"' does not support this method.");
855   }
856
857   /**
858    * Parses the contents of the specified reader and loads the results into the specified collection.
859    *
860    * <p>
861    * Used in the following locations:
862    * <ul class='spaced-list'>
863    *    <li>
864    *       The various character-based constructors in {@link JsonList} (e.g.
865    *       {@link JsonList#JsonList(CharSequence,Parser)}.
866    * </ul>
867    *
868    * @param <E> The element class type.
869    * @param input The input.  See {@link #parse(Object, ClassMeta)} for supported input types.
870    * @param c The collection being loaded.
871    * @param elementType The class type of the elements, or <jk>null</jk> to default to whatever is being parsed.
872    * @return The same collection that was passed in to allow this method to be chained.
873    * @throws ParseException Malformed input encountered.
874    * @throws UnsupportedOperationException If not implemented.
875    */
876   public final <E> Collection<E> parseIntoCollection(Object input, Collection<E> c, Type elementType) throws ParseException {
877      try (ParserPipe pipe = createPipe(input)) {
878         return doParseIntoCollection(pipe, c, elementType);
879      } catch (ParseException e) {
880         throw e;
881      } catch (StackOverflowError e) {
882         throw new ParseException(this, "Depth too deep.  Stack overflow occurred.");
883      } catch (IOException e) {
884         throw new ParseException(this, e, "I/O exception occurred.  exception={0}, message={1}.",
885            e.getClass().getSimpleName(), e.getLocalizedMessage());
886      } catch (Exception e) {
887         throw new ParseException(this, e, "Exception occurred.  exception={0}, message={1}.",
888            e.getClass().getSimpleName(), e.getLocalizedMessage());
889      } finally {
890         checkForWarnings();
891      }
892   }
893
894   /**
895    * Implementation method.
896    *
897    * <p>
898    * Default implementation throws an {@link UnsupportedOperationException}.
899    *
900    * @param <E> The element type.
901    * @param pipe The parser input.
902    * @param c The collection being loaded.
903    * @param elementType The class type of the elements, or <jk>null</jk> to default to whatever is being parsed.
904    * @return The same collection that was passed in to allow this method to be chained.
905    * @throws Exception If thrown from underlying stream, or if the input contains a syntax error or is malformed.
906    */
907   protected <E> Collection<E> doParseIntoCollection(ParserPipe pipe, Collection<E> c, Type elementType) throws Exception {
908      throw new UnsupportedOperationException("Parser '"+className(getClass())+"' does not support this method.");
909   }
910
911   /**
912    * Parses the specified array input with each entry in the object defined by the {@code argTypes}
913    * argument.
914    *
915    * <p>
916    * Used for converting arrays (e.g. <js>"[arg1,arg2,...]"</js>) into an {@code Object[]} that can be passed
917    * to the {@code Method.invoke(target, args)} method.
918    *
919    * <p>
920    * Used in the following locations:
921    * <ul class='spaced-list'>
922    *    <li>
923    *       Used to parse argument strings in the {@link ObjectIntrospector#invokeMethod(Method, Reader)} method.
924    * </ul>
925    *
926    * @param input The input.  Subclasses can support different input types.
927    * @param argTypes Specifies the type of objects to create for each entry in the array.
928    * @return An array of parsed objects.
929    * @throws ParseException Malformed input encountered.
930    */
931   public final Object[] parseArgs(Object input, Type[] argTypes) throws ParseException {
932      try (ParserPipe pipe = createPipe(input)) {
933         return doParse(pipe, getArgsClassMeta(argTypes));
934      } catch (ParseException e) {
935         throw e;
936      } catch (StackOverflowError e) {
937         throw new ParseException(this, "Depth too deep.  Stack overflow occurred.");
938      } catch (IOException e) {
939         throw new ParseException(this, e, "I/O exception occurred.  exception={0}, message={1}.",
940            e.getClass().getSimpleName(), e.getLocalizedMessage());
941      } catch (Exception e) {
942         throw new ParseException(this, e, "Exception occurred.  exception={0}, message={1}.",
943            e.getClass().getSimpleName(), e.getLocalizedMessage());
944      } finally {
945         checkForWarnings();
946      }
947   }
948
949   /**
950    * Converts the specified string to the specified type.
951    *
952    * @param outer
953    *    The outer object if we're converting to an inner object that needs to be created within the context
954    *    of an outer object.
955    * @param s The string to convert.
956    * @param type The class type to convert the string to.
957    * @return The string converted as an object of the specified type.
958    * @param <T> The class type to convert the string to.
959    * @throws ParseException Malformed input encountered.
960    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
961    */
962   @SuppressWarnings({ "unchecked", "rawtypes" })
963   protected final <T> T convertAttrToType(Object outer, String s, ClassMeta<T> type) throws ParseException {
964      if (s == null)
965         return null;
966
967      if (type == null)
968         type = (ClassMeta<T>)object();
969      ObjectSwap swap = type.getSwap(this);
970      ClassMeta<?> sType = swap == null ? type : swap.getSwapClassMeta(this);
971
972      Object o = s;
973      if (sType.isChar())
974         o = parseCharacter(s);
975      else if (sType.isNumber())
976         o = parseNumber(s, (Class<? extends Number>)sType.getInnerClass());
977      else if (sType.isBoolean())
978         o = Boolean.parseBoolean(s);
979      else if (! (sType.isCharSequence() || sType.isObject())) {
980         if (sType.canCreateNewInstanceFromString(outer))
981            o = sType.newInstanceFromString(outer, s);
982         else
983            throw new ParseException(this, "Invalid conversion from string to class ''{0}''", type);
984      }
985
986      if (swap != null)
987         o = unswap(swap, o, type);
988
989      return (T)o;
990   }
991
992   /**
993    * Convenience method for calling the {@link ParentProperty @ParentProperty} method on the specified object if it
994    * exists.
995    *
996    * @param cm The class type of the object.
997    * @param o The object.
998    * @param parent The parent to set.
999    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
1000    */
1001   protected static final void setParent(ClassMeta<?> cm, Object o, Object parent) throws ExecutableException {
1002      Setter m = cm.getParentProperty();
1003      if (m != null)
1004         m.set(o, parent);
1005   }
1006
1007   /**
1008    * Convenience method for calling the {@link NameProperty @NameProperty} method on the specified object if it exists.
1009    *
1010    * @param cm The class type of the object.
1011    * @param o The object.
1012    * @param name The name to set.
1013    * @throws ExecutableException Exception occurred on invoked constructor/method/field.
1014    */
1015   protected static final void setName(ClassMeta<?> cm, Object o, Object name) throws ExecutableException {
1016      if (cm != null) {
1017         Setter m = cm.getNameProperty();
1018         if (m != null)
1019            m.set(o, name);
1020      }
1021   }
1022
1023   /**
1024    * Returns the listener associated with this session.
1025    *
1026    * @param <T> The listener type.
1027    * @param c The listener class to cast to.
1028    * @return The listener associated with this session, or <jk>null</jk> if there is no listener.
1029    */
1030   @SuppressWarnings("unchecked")
1031   public <T extends ParserListener> T getListener(Class<T> c) {
1032      return (T)listener;
1033   }
1034
1035   /**
1036    * The {@link #createPipe(Object)} method should call this method to set the pipe for debugging purposes.
1037    *
1038    * @param pipe The pipe created for this session.
1039    * @return The same pipe.
1040    */
1041   protected ParserPipe setPipe(ParserPipe pipe) {
1042      this.pipe = pipe;
1043      return pipe;
1044   }
1045
1046   /**
1047    * Returns the current position into the reader or input stream.
1048    *
1049    * @return
1050    *    The current position into the reader or input stream.
1051    *    <br>Never <jk>null</jk>.
1052    */
1053   public Position getPosition() {
1054      if (mark.line != -1 || mark.column != -1 || mark.position != -1)
1055         return mark;
1056      if (pipe == null)
1057         return Position.UNKNOWN;
1058      return pipe.getPosition();
1059   }
1060
1061   /**
1062    * Marks the current position.
1063    */
1064   protected void mark() {
1065      if (pipe != null) {
1066         Position p = pipe.getPosition();
1067         mark.line = p.line;
1068         mark.column = p.column;
1069         mark.position = p.position;
1070      }
1071   }
1072
1073   /**
1074    * Unmarks the current position.
1075    */
1076   protected void unmark() {
1077      mark.line = -1;
1078      mark.column = -1;
1079      mark.position = -1;
1080   }
1081
1082   /**
1083    * Returns the input as a string.
1084    *
1085    * <p>
1086    * This always returns a value for input of type {@link CharSequence}.
1087    * <br>For other input types, use {@link org.apache.juneau.Context.Builder#debug()} setting to enable caching to a string
1088    * before parsing so that this method returns the input.
1089    *
1090    * @return The input as a string, or <jk>null</jk> if no pipe has been created or we're reading from an uncached reader or input stream source.
1091    */
1092   public String getInputAsString() {
1093      return pipe == null ? null : pipe.getInputAsString();
1094   }
1095
1096   /**
1097    * Invokes the specified swap on the specified object.
1098    *
1099    * @param swap The swap to invoke.
1100    * @param o The input object.
1101    * @param eType The expected type.
1102    * @return The swapped object.
1103    * @throws ParseException If swap method threw an exception.
1104    */
1105   @SuppressWarnings({ "rawtypes", "unchecked" })
1106   protected Object unswap(ObjectSwap swap, Object o, ClassMeta<?> eType) throws ParseException {
1107      try {
1108         return swap.unswap(this, o, eType);
1109      } catch (Exception e) {
1110         throw new ParseException(e);
1111      }
1112   }
1113
1114   /**
1115    * Creates a reusable {@link StringBuilder} object from an internal pool.
1116    *
1117    * <p>
1118    * String builders are returned to the pool by calling {@link #returnStringBuilder(StringBuilder)}.
1119    *
1120    * @return A new or previously returned string builder.
1121    */
1122   protected final StringBuilder getStringBuilder() {
1123      if (sbStack.isEmpty())
1124         return new StringBuilder();
1125      return sbStack.pop();
1126   }
1127
1128   /**
1129    * Returns a {@link StringBuilder} object back into the internal reuse pool.
1130    *
1131    * @param sb The string builder to return to the pool.  No-op if <jk>null</jk>.
1132    */
1133   protected final void returnStringBuilder(StringBuilder sb) {
1134      if (sb == null)
1135         return;
1136      sb.setLength(0);
1137      sbStack.push(sb);
1138   }
1139
1140   //-----------------------------------------------------------------------------------------------------------------
1141   // Properties
1142   //-----------------------------------------------------------------------------------------------------------------
1143
1144   /**
1145    * Auto-close streams.
1146    *
1147    * @see Parser.Builder#autoCloseStreams()
1148    * @return
1149    *    <jk>true</jk> if <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed
1150    *    after parsing is complete.
1151    */
1152   protected final boolean isAutoCloseStreams() {
1153      return ctx.isAutoCloseStreams();
1154   }
1155
1156   /**
1157    * Debug output lines.
1158    *
1159    * @see Parser.Builder#debugOutputLines(int)
1160    * @return
1161    *    The number of lines of input before and after the error location to be printed as part of the exception message.
1162    */
1163   protected final int getDebugOutputLines() {
1164      return ctx.getDebugOutputLines();
1165   }
1166
1167   /**
1168    * Returns the listener associated with this session.
1169    *
1170    * @return The listener associated with this session, or <jk>null</jk> if there is no listener.
1171    */
1172   public ParserListener getListener() {
1173      return listener;
1174   }
1175
1176   /**
1177    * Strict mode.
1178    *
1179    * @see Parser.Builder#strict()
1180    * @return
1181    *    <jk>true</jk> if strict mode for the parser is enabled.
1182    */
1183   protected final boolean isStrict() {
1184      return ctx.isStrict();
1185   }
1186
1187   /**
1188    * Trim parsed strings.
1189    *
1190    * @see Parser.Builder#trimStrings()
1191    * @return
1192    *    <jk>true</jk> if string values will be trimmed of whitespace using {@link String#trim()} before being added to
1193    *    the POJO.
1194    */
1195   protected final boolean isTrimStrings() {
1196      return ctx.isTrimStrings();
1197   }
1198
1199   /**
1200    * Unbuffered.
1201    *
1202    * @see Parser.Builder#unbuffered()
1203    * @return
1204    *    <jk>true</jk> if parsers don't use internal buffering during parsing.
1205    */
1206   protected final boolean isUnbuffered() {
1207      return ctx.isUnbuffered();
1208   }
1209
1210   /**
1211    * HTTP part schema of object being parsed.
1212    *
1213    * @return HTTP part schema of object being parsed, or <jk>null</jk> if not specified.
1214    */
1215   public final HttpPartSchema getSchema() {
1216      return schema;
1217   }
1218
1219   //-----------------------------------------------------------------------------------------------------------------
1220   // Other methods
1221   //-----------------------------------------------------------------------------------------------------------------
1222
1223   /**
1224    * Parser listener.
1225    *
1226    * @see Parser.Builder#listener(Class)
1227    * @return
1228    *    Class used to listen for errors and warnings that occur during parsing.
1229    */
1230   protected final Class<? extends ParserListener> getListenerClass() {
1231      return ctx.getListener();
1232   }
1233
1234   @Override /* ContextSession */
1235   protected JsonMap properties() {
1236      return filteredMap("javaMethod", javaMethod, "listener", listener, "outer", outer);
1237   }
1238}