// ***************************************************************************************************************************
// * 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.uon;

import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.uon.UonParser.*;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.transform.*;

/**
 * Session object that lives for the duration of a single use of {@link UonParser}.
 *
 * <p>
 * This class is NOT thread safe.
 * It is typically discarded after one-time use although it can be reused against multiple inputs.
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class UonParserSession extends ReaderParserSession implements HttpPartParserSession {

	// Characters that need to be preceded with an escape character.
	private static final AsciiSet escapedChars = AsciiSet.create("~'\u0001\u0002");

	private static final char AMP='\u0001', EQ='\u0002';  // Flags set in reader to denote & and = characters.

	private final UonParser ctx;
	private final boolean decoding;

	/**
	 * Create a new session using properties specified in the context.
	 *
	 * @param ctx
	 * 	The context creating this session object.
	 * 	The context contains all the configuration settings for this object.
	 * @param args
	 * 	Runtime session arguments.
	 */
	protected UonParserSession(UonParser ctx, ParserSessionArgs args) {
		super(ctx, args);
		this.ctx = ctx;
		decoding = getProperty(UON_decoding, boolean.class, ctx.isDecoding());
	}

	/**
	 * Create a specialized parser session for parsing URL parameters.
	 *
	 * <p>
	 * The main difference is that characters are never decoded, and the {@link UonParser#UON_decoding}
	 * property is always ignored.
	 *
	 * @param ctx
	 * 	The context creating this session object.
	 * 	The context contains all the configuration settings for this object.
	 * @param args
	 * 	Runtime session arguments.
	 * @param decoding
	 * 	Whether to decode characters.
	 */
	protected UonParserSession(UonParser ctx, ParserSessionArgs args, boolean decoding) {
		super(ctx, args);
		this.ctx = ctx;
		this.decoding = decoding;
	}

	@Override /* ParserSession */
	protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {
		try (UonReader r = getUonReader(pipe, decoding)) {
			T o = parseAnything(type, r, getOuter(), true, null);
			validateEnd(r);
			return o;
		}
	}

	@Override /* ReaderParserSession */
	protected <K,V> Map<K,V> doParseIntoMap(ParserPipe pipe, Map<K,V> m, Type keyType, Type valueType) throws Exception {
		try (UonReader r = getUonReader(pipe, decoding)) {
			m = parseIntoMap(r, m, (ClassMeta<K>)getClassMeta(keyType), (ClassMeta<V>)getClassMeta(valueType), null);
			validateEnd(r);
			return m;
		}
	}

	@Override /* ReaderParserSession */
	protected <E> Collection<E> doParseIntoCollection(ParserPipe pipe, Collection<E> c, Type elementType) throws Exception {
		try (UonReader r = getUonReader(pipe, decoding)) {
			c = parseIntoCollection(r, c, (ClassMeta<E>)getClassMeta(elementType), false, null);
			validateEnd(r);
			return c;
		}
	}

	@Override /* HttpPartParser */
	public <T> T parse(HttpPartType partType, HttpPartSchema schema, String in, ClassMeta<T> toType) throws ParseException, SchemaValidationException {
		if (in == null)
			return null;
		if (toType.isString() && in.length() > 0) {
			// Shortcut - If we're returning a string and the value doesn't start with "'" or is "null", then
			// just return the string since it's a plain value.
			// This allows us to bypass the creation of a UonParserSession object.
			char x = firstNonWhitespaceChar(in);
			if (x != '\'' && x != 'n' && in.indexOf('~') == -1)
				return (T)in;
			if (x == 'n' && "null".equals(in))
				return null;
		}
		try (ParserPipe pipe = createPipe(in)) {
			try (UonReader r = getUonReader(pipe, false)) {
				return parseAnything(toType, r, null, true, null);
			}
		} catch (ParseException e) {
			throw e;
		} catch (Exception e) {
			throw new ParseException(e);
		}
	}

	@Override /* HttpPartParserSession */
	public <T> T parse(HttpPartType partType, HttpPartSchema schema, String in, Class<T> toType) throws ParseException, SchemaValidationException {
		return parse(null, schema, in, getClassMeta(toType));
	}

	@Override /* HttpPartParserSession */
	public <T> T parse(HttpPartType partType, HttpPartSchema schema, String in, Type toType, Type...toTypeArgs) throws ParseException, SchemaValidationException {
		return (T)parse(null, schema, in, getClassMeta(toType, toTypeArgs));
	}

	@Override /* HttpPartParserSession */
	public <T> T parse(HttpPartSchema schema, String in, Class<T> toType) throws ParseException, SchemaValidationException {
		return parse(null, schema, in, getClassMeta(toType));
	}

	@Override /* HttpPartParserSession */
	public <T> T parse(HttpPartSchema schema, String in, ClassMeta<T> toType) throws ParseException, SchemaValidationException {
		return parse(null, schema, in, toType);
	}

	@Override /* HttpPartParserSession */
	public <T> T parse(HttpPartSchema schema, String in, Type toType, Type...toTypeArgs) throws ParseException, SchemaValidationException {
		return (T)parse(null, schema, in, getClassMeta(toType, toTypeArgs));
	}

	/**
	 * Workhorse method.
	 *
	 * @param <T> The class type being parsed, or <jk>null</jk> if unknown.
	 * @param eType The class type being parsed, or <jk>null</jk> if unknown.
	 * @param r The reader being parsed.
	 * @param outer The outer object (for constructing nested inner classes).
	 * @param isUrlParamValue
	 * 	If <jk>true</jk>, then we're parsing a top-level URL-encoded value which is treated a bit different than the
	 * 	default case.
	 * @param pMeta The current bean property being parsed.
	 * @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> T parseAnything(ClassMeta<?> eType, UonReader r, Object outer, boolean isUrlParamValue, BeanPropertyMeta pMeta) throws IOException, ParseException, ExecutableException {

		if (eType == null)
			eType = object();
		PojoSwap<T,Object> swap = (PojoSwap<T,Object>)eType.getPojoSwap(this);
		BuilderSwap<T,Object> builder = (BuilderSwap<T,Object>)eType.getBuilderSwap(this);
		ClassMeta<?> sType = null;
		if (builder != null)
			sType = builder.getBuilderClassMeta(this);
		else if (swap != null)
			sType = swap.getSwapClassMeta(this);
		else
			sType = eType;
		
		if (sType.isOptional()) 
			return (T)Optional.ofNullable(parseAnything(eType.getElementType(), r, outer, isUrlParamValue, pMeta));
		
		setCurrentClass(sType);

		Object o = null;

		int c = r.peekSkipWs();

		if (c == -1 || c == AMP) {
			// If parameter is blank and it's an array or collection, return an empty list.
			if (sType.isCollectionOrArray())
				o = sType.newInstance();
			else if (sType.isString() || sType.isObject())
				o = "";
			else if (sType.isPrimitive())
				o = sType.getPrimitiveDefault();
			// Otherwise, leave null.
		} else if (sType.isVoid()) {
			String s = parseString(r, isUrlParamValue);
			if (s != null)
				throw new ParseException(this, "Expected ''null'' for void value, but was ''{0}''.", s);
		} else if (sType.isObject()) {
			if (c == '(') {
				ObjectMap m = new ObjectMap(this);
				parseIntoMap(r, m, string(), object(), pMeta);
				o = cast(m, pMeta, eType);
			} else if (c == '@') {
				Collection l = new ObjectList(this);
				o = parseIntoCollection(r, l, sType, isUrlParamValue, pMeta);
			} else {
				String s = parseString(r, isUrlParamValue);
				if (c != '\'') {
					if ("true".equals(s) || "false".equals(s))
						o = Boolean.valueOf(s);
					else if (! "null".equals(s)) {
						if (isNumeric(s))
							o = StringUtils.parseNumber(s, Number.class);
						else
							o = s;
					}
				} else {
					o = s;
				}
			}
		} else if (sType.isBoolean()) {
			o = parseBoolean(r);
		} else if (sType.isCharSequence()) {
			o = parseString(r, isUrlParamValue);
		} else if (sType.isChar()) {
			o = parseCharacter(parseString(r, isUrlParamValue));
		} else if (sType.isNumber()) {
			o = parseNumber(r, (Class<? extends Number>)sType.getInnerClass());
		} else if (sType.isMap()) {
			Map m = (sType.canCreateNewInstance(outer) ? (Map)sType.newInstance(outer) : new ObjectMap(this));
			o = parseIntoMap(r, m, sType.getKeyType(), sType.getValueType(), pMeta);
		} else if (sType.isCollection()) {
			if (c == '(') {
				ObjectMap m = new ObjectMap(this);
				parseIntoMap(r, m, string(), object(), pMeta);
				// Handle case where it's a collection, but serialized as a map with a _type or _value key.
				if (m.containsKey(getBeanTypePropertyName(sType)))
					o = cast(m, pMeta, eType);
				// Handle case where it's a collection, but only a single value was specified.
				else {
					Collection l = (
						sType.canCreateNewInstance(outer)
						? (Collection)sType.newInstance(outer)
						: new ObjectList(this)
					);
					l.add(m.cast(sType.getElementType()));
					o = l;
				}
			} else {
				Collection l = (
					sType.canCreateNewInstance(outer)
					? (Collection)sType.newInstance(outer)
					: new ObjectList(this)
				);
				o = parseIntoCollection(r, l, sType, isUrlParamValue, pMeta);
			}
		} else if (builder != null) {
			BeanMap m = toBeanMap(builder.create(this, eType));
			m = parseIntoBeanMap(r, m);
			o = m == null ? null : builder.build(this, m.getBean(), eType);
		} else if (sType.canCreateNewBean(outer)) {
			BeanMap m = newBeanMap(outer, sType.getInnerClass());
			m = parseIntoBeanMap(r, m);
			o = m == null ? null : m.getBean();
		} else if (sType.canCreateNewInstanceFromString(outer)) {
			String s = parseString(r, isUrlParamValue);
			if (s != null)
				o = sType.newInstanceFromString(outer, s);
		} else if (sType.isArray() || sType.isArgs()) {
			if (c == '(') {
				ObjectMap m = new ObjectMap(this);
				parseIntoMap(r, m, string(), object(), pMeta);
				// Handle case where it's an array, but serialized as a map with a _type or _value key.
				if (m.containsKey(getBeanTypePropertyName(sType)))
					o = cast(m, pMeta, eType);
				// Handle case where it's an array, but only a single value was specified.
				else {
					ArrayList l = new ArrayList(1);
					l.add(m.cast(sType.getElementType()));
					o = toArray(sType, l);
				}
			} else {
				ArrayList l = (ArrayList)parseIntoCollection(r, new ArrayList(), sType, isUrlParamValue, pMeta);
				o = toArray(sType, l);
			}
		} else if (c == '(') {
			// It could be a non-bean with _type attribute.
			ObjectMap m = new ObjectMap(this);
			parseIntoMap(r, m, string(), object(), pMeta);
			if (m.containsKey(getBeanTypePropertyName(sType)))
				o = cast(m, pMeta, eType);
			else
				throw new ParseException(this, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''",
					sType.getInnerClass().getName(), sType.getNotABeanReason());
		} else if (c == 'n') {
			r.read();
			parseNull(r);
		} else {
			throw new ParseException(this, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''",
				sType.getInnerClass().getName(), sType.getNotABeanReason());
		}

		if (o == null && sType.isPrimitive())
			o = sType.getPrimitiveDefault();
		if (swap != null && o != null)
			o = unswap(swap, o, eType);

		if (outer != null)
			setParent(eType, o, outer);

		return (T)o;
	}

	private <K,V> Map<K,V> parseIntoMap(UonReader r, Map<K,V> m, ClassMeta<K> keyType, ClassMeta<V> valueType,
			BeanPropertyMeta pMeta) throws IOException, ParseException, ExecutableException {

		if (keyType == null)
			keyType = (ClassMeta<K>)string();

		int c = r.read();
		if (c == -1 || c == AMP)
			return null;
		if (c == 'n')
			return (Map<K,V>)parseNull(r);
		if (c != '(')
			throw new ParseException(this, "Expected '(' at beginning of object.");

		final int S1=1; // Looking for attrName start.
		final int S2=2; // Found attrName end, looking for =.
		final int S3=3; // Found =, looking for valStart.
		final int S4=4; // Looking for , or )
		boolean isInEscape = false;

		int state = S1;
		K currAttr = null;
		while (c != -1 && c != AMP) {
			c = r.read();
			if (! isInEscape) {
				if (state == S1) {
					if (c == ')')
						return m;
					if (Character.isWhitespace(c))
						skipSpace(r);
					else {
						r.unread();
						Object attr = parseAttr(r, decoding);
						currAttr = attr == null ? null : convertAttrToType(m, trim(attr.toString()), keyType);
						state = S2;
						c = 0; // Avoid isInEscape if c was '\'
					}
				} else if (state == S2) {
					if (c == EQ || c == '=')
						state = S3;
					else if (c == -1 || c == ',' || c == ')' || c == AMP) {
						if (currAttr == null) {
							// Value was '%00'
							r.unread();
							return null;
						}
						m.put(currAttr, null);
						if (c == ')' || c == -1 || c == AMP)
							return m;
						state = S1;
					}
				} else if (state == S3) {
					if (c == -1 || c == ',' || c == ')' || c == AMP) {
						V value = convertAttrToType(m, "", valueType);
						m.put(currAttr, value);
						if (c == -1 || c == ')' || c == AMP)
							return m;
						state = S1;
					} else  {
						V value = parseAnything(valueType, r.unread(), m, false, pMeta);
						setName(valueType, value, currAttr);
						m.put(currAttr, value);
						state = S4;
						c = 0; // Avoid isInEscape if c was '\'
					}
				} else if (state == S4) {
					if (c == ',')
						state = S1;
					else if (c == ')' || c == -1 || c == AMP) {
						return m;
					}
				}
			}
			isInEscape = isInEscape(c, r, isInEscape);
		}
		if (state == S1)
			throw new ParseException(this, "Could not find attribute name on object.");
		if (state == S2)
			throw new ParseException(this, "Could not find '=' following attribute name on object.");
		if (state == S3)
			throw new ParseException(this, "Dangling '=' found in object entry");
		if (state == S4)
			throw new ParseException(this, "Could not find ')' marking end of object.");

		return null; // Unreachable.
	}

	private <E> Collection<E> parseIntoCollection(UonReader r, Collection<E> l, ClassMeta<E> type, boolean isUrlParamValue, BeanPropertyMeta pMeta) throws IOException, ParseException, ExecutableException {

		int c = r.readSkipWs();
		if (c == -1 || c == AMP)
			return null;
		if (c == 'n')
			return (Collection<E>)parseNull(r);

		int argIndex = 0;

		// If we're parsing a top-level parameter, we're allowed to have comma-delimited lists outside parenthesis (e.g. "&foo=1,2,3&bar=a,b,c")
		// This is not allowed at lower levels since we use comma's as end delimiters.
		boolean isInParens = (c == '@');
		if (! isInParens) {
			if (isUrlParamValue)
				r.unread();
			else
				throw new ParseException(this, "Could not find '(' marking beginning of collection.");
		} else {
			r.read();
		}

		if (isInParens) {
			final int S1=1; // Looking for starting of first entry.
			final int S2=2; // Looking for starting of subsequent entries.
			final int S3=3; // Looking for , or ) after first entry.

			int state = S1;
			while (c != -1 && c != AMP) {
				c = r.read();
				if (state == S1 || state == S2) {
					if (c == ')') {
						if (state == S2) {
							l.add((E)parseAnything(type.isArgs() ? type.getArg(argIndex++) : type.getElementType(),
									r.unread(), l, false, pMeta));
							r.read();
						}
						return l;
					} else if (Character.isWhitespace(c)) {
						skipSpace(r);
					} else {
						l.add((E)parseAnything(type.isArgs() ? type.getArg(argIndex++) : type.getElementType(),
								r.unread(), l, false, pMeta));
						state = S3;
					}
				} else if (state == S3) {
					if (c == ',') {
						state = S2;
					} else if (c == ')') {
						return l;
					}
				}
			}
			if (state == S1 || state == S2)
				throw new ParseException(this, "Could not find start of entry in array.");
			if (state == S3)
				throw new ParseException(this, "Could not find end of entry in array.");

		} else {
			final int S1=1; // Looking for starting of entry.
			final int S2=2; // Looking for , or & or END after first entry.

			int state = S1;
			while (c != -1 && c != AMP) {
				c = r.read();
				if (state == S1) {
					if (Character.isWhitespace(c)) {
						skipSpace(r);
					} else {
						l.add((E)parseAnything(type.isArgs() ? type.getArg(argIndex++) : type.getElementType(),
								r.unread(), l, false, pMeta));
						state = S2;
					}
				} else if (state == S2) {
					if (c == ',') {
						state = S1;
					} else if (Character.isWhitespace(c)) {
						skipSpace(r);
					} else if (c == AMP || c == -1) {
						r.unread();
						return l;
					}
				}
			}
		}

		return null;  // Unreachable.
	}

	private <T> BeanMap<T> parseIntoBeanMap(UonReader r, BeanMap<T> m) throws IOException, ParseException, ExecutableException {

		int c = r.readSkipWs();
		if (c == -1 || c == AMP)
			return null;
		if (c == 'n')
			return (BeanMap<T>)parseNull(r);
		if (c != '(')
			throw new ParseException(this, "Expected '(' at beginning of object.");

		final int S1=1; // Looking for attrName start.
		final int S2=2; // Found attrName end, looking for =.
		final int S3=3; // Found =, looking for valStart.
		final int S4=4; // Looking for , or }
		boolean isInEscape = false;

		int state = S1;
		String currAttr = "";
		mark();
		try {
			while (c != -1 && c != AMP) {
				c = r.read();
				if (! isInEscape) {
					if (state == S1) {
						if (c == ')' || c == -1 || c == AMP) {
							return m;
						}
						if (Character.isWhitespace(c))
							skipSpace(r);
						else {
							r.unread();
							mark();
							currAttr = parseAttrName(r, decoding);
							if (currAttr == null) { // Value was '%00'
								return null;
							}
							state = S2;
						}
					} else if (state == S2) {
						if (c == EQ || c == '=')
							state = S3;
						else if (c == -1 || c == ',' || c == ')' || c == AMP) {
							m.put(currAttr, null);
							if (c == ')' || c == -1 || c == AMP) {
								return m;
							}
							state = S1;
						}
					} else if (state == S3) {
						if (c == -1 || c == ',' || c == ')' || c == AMP) {
							if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) {
								BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
								if (pMeta == null) {
									onUnknownProperty(currAttr, m);
									unmark();
								} else {
									unmark();
									Object value = convertToType("", pMeta.getClassMeta());
									pMeta.set(m, currAttr, value);
								}
							}
							if (c == -1 || c == ')' || c == AMP)
								return m;
							state = S1;
						} else {
							if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) {
								BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
								if (pMeta == null) {
									onUnknownProperty(currAttr, m);
									unmark();
									parseAnything(object(), r.unread(), m.getBean(false), false, null); // Read content anyway to ignore it
								} else {
									unmark();
									setCurrentProperty(pMeta);
									ClassMeta<?> cm = pMeta.getClassMeta();
									Object value = parseAnything(cm, r.unread(), m.getBean(false), false, pMeta);
									setName(cm, value, currAttr);
									pMeta.set(m, currAttr, value);
									setCurrentProperty(null);
								}
							}
							state = S4;
						}
					} else if (state == S4) {
						if (c == ',')
							state = S1;
						else if (c == ')' || c == -1 || c == AMP) {
							return m;
						}
					}
				}
				isInEscape = isInEscape(c, r, isInEscape);
			}
			if (state == S1)
				throw new ParseException(this, "Could not find attribute name on object.");
			if (state == S2)
				throw new ParseException(this, "Could not find '=' following attribute name on object.");
			if (state == S3)
				throw new ParseException(this, "Could not find value following '=' on object.");
			if (state == S4)
				throw new ParseException(this, "Could not find ')' marking end of object.");
		} finally {
			unmark();
		}

		return null; // Unreachable.
	}

	private Object parseNull(UonReader r) throws IOException, ParseException {
		String s = parseString(r, false);
		if ("ull".equals(s))
			return null;
		throw new ParseException(this, "Unexpected character sequence: ''{0}''", s);
	}

	/**
	 * Convenience method for parsing an attribute from the specified parser.
	 *
	 * @param r The reader.
	 * @param encoded Whether the attribute is encoded.
	 * @return The parsed object
	 * @throws IOException Exception thrown by underlying stream.
	 * @throws ParseException Attribute was malformed.
	 */
	protected final Object parseAttr(UonReader r, boolean encoded) throws IOException, ParseException {
		Object attr;
		attr = parseAttrName(r, encoded);
		return attr;
	}

	/**
	 * Parses an attribute name from the specified reader.
	 *
	 * @param r The reader.
	 * @param encoded Whether the attribute is encoded.
	 * @return The parsed attribute name.
	 * @throws IOException Exception thrown by underlying stream.
	 * @throws ParseException Attribute name was malformed.
	 */
	protected final String parseAttrName(UonReader r, boolean encoded) throws IOException, ParseException {

		// If string is of form 'xxx', we're looking for ' at the end.
		// Otherwise, we're looking for '&' or '=' or WS or -1 denoting the end of this string.

		int c = r.peekSkipWs();
		if (c == '\'')
			return parsePString(r);

		r.mark();
		boolean isInEscape = false;
		if (encoded) {
			while (c != -1) {
				c = r.read();
				if (! isInEscape) {
					if (c == AMP || c == EQ || c == -1 || Character.isWhitespace(c)) {
						if (c != -1)
							r.unread();
						String s = r.getMarked();
						return ("null".equals(s) ? null : s);
					}
				}
				else if (c == AMP)
					r.replace('&');
				else if (c == EQ)
					r.replace('=');
				isInEscape = isInEscape(c, r, isInEscape);
			}
		} else {
			while (c != -1) {
				c = r.read();
				if (! isInEscape) {
					if (c == '=' || c == -1 || Character.isWhitespace(c)) {
						if (c != -1)
							r.unread();
						String s = r.getMarked();
						return ("null".equals(s) ? null : trim(s));
					}
				}
				isInEscape = isInEscape(c, r, isInEscape);
			}
		}

		// We should never get here.
		throw new ParseException(this, "Unexpected condition.");
	}


	/*
	 * Returns true if the next character in the stream is preceded by an escape '~' character.
	 */
	private static final boolean isInEscape(int c, ParserReader r, boolean prevIsInEscape) throws IOException {
		if (c == '~' && ! prevIsInEscape) {
			c = r.peek();
			if (escapedChars.contains(c)) {
				r.delete();
				return true;
			}
		}
		return false;
	}

	/**
	 * Parses a string value from the specified reader.
	 *
	 * @param r The input reader.
	 * @param isUrlParamValue Whether this is a URL parameter.
	 * @return The parsed string.
	 * @throws IOException Exception thrown by underlying stream.
	 * @throws ParseException Malformed input found.
	 */
	protected final String parseString(UonReader r, boolean isUrlParamValue) throws IOException, ParseException {

		// If string is of form 'xxx', we're looking for ' at the end.
		// Otherwise, we're looking for ',' or ')' or -1 denoting the end of this string.

		int c = r.peekSkipWs();
		if (c == '\'')
			return parsePString(r);

		r.mark();
		boolean isInEscape = false;
		String s = null;
		AsciiSet endChars = (isUrlParamValue ? endCharsParam : endCharsNormal);
		while (c != -1) {
			c = r.read();
			if (! isInEscape) {
				// If this is a URL parameter value, we're looking for:  &
				// If not, we're looking for:  &,)
				if (endChars.contains(c)) {
					r.unread();
					c = -1;
				}
			}
			if (c == -1)
				s = r.getMarked();
			else if (c == EQ)
				r.replace('=');
			else if (Character.isWhitespace(c) && ! isUrlParamValue) {
				s = r.getMarked(0, -1);
				skipSpace(r);
				c = -1;
			}
			isInEscape = isInEscape(c, r, isInEscape);
		}

		if (isUrlParamValue)
			s = StringUtils.trim(s);

		return ("null".equals(s) ? null : trim(s));
	}

	private static final AsciiSet endCharsParam = AsciiSet.create(""+AMP), endCharsNormal = AsciiSet.create(",)"+AMP);


	/*
	 * Parses a string of the form "'foo'"
	 * All whitespace within parenthesis are preserved.
	 */
	private String parsePString(UonReader r) throws IOException, ParseException {

		r.read(); // Skip first quote.
		r.mark();
		int c = 0;

		boolean isInEscape = false;
		while (c != -1) {
			c = r.read();
			if (! isInEscape) {
				if (c == '\'')
					return trim(r.getMarked(0, -1));
			}
			if (c == EQ)
				r.replace('=');
			isInEscape = isInEscape(c, r, isInEscape);
		}
		throw new ParseException(this, "Unmatched parenthesis");
	}

	private Boolean parseBoolean(UonReader r) throws IOException, ParseException {
		String s = parseString(r, false);
		if (s == null || s.equals("null"))
			return null;
		if (s.equalsIgnoreCase("true"))
			return true;
		if (s.equalsIgnoreCase("false"))
			return false;
		throw new ParseException(this, "Unrecognized syntax for boolean.  ''{0}''.", s);
	}

	private Number parseNumber(UonReader r, Class<? extends Number> c) throws IOException, ParseException {
		String s = parseString(r, false);
		if (s == null)
			return null;
		return StringUtils.parseNumber(s, c);
	}

	/*
	 * Call this method after you've finished a parsing a string to make sure that if there's any
	 * remainder in the input, that it consists only of whitespace and comments.
	 */
	private void validateEnd(UonReader r) throws IOException, ParseException {
		if (! isValidateEnd())
			return;
		while (true) {
			int c = r.read();
			if (c == -1)
				return;
			if (! Character.isWhitespace(c))
				throw new ParseException(this, "Remainder after parse: ''{0}''.", (char)c);
		}
	}

	private static void skipSpace(ParserReader r) throws IOException {
		int c = 0;
		while ((c = r.read()) != -1) {
			if (c <= 2 || ! Character.isWhitespace(c)) {
				r.unread();
				return;
			}
		}
	}

	/**
	 * Creates a {@link UonReader} from the specified parser pipe.
	 *
	 * @param pipe The parser input.
	 * @param decodeChars Whether the reader should automatically decode URL-encoded characters.
	 * @return A new {@link UonReader} object.
	 * @throws IOException Thrown by underlying stream.
	 */
	public final UonReader getUonReader(ParserPipe pipe, boolean decodeChars) throws IOException {
		Reader r = pipe.getReader();
		if (r instanceof UonReader)
			return (UonReader)r;
		return new UonReader(pipe, decodeChars);
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Properties
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Configuration property: Decode <js>"%xx"</js> sequences.
	 *
	 * @see UonParser#UON_decoding
	 * @return
	 * 	<jk>true</jk> if URI encoded characters should be decoded, <jk>false</jk> if they've already been decoded
	 * 	before being passed to this parser.
	 */
	protected final boolean isDecoding() {
		return decoding;
	}

	/**
	 * Configuration property:  Validate end.
	 *
	 * @see UonParser#UON_validateEnd
	 * @return
	 * 	<jk>true</jk> if after parsing a POJO from the input, verifies that the remaining input in
	 * 	the stream consists of only comments or whitespace.
	 */
	protected final boolean isValidateEnd() {
		return ctx.isValidateEnd();
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Other methods
	//-----------------------------------------------------------------------------------------------------------------

	@Override /* Session */
	public ObjectMap toMap() {
		return super.toMap()
			.append("UonParserSession", new DefaultFilteringObjectMap()
				.append("decoding", decoding)
			);
	}
}
