![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.juneau.parser.Parser Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau.parser;
import static org.apache.juneau.collections.JsonMap.*;
import static org.apache.juneau.common.internal.StringUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;
import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.nio.charset.*;
import java.util.*;
import org.apache.juneau.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.html.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.msgpack.*;
import org.apache.juneau.objecttools.*;
import org.apache.juneau.swap.*;
import org.apache.juneau.swaps.*;
import org.apache.juneau.uon.*;
import org.apache.juneau.utils.*;
import org.apache.juneau.xml.*;
/**
* Parent class for all Juneau parsers.
*
* Valid data conversions
*
* Parsers can parse any parsable POJO types, as specified in the POJO Categories.
*
*
* Some examples of conversions are shown below...
*
*
*
* Data type
* Class type
* JSON example
* XML example
* Class examples
*
*
* object
* Maps, Java beans
* {name:'John Smith' ,age:21}
* <object>
* <name type ='string' > John Smith</name>
* <age type ='number' > 21</age>
* </object>
* HashMap, TreeMap<String,Integer>
*
*
* array
* Collections, Java arrays
* [1,2,3]
* <array>
* <number> 1</number>
* <number> 2</number>
* <number> 3</number>
* </array>
* List<Integer>, int [], Float[], Set<Person>
*
*
* number
* Numbers
* 123
* <number> 123</number>
* Integer, Long, Float, int
*
*
* boolean
* Booleans
* true
* <boolean> true</boolean>
* Boolean
*
*
* string
* CharSequences
* 'foobar'
* <string> foobar</string>
* String, StringBuilder
*
*
*
*
* In addition, any class types with {@link ObjectSwap ObjectSwaps} associated with them on the registered
* bean context can also be passed in.
*
*
* For example, if the {@link TemporalCalendarSwap} transform is used to generalize {@code Calendar} objects to {@code String}
* objects.
* When registered with this parser, you can construct {@code Calendar} objects from {@code Strings} using the
* following syntax...
*
* Calendar calendar = parser .parse("'Sun Mar 03 04:05:06 EST 2001'" , GregorianCalendar.class );
*
*
*
* If Object.class
is specified as the target type, then the parser automatically determines the
* data types and generates the following object types...
*
* JSON type Class type
* object {@link JsonMap}
* array {@link JsonList}
* number {@link Number}
(depending on length and format, could be {@link Integer},
* {@link Double}, {@link Float}, etc...)
* boolean {@link Boolean}
* string {@link String}
*
*
* Notes:
* - This class is thread safe and reusable.
*
*
* See Also:
*/
public class Parser extends BeanContextable {
//-------------------------------------------------------------------------------------------------------------------
// Static
//-------------------------------------------------------------------------------------------------------------------
/**
* Creates a new builder for this object.
*
* @return A new builder.
*/
public static Builder create() {
return new Builder();
}
//-------------------------------------------------------------------------------------------------------------------
// Static
//-------------------------------------------------------------------------------------------------------------------
/**
* Represents no Parser.
*/
public static abstract class Null extends Parser {
private Null(Builder builder) {
super(builder);
}
}
/**
* Instantiates a builder of the specified parser class.
*
*
* Looks for a public static method called create that returns an object that can be passed into a public
* or protected constructor of the class.
*
* @param c The builder to create.
* @return A new builder.
*/
public static Builder createParserBuilder(Class extends Parser> c) {
return (Builder)Context.createBuilder(c);
}
//-------------------------------------------------------------------------------------------------------------------
// Builder
//-------------------------------------------------------------------------------------------------------------------
/**
* Builder class.
*/
@FluentSetters
public static class Builder extends BeanContextable.Builder {
boolean autoCloseStreams, strict, trimStrings, unbuffered;
String consumes;
int debugOutputLines;
Class extends ParserListener> listener;
/**
* Constructor, default settings.
*/
protected Builder() {
autoCloseStreams = env("Parser.autoCloseStreams", false);
strict = env("Parser.strict", false);
trimStrings = env("Parser.trimStrings", false);
unbuffered = env("Parser.unbuffered", false);
debugOutputLines = env("Parser.debugOutputLines", 5);
listener = null;
consumes = null;
}
/**
* Copy constructor.
*
* @param copyFrom The bean to copy from.
*/
protected Builder(Parser copyFrom) {
super(copyFrom);
autoCloseStreams = copyFrom.autoCloseStreams;
strict = copyFrom.strict;
trimStrings = copyFrom.trimStrings;
unbuffered = copyFrom.unbuffered;
debugOutputLines = copyFrom.debugOutputLines;
listener = copyFrom.listener;
consumes = copyFrom.consumes;
}
/**
* Copy constructor.
*
* @param copyFrom The builder to copy from.
*/
protected Builder(Builder copyFrom) {
super(copyFrom);
autoCloseStreams = copyFrom.autoCloseStreams;
strict = copyFrom.strict;
trimStrings = copyFrom.trimStrings;
unbuffered = copyFrom.unbuffered;
debugOutputLines = copyFrom.debugOutputLines;
listener = copyFrom.listener;
consumes = copyFrom.consumes;
}
@Override /* Context.Builder */
public Builder copy() {
return new Builder(this);
}
@Override /* Context.Builder */
public Parser build() {
return build(Parser.class);
}
@Override /* Context.Builder */
public HashKey hashKey() {
return HashKey.of(
super.hashKey(),
autoCloseStreams,
strict,
trimStrings,
unbuffered,
debugOutputLines,
listener,
consumes
);
}
//-----------------------------------------------------------------------------------------------------------------
// Properties
//-----------------------------------------------------------------------------------------------------------------
/**
* Specifies the media type that this parser consumes.
*
* @param value The value for this setting.
* @return This object.
*/
@FluentSetter
public Builder consumes(String value) {
this.consumes = value;
return this;
}
/**
* Returns the current value for the 'consumes' property.
*
* @return The current value for the 'consumes' property.
*/
public String getConsumes() {
return consumes;
}
/**
* Auto-close streams.
*
*
* When enabled, InputStreams and Readers passed into parsers will be closed
* after parsing is complete.
*
*
Example:
*
* // Create a parser using strict mode.
* ReaderParser parser = JsonParser
* .create ()
* .autoCloseStreams()
* .build();
*
* Reader myReader = new FileReader("/tmp/myfile.json" );
* MyBean myBean = parser .parse(myReader , MyBean.class );
*
* assertTrue (myReader .isClosed());
*
*
* @return This object.
*/
@FluentSetter
public Builder autoCloseStreams() {
return autoCloseStreams(true);
}
/**
* Same as {@link #autoCloseStreams()} but allows you to explicitly specify the value.
*
* @param value The value for this setting.
* @return This object.
*/
@FluentSetter
public Builder autoCloseStreams(boolean value) {
autoCloseStreams = value;
return this;
}
/**
* Debug output lines.
*
*
* When parse errors occur, this specifies the number of lines of input before and after the
* error location to be printed as part of the exception message.
*
*
Example:
*
* // Create a parser whose exceptions print out 100 lines before and after the parse error location.
* ReaderParser parser = JsonParser
* .create ()
* .debug() // Enable debug mode to capture Reader contents as strings.
* .debugOuputLines(100)
* .build();
*
* Reader myReader = new FileReader("/tmp/mybadfile.json" );
* try {
* parser .parse(myReader , Object.class );
* } catch (ParseException e ) {
* System.err .println(e .getMessage()); // Will display 200 lines of the output.
* }
*
*
* @param value
* The new value for this property.
*
The default value is 5 .
* @return This object.
*/
@FluentSetter
public Builder debugOutputLines(int value) {
debugOutputLines = value;
return this;
}
/**
* Parser listener.
*
*
* Class used to listen for errors and warnings that occur during parsing.
*
*
Example:
*
* // Define our parser listener.
* // Simply captures all unknown bean property events.
* public class MyParserListener extends ParserListener {
*
* // A simple property to store our events.
* public List<String> events = new LinkedList<>();
*
* @Override
* public <T> void onUnknownBeanProperty(ParserSession session , String propertyName , Class<T> beanClass , T bean ) {
* Position position = parser .getPosition();
* events .add(propertyName + "," + position .getLine() + "," + position .getColumn());
* }
* }
*
* // Create a parser using our listener.
* ReaderParser parser = JsonParser
* .create ()
* .listener(MyParserListener.class )
* .build();
*
* // Create a session object.
* // Needed because listeners are created per-session.
* try (ReaderParserSession session = parser .createSession()) {
*
* // Parse some JSON object.
* MyBean myBean = session .parse("{...}" , MyBean.class );
*
* // Get the listener.
* MyParserListener listener = session .getListener(MyParserListener.class );
*
* // Dump the results to the console.
* Json5.DEFAULT .println(listener .events );
* }
*
*
* @param value The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder listener(Class extends ParserListener> value) {
listener = value;
return this;
}
/**
* Strict mode.
*
*
* When enabled, strict mode for the parser is enabled.
*
*
* Strict mode can mean different things for different parsers.
*
*
* Parser class Strict behavior
*
* All reader-based parsers
*
* When enabled, throws {@link ParseException ParseExceptions} on malformed charset input.
* Otherwise, malformed input is ignored.
*
*
*
* {@link JsonParser}
*
* When enabled, throws exceptions on the following invalid JSON syntax:
*
* - Unquoted attributes.
*
- Missing attribute values.
*
- Concatenated strings.
*
- Javascript comments.
*
- Numbers and booleans when Strings are expected.
*
- Numbers valid in Java but not JSON (e.g. octal notation, etc...)
*
*
*
*
*
* Example:
*
* // Create a parser using strict mode.
* ReaderParser parser = JsonParser
* .create ()
* .strict()
* .build();
*
* // Use it.
* try {
* String json = "{unquotedAttr:'value'}" ;
* parser .parse(json , MyBean.class );
* } catch (ParseException e ) {
* assertTrue (e .getMessage().contains("Unquoted attribute detected." );
* }
*
*
* @return This object.
*/
@FluentSetter
public Builder strict() {
return strict(true);
}
/**
* Same as {@link #strict()} but allows you to explicitly specify the value.
*
* @param value The value for this setting.
* @return This object.
*/
@FluentSetter
public Builder strict(boolean value) {
strict = value;
return this;
}
/**
* Trim parsed strings.
*
*
* When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to
* the POJO.
*
*
Example:
*
* // Create a parser with trim-strings enabled.
* ReaderParser parser = JsonParser
* .create ()
* .trimStrings()
* .build();
*
* // Use it.
* String json = "{' foo ':' bar '}" ;
* Map<String,String> myMap = parser .parse(json , HashMap.class , String.class , String.class );
*
* // Make sure strings are parsed.
* assertEquals ("bar" , myMap .get("foo" ));
*
*
* @return This object.
*/
@FluentSetter
public Builder trimStrings() {
return trimStrings(true);
}
/**
* Same as {@link #trimStrings()} but allows you to explicitly specify the value.
*
* @param value The value for this setting.
* @return This object.
*/
@FluentSetter
public Builder trimStrings(boolean value) {
trimStrings = value;
return this;
}
/**
* Unbuffered.
*
*
* When enabled, don't use internal buffering during parsing.
*
*
* This is useful in cases when you want to parse the same input stream or reader multiple times
* because it may contain multiple independent POJOs to parse.
*
Buffering would cause the parser to read past the current POJO in the stream.
*
*
Example:
*
* // Create a parser using strict mode.
* ReaderParser parser = JsonParser.
* .create ()
* .unbuffered(true )
* .build();
*
* // If you're calling parse on the same input multiple times, use a session instead of the parser directly.
* // It's more efficient because we don't need to recalc the session settings again.
* ReaderParserSession session = parser .createSession();
*
* // Read input with multiple POJOs
* Reader json = new StringReader("{foo:'bar'}{foo:'baz'}" );
* MyBean myBean1 = session .parse(json , MyBean.class );
* MyBean myBean2 = session .parse(json , MyBean.class );
*
*
* Notes:
* -
* This only allows for multi-input streams for the following parsers:
*
* - {@link JsonParser}
*
- {@link UonParser}
*
* It has no effect on the following parsers:
*
* - {@link MsgPackParser} - It already doesn't use buffering.
*
- {@link XmlParser}, {@link HtmlParser} - These use StAX which doesn't allow for more than one root element anyway.
*
- RDF parsers - These read everything into an internal model before any parsing begins.
*
*
*
* @return This object.
*/
@FluentSetter
public Builder unbuffered() {
return unbuffered(true);
}
/**
* Same as {@link #unbuffered()} but allows you to explicitly specify the value.
*
* @param value The value for this setting.
* @return This object.
*/
@FluentSetter
public Builder unbuffered(boolean value) {
unbuffered = value;
return this;
}
//
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder annotations(Annotation...values) {
super.annotations(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder apply(AnnotationWorkList work) {
super.apply(work);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder applyAnnotations(java.lang.Class>...fromClasses) {
super.applyAnnotations(fromClasses);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder applyAnnotations(Method...fromMethods) {
super.applyAnnotations(fromMethods);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder cache(Cache value) {
super.cache(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder debug() {
super.debug();
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder debug(boolean value) {
super.debug(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder impl(Context value) {
super.impl(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder type(Class extends org.apache.juneau.Context> value) {
super.type(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanClassVisibility(Visibility value) {
super.beanClassVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanConstructorVisibility(Visibility value) {
super.beanConstructorVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanContext(BeanContext value) {
super.beanContext(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanContext(BeanContext.Builder value) {
super.beanContext(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanDictionary(java.lang.Class>...values) {
super.beanDictionary(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanFieldVisibility(Visibility value) {
super.beanFieldVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanInterceptor(Class> on, Class extends org.apache.juneau.swap.BeanInterceptor>> value) {
super.beanInterceptor(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanMapPutReturnsOldValue() {
super.beanMapPutReturnsOldValue();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanMethodVisibility(Visibility value) {
super.beanMethodVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanProperties(Map values) {
super.beanProperties(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanProperties(Class> beanClass, String properties) {
super.beanProperties(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanProperties(String beanClassName, String properties) {
super.beanProperties(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesExcludes(Map values) {
super.beanPropertiesExcludes(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesExcludes(Class> beanClass, String properties) {
super.beanPropertiesExcludes(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesExcludes(String beanClassName, String properties) {
super.beanPropertiesExcludes(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesReadOnly(Map values) {
super.beanPropertiesReadOnly(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesReadOnly(Class> beanClass, String properties) {
super.beanPropertiesReadOnly(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
super.beanPropertiesReadOnly(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesWriteOnly(Map values) {
super.beanPropertiesWriteOnly(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesWriteOnly(Class> beanClass, String properties) {
super.beanPropertiesWriteOnly(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
super.beanPropertiesWriteOnly(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beansRequireDefaultConstructor() {
super.beansRequireDefaultConstructor();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beansRequireSerializable() {
super.beansRequireSerializable();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beansRequireSettersForGetters() {
super.beansRequireSettersForGetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder dictionaryOn(Class> on, java.lang.Class>...values) {
super.dictionaryOn(on, values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableBeansRequireSomeProperties() {
super.disableBeansRequireSomeProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableIgnoreMissingSetters() {
super.disableIgnoreMissingSetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableIgnoreTransientFields() {
super.disableIgnoreTransientFields();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableIgnoreUnknownNullBeanProperties() {
super.disableIgnoreUnknownNullBeanProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableInterfaceProxies() {
super.disableInterfaceProxies();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder example(Class pojoClass, T o) {
super.example(pojoClass, o);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder example(Class pojoClass, String json) {
super.example(pojoClass, json);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder findFluentSetters() {
super.findFluentSetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder findFluentSetters(Class> on) {
super.findFluentSetters(on);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreInvocationExceptionsOnGetters() {
super.ignoreInvocationExceptionsOnGetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreInvocationExceptionsOnSetters() {
super.ignoreInvocationExceptionsOnSetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreUnknownBeanProperties() {
super.ignoreUnknownBeanProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreUnknownEnumValues() {
super.ignoreUnknownEnumValues();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder implClass(Class> interfaceClass, Class> implClass) {
super.implClass(interfaceClass, implClass);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder implClasses(Map,Class>> values) {
super.implClasses(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder interfaceClass(Class> on, Class> value) {
super.interfaceClass(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder interfaces(java.lang.Class>...value) {
super.interfaces(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder locale(Locale value) {
super.locale(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder mediaType(MediaType value) {
super.mediaType(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder notBeanClasses(java.lang.Class>...values) {
super.notBeanClasses(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder notBeanPackages(String...values) {
super.notBeanPackages(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder propertyNamer(Class extends org.apache.juneau.PropertyNamer> value) {
super.propertyNamer(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder propertyNamer(Class> on, Class extends org.apache.juneau.PropertyNamer> value) {
super.propertyNamer(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder sortProperties() {
super.sortProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder sortProperties(java.lang.Class>...on) {
super.sortProperties(on);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder stopClass(Class> on, Class> value) {
super.stopClass(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder swap(Class normalClass, Class swappedClass, ThrowingFunction swapFunction) {
super.swap(normalClass, swappedClass, swapFunction);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder swap(Class normalClass, Class swappedClass, ThrowingFunction swapFunction, ThrowingFunction unswapFunction) {
super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder swaps(java.lang.Class>...values) {
super.swaps(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder timeZone(TimeZone value) {
super.timeZone(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder typeName(Class> on, String value) {
super.typeName(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder typePropertyName(String value) {
super.typePropertyName(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder typePropertyName(Class> on, String value) {
super.typePropertyName(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder useEnumNames() {
super.useEnumNames();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder useJavaBeanIntrospector() {
super.useJavaBeanIntrospector();
return this;
}
//
}
//-------------------------------------------------------------------------------------------------------------------
// Instance
//-------------------------------------------------------------------------------------------------------------------
final boolean trimStrings, strict, autoCloseStreams, unbuffered;
final int debugOutputLines;
final String consumes;
final Class extends ParserListener> listener;
/** General parser properties currently set on this parser. */
private final MediaType[] consumesArray;
/**
* Constructor.
*
* @param builder The builder this object.
*/
protected Parser(Builder builder) {
super(builder);
consumes = builder.consumes;
trimStrings = builder.trimStrings;
strict = builder.strict;
autoCloseStreams = builder.autoCloseStreams;
debugOutputLines = builder.debugOutputLines;
unbuffered = builder.unbuffered;
listener = builder.listener;
String[] _consumes = split(consumes != null ? consumes : "");
this.consumesArray = new MediaType[_consumes.length];
for (int i = 0; i < _consumes.length; i++) {
this.consumesArray[i] = MediaType.of(_consumes[i]);
}
}
@Override /* Context */
public Builder copy() {
return new Builder(this);
}
//-----------------------------------------------------------------------------------------------------------------
// Abstract methods
//-----------------------------------------------------------------------------------------------------------------
/**
* Returns true if this parser subclasses from {@link ReaderParser}.
*
* @return true if this parser subclasses from {@link ReaderParser}.
*/
public boolean isReaderParser() {
return true;
}
//-----------------------------------------------------------------------------------------------------------------
// Other methods
//-----------------------------------------------------------------------------------------------------------------
/**
* Parses input into the specified object type.
*
*
* The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
*
*
Examples:
*
* ReaderParser parser = JsonParser.DEFAULT ;
*
* // Parse into a linked-list of strings.
* List list1 = parser .parse(json , LinkedList.class , String.class );
*
* // Parse into a linked-list of beans.
* List list2 = parser .parse(json , LinkedList.class , MyBean.class );
*
* // Parse into a linked-list of linked-lists of strings.
* List list3 = parser .parse(json , LinkedList.class , LinkedList.class , String.class );
*
* // Parse into a map of string keys/values.
* Map map1 = parser .parse(json , TreeMap.class , String.class , String.class );
*
* // Parse into a map containing string keys and values of lists containing beans.
* Map map2 = parser .parse(json , TreeMap.class , String.class , List.class , MyBean.class );
*
*
*
* Collection classes are assumed to be followed by zero or one objects indicating the element type.
*
*
* Map classes are assumed to be followed by zero or two meta objects indicating the key and value types.
*
*
* The array can be arbitrarily long to indicate arbitrarily complex data structures.
*
*
Notes:
* -
* Use the {@link #parse(Object, Class)} method instead if you don't need a parameterized map/collection.
*
*
* @param The class type of the object to create.
* @param input
* The input.
*
Character-based parsers can handle the following input class types:
*
* null
* - {@link Reader}
*
- {@link CharSequence}
*
- {@link InputStream} containing UTF-8 encoded text (or charset defined by
* {@link ReaderParser.Builder#streamCharset(Charset)} property value).
*
byte []
containing UTF-8 encoded text (or charset defined by
* {@link ReaderParser.Builder#streamCharset(Charset)} property value).
* - {@link File} containing system encoded text (or charset defined by
* {@link ReaderParser.Builder#fileCharset(Charset)} property value).
*
*
Stream-based parsers can handle the following input class types:
*
* null
* - {@link InputStream}
*
byte []
* - {@link File}
*
- {@link CharSequence} containing encoded bytes according to the {@link InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting.
*
* @param type
* The object type to create.
*
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
* @param args
* The type arguments of the class if it's a collection or map.
*
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
*
Ignored if the main type is not a map or collection.
* @return The parsed object.
* @throws ParseException Malformed input encountered.
* @throws IOException Thrown by underlying stream.
* @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
*/
public final T parse(Object input, Type type, Type...args) throws ParseException, IOException {
return getSession().parse(input, type, args);
}
/**
* Same as {@link #parse(Object, Type, Type...)} but since it's a {@link String} input doesn't throw an {@link IOException}.
*
* @param The class type of the object being created.
* @param input
* The input.
* See {@link #parse(Object, Type, Type...)} for details.
* @param type
* The object type to create.
*
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
* @param args
* The type arguments of the class if it's a collection or map.
*
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
*
Ignored if the main type is not a map or collection.
* @return The parsed object.
* @throws ParseException Malformed input encountered.
*/
public final T parse(String input, Type type, Type...args) throws ParseException {
return getSession().parse(input, type, args);
}
/**
* Same as {@link #parse(Object, Type, Type...)} except optimized for a non-parameterized class.
*
*
* This is the preferred parse method for simple types since you don't need to cast the results.
*
*
Examples:
*
* ReaderParser parser = JsonParser.DEFAULT ;
*
* // Parse into a string.
* String string = parser .parse(json , String.class );
*
* // Parse into a bean.
* MyBean bean = parser .parse(json , MyBean.class );
*
* // Parse into a bean array.
* MyBean[] beanArray = parser .parse(json , MyBean[].class );
*
* // Parse into a linked-list of objects.
* List list = parser .parse(json , LinkedList.class );
*
* // Parse into a map of object keys/values.
* Map map = parser .parse(json , TreeMap.class );
*
*
* @param The class type of the object being created.
* @param input
* The input.
* See {@link #parse(Object, Type, Type...)} for details.
* @param type The object type to create.
* @return The parsed object.
* @throws ParseException Malformed input encountered.
* @throws IOException Thrown by the underlying stream.
*/
public final T parse(Object input, Class type) throws ParseException, IOException {
return getSession().parse(input, type);
}
/**
* Same as {@link #parse(Object, Class)} but since it's a {@link String} input doesn't throw an {@link IOException}.
*
* @param The class type of the object being created.
* @param input
* The input.
* See {@link #parse(Object, Type, Type...)} for details.
* @param type The object type to create.
* @return The parsed object.
* @throws ParseException Malformed input encountered.
*/
public final T parse(String input, Class type) throws ParseException {
return getSession().parse(input, type);
}
/**
* Same as {@link #parse(Object, Type, Type...)} except the type has already been converted into a {@link ClassMeta}
* object.
*
*
* This is mostly an internal method used by the framework.
*
* @param The class type of the object being created.
* @param input
* The input.
* See {@link #parse(Object, Type, Type...)} for details.
* @param type The object type to create.
* @return The parsed object.
* @throws ParseException Malformed input encountered.
* @throws IOException Thrown by the underlying stream.
*/
public final T parse(Object input, ClassMeta type) throws ParseException, IOException {
return getSession().parse(input, type);
}
/**
* Same as {@link #parse(Object, ClassMeta)} but since it's a {@link String} input doesn't throw an {@link IOException}.
*
* @param The class type of the object being created.
* @param input
* The input.
* See {@link #parse(Object, Type, Type...)} for details.
* @param type The object type to create.
* @return The parsed object.
* @throws ParseException Malformed input encountered.
*/
public final T parse(String input, ClassMeta type) throws ParseException {
return getSession().parse(input, type);
}
@Override /* Context */
public ParserSession.Builder createSession() {
return ParserSession.create(this);
}
@Override /* Context */
public ParserSession getSession() {
return createSession().build();
}
/**
* Workhorse method.
*
*
* Subclasses are expected to either implement this method or {@link ParserSession#doParse(ParserPipe, ClassMeta)}.
*
* @param session The current session.
* @param pipe Where to get the input from.
* @param type
* The class type of the object to create.
* If null or Object.class
, object type is based on what's being parsed.
* For example, when parsing JSON text, it may return a String , Number ,
* JsonMap , etc...
* @param The class type of the object to create.
* @return The parsed object.
* @throws IOException Thrown by underlying stream.
* @throws ParseException Malformed input encountered.
* @throws ExecutableException Exception occurred on invoked constructor/method/field.
*/
public T doParse(ParserSession session, ParserPipe pipe, ClassMeta type) throws IOException, ParseException {
throw new UnsupportedOperationException();
}
//-----------------------------------------------------------------------------------------------------------------
// Optional methods
//-----------------------------------------------------------------------------------------------------------------
/**
* Parses the contents of the specified reader and loads the results into the specified map.
*
*
* Reader must contain something that serializes to a map (such as text containing a JSON object).
*
*
* Used in the following locations:
*
* -
* The various character-based constructors in {@link JsonMap} (e.g.
* {@link JsonMap#JsonMap(CharSequence,Parser)}).
*
*
* @param The key class type.
* @param The value class type.
* @param input The input. See {@link #parse(Object, ClassMeta)} for supported input types.
* @param m The map being loaded.
* @param keyType The class type of the keys, or null to default to String.class
.
* @param valueType The class type of the values, or null to default to whatever is being parsed.
* @return The same map that was passed in to allow this method to be chained.
* @throws ParseException Malformed input encountered.
* @throws UnsupportedOperationException If not implemented.
*/
public final Map parseIntoMap(Object input, Map m, Type keyType, Type valueType) throws ParseException {
return getSession().parseIntoMap(input, m, keyType, valueType);
}
/**
* Parses the contents of the specified reader and loads the results into the specified collection.
*
*
* Used in the following locations:
*
* -
* The various character-based constructors in {@link JsonList} (e.g.
* {@link JsonList#JsonList(CharSequence,Parser)}.
*
*
* @param The element class type.
* @param input The input. See {@link #parse(Object, ClassMeta)} for supported input types.
* @param c The collection being loaded.
* @param elementType The class type of the elements, or null to default to whatever is being parsed.
* @return The same collection that was passed in to allow this method to be chained.
* @throws ParseException Malformed input encountered.
* @throws UnsupportedOperationException If not implemented.
*/
public final Collection parseIntoCollection(Object input, Collection c, Type elementType) throws ParseException {
return getSession().parseIntoCollection(input, c, elementType);
}
/**
* Parses the specified array input with each entry in the object defined by the {@code argTypes}
* argument.
*
*
* Used for converting arrays (e.g. "[arg1,arg2,...]" ) into an {@code Object[]} that can be passed
* to the {@code Method.invoke(target, args)} method.
*
*
* Used in the following locations:
*
* -
* Used to parse argument strings in the {@link ObjectIntrospector#invokeMethod(Method, Reader)} method.
*
*
* @param input The input. Subclasses can support different input types.
* @param argTypes Specifies the type of objects to create for each entry in the array.
* @return An array of parsed objects.
* @throws ParseException Malformed input encountered.
*/
public final Object[] parseArgs(Object input, Type[] argTypes) throws ParseException {
if (argTypes == null || argTypes.length == 0)
return new Object[0];
return getSession().parseArgs(input, argTypes);
}
//-----------------------------------------------------------------------------------------------------------------
// Other methods
//-----------------------------------------------------------------------------------------------------------------
/**
* Returns the media types handled based on the values passed to the consumes constructor parameter.
*
* @return The list of media types. Never null .
*/
public final List getMediaTypes() {
return ulist(consumesArray);
}
/**
* Returns the first media type handled based on the values passed to the consumes constructor parameter.
*
* @return The media type.
*/
public final MediaType getPrimaryMediaType() {
return consumesArray == null || consumesArray.length == 0 ? null : consumesArray[0];
}
/**
* Returns true if this parser can handle the specified content type.
*
* @param contentType The content type to test.
* @return true if this parser can handle the specified content type.
*/
public boolean canHandle(String contentType) {
if (contentType != null)
for (MediaType mt : getMediaTypes())
if (contentType.equals(mt.toString()))
return true;
return false;
}
//-----------------------------------------------------------------------------------------------------------------
// Properties
//-----------------------------------------------------------------------------------------------------------------
/**
* Auto-close streams.
*
* @see Parser.Builder#autoCloseStreams()
* @return
* true if InputStreams and Readers passed into parsers will be closed
* after parsing is complete.
*/
protected final boolean isAutoCloseStreams() {
return autoCloseStreams;
}
/**
* Debug output lines.
*
* @see Parser.Builder#debugOutputLines(int)
* @return
* The number of lines of input before and after the error location to be printed as part of the exception message.
*/
protected final int getDebugOutputLines() {
return debugOutputLines;
}
/**
* Parser listener.
*
* @see Parser.Builder#listener(Class)
* @return
* Class used to listen for errors and warnings that occur during parsing.
*/
protected final Class extends ParserListener> getListener() {
return listener;
}
/**
* Strict mode.
*
* @see Parser.Builder#strict()
* @return
* true if strict mode for the parser is enabled.
*/
protected final boolean isStrict() {
return strict;
}
/**
* Trim parsed strings.
*
* @see Parser.Builder#trimStrings()
* @return
* true if string values will be trimmed of whitespace using {@link String#trim()} before being added to
* the POJO.
*/
protected final boolean isTrimStrings() {
return trimStrings;
}
/**
* Unbuffered.
*
* @see Parser.Builder#unbuffered()
* @return
* true if parsers don't use internal buffering during parsing.
*/
protected final boolean isUnbuffered() {
return unbuffered;
}
//-----------------------------------------------------------------------------------------------------------------
// Other methods
//-----------------------------------------------------------------------------------------------------------------
@Override /* Context */
protected JsonMap properties() {
return filteredMap()
.append("autoCloseStreams", autoCloseStreams)
.append("debugOutputLines", debugOutputLines)
.append("listener", listener)
.append("strict", strict)
.append("trimStrings", trimStrings)
.append("unbuffered", unbuffered);
}
}