// ***************************************************************************************************************************
// * 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.collections;

import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;

import org.apache.juneau.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.marshall.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.transform.*;
import org.apache.juneau.utils.*;

/**
 * Java implementation of a JSON object.
 *
 * <p>
 * An extension of {@link LinkedHashMap}, so all methods available in that class are also available to this class.
 *
 * <p>
 * Note that the use of this class is optional for generating JSON. The serializers will accept any objects that implement the
 * {@link java.util.Map} interface.  But this class provides some useful additional functionality when working with
 * JSON models constructed from Java Collections Framework objects.  For example, a constructor is provided for
 * converting a JSON object string directly into a {@link Map}.  It also contains accessor methods for to avoid common
 * typecasting when accessing elements in a list.
 *
 * <h5 class='section'>Example:</h5>
 * <p class='bcode w800'>
 * 	<jc>// Construct an empty Map</jc>
 * 	OMap m = OMap.<jsm>of</jsm>();
 *
 * 	<jc>// Construct a Map from JSON</jc>
 * 	m = OMap.<jsm>ofJson</jsm>(<js>"{a:'A',b:{c:'C',d:123}}"</js>);
 *
 * 	<jc>// Construct a Map using the append method</jc>
 * 	m = OMap.<jsm>of</jsm>().a(<js>"foo"</js>,<js>"x"</js>).a(<js>"bar"</js>,123).a(<js>"baz"</js>,<jk>true</jk>);
 *
 * 	<jc>// Construct a Map from XML generated by XmlSerializer</jc>
 * 	String xml = <js>"&lt;object&gt;&lt;a type='string'&gt;A&lt;/a&gt;&lt;b type='object'&gt;&lt;c type='string'&gt;C&lt;/c&gt;&lt;d type='number'&gt;123&lt;/d&gt;&lt;/b&gt;&lt;/object&gt;"</js>;
 * 	m = OMap.<jsm>of</jsm>(xml, XmlParser.<jsf>DEFAULT</jsf>);
 *
 * 	<jc>// Construct a Map from a URL GET parameter string generated by UrlEncodingParser</jc>
 * 	String urlParams = <js>"?a='A'&amp;b={c:'C',d:123}"</js>;
 * 	m = OMap.<jsm>of</jsm>(urlParams, UrlEncodingParser.<jsf>DEFAULT</jsf>);
 *
 * 	<jc>// Construct JSON from OMap</jc>
 * 	m = OMap.<jsm>ofJson</jsm>(<js>"{foo:'bar'},{baz:[123,true]}"</js>);
 * 	json = m.toString();  <jc>// Produces "{foo:'bar'},{baz:[123,true]}"</jc>
 * 	json = m.toString(JsonSerializer.<jsf>DEFAULT</jsf>);  <jc>// Equivalent</jc>
 * 	json = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(m);  <jc>// Equivalent</jc>
 *
 * 	<jc>// Get a map entry as an Integer</jc>
 * 	m = OMap.<jsm>ofJson</jsm>(<js>"{foo:123}"</js>);
 * 	Integer i = m.getInt(<js>"foo"</js>);
 * 	i = m.get(Integer.<jk>class</jk>, <js>"foo"</js>);  <jc>// Equivalent</jc>
 *
 * 	<jc>// Get a map entry as a Float</jc>
 * 	m = OMap.<jsm>ofJson</jsm>(<js>"{foo:123}"</js>);
 * 	Float f = m.getFloat(<js>"foo"</js>);
 * 	f = m.get(Float.<jk>class</jk>, <js>"foo"</js>);  <jc>// Equivalent</jc>
 *
 * 	<jc>// Same as above, except converted to a String</jc>
 * 	m = OMap.<jsm>ofJson</jsm>(<js>"{foo:123}"</js>);
 * 	String s = m.getString(<js>"foo"</js>); <jc>// Returns "123"</jc>
 * 	s = m.get(String.<jk>class</jk>, <js>"foo"</js>);  <jc>// Equivalent</jc>
 *
 * 	<jc>// Get one of the entries in the list as a bean (converted to a bean if it isn't already one)</jc>
 * 	m = OMap.<jsm>ofJson</jsm>(<js>"{person:{name:'John Smith',age:45}}"</js>);
 * 	Person p = m.get(Person.<jk>class</jk>, <js>"person"</js>);
 *
 * 	<jc>// Add an inner map</jc>
 * 	OMap m1 = OMap.<jsm>ofJson</jsm>(<js>"{a:1}"</js>);
 * 	OMap m2 = OMap.<jsm>ofJson</jsm>(<js>"{b:2}"</js>).setInner(m1);
 * 	<jk>int</jk> a = m2.getInt(<js>"a"</js>);  <jc>// a == 1 </jc>
 * </p>
 *
 * <p>
 * This class is not thread safe.
 */
public class OMap extends LinkedHashMap<String,Object> {
	private static final long serialVersionUID = 1L;

	private transient BeanSession session;
	private Map<String,Object> inner;
	private transient PojoRest pojoRest;

	/**
	 * An empty read-only OMap.
	 */
	public static final OMap EMPTY_MAP = new OMap() {

		private static final long serialVersionUID = 1L;

		@Override /* Map */
		public Set<Map.Entry<String,Object>> entrySet() {
			return Collections.<String,Object>emptyMap().entrySet();
		}

		@Override /* Map */
		public Set<String> keySet() {
			return Collections.<String,Object>emptyMap().keySet();
		}

		@Override /* Map */
		public Object put(String key, Object value) {
			throw new UnsupportedOperationException();
		}

		@Override /* Map */
		public Object remove(Object key) {
			throw new UnsupportedOperationException();
		}

		@Override /* Map */
		public Collection<Object> values() {
			return Collections.emptyMap().values();
		}
	};

	//------------------------------------------------------------------------------------------------------------------
	// Constructors.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Construct an empty map.
	 */
	public OMap() {}

	/**
	 * Construct an empty map with the specified bean context.
	 *
	 * @param session The bean session to use for creating beans.
	 */
	public OMap(BeanSession session) {
		this.session = session;
	}

	/**
	 * Construct a map initialized with the specified map.
	 *
	 * @param in
	 * 	The map to copy.
	 * 	<br>Can be <jk>null</jk>.
	 * 	<br>Keys will be converted to strings using {@link Object#toString()}.
	 */
	public OMap(Map<?,?> in) {
		this();
		if (in != null)
			for (Map.Entry<?,?> e : in.entrySet())
				put(e.getKey().toString(), e.getValue());
	}

	/**
	 * Construct a map initialized with the specified JSON.
	 *
	 * @param json
	 * 	The JSON text to parse.
	 * 	<br>Can be normal or simplified JSON.
	 * @throws ParseException Malformed input encountered.
	 */
	public OMap(CharSequence json) throws ParseException {
		this(json, JsonParser.DEFAULT);
	}

	/**
	 * Construct a map initialized with the specified string.
	 *
	 * @param in
	 * 	The input being parsed.
	 * 	<br>Can be <jk>null</jk>.
	 * @param p
	 * 	The parser to use to parse the input.
	 * 	<br>If <jk>null</jk>, uses {@link JsonParser}.
	 * @throws ParseException Malformed input encountered.
	 */
	public OMap(CharSequence in, Parser p) throws ParseException {
		this(p == null ? null : p.createBeanSession());
		if (p == null)
			p = JsonParser.DEFAULT;
		if (! StringUtils.isEmpty(in))
			p.parseIntoMap(in, this, bs().string(), bs().object());
	}

	/**
	 * Construct a map initialized with the specified reader containing JSON.
	 *
	 * @param json
	 * 	The reader containing JSON text to parse.
	 * 	<br>Can contain normal or simplified JSON.
	 * @throws ParseException Malformed input encountered.
	 */
	public OMap(Reader json) throws ParseException {
		parse(json, JsonParser.DEFAULT);
	}

	/**
	 * Construct a map initialized with the specified string.
	 *
	 * @param in
	 * 	The reader containing the input being parsed.
	 * 	<br>Can contain normal or simplified JSON.
	 * @param p
	 * 	The parser to use to parse the input.
	 * 	<br>If <jk>null</jk>, uses {@link JsonParser}.
	 * @throws ParseException Malformed input encountered.
	 */
	public OMap(Reader in, Parser p) throws ParseException {
		this(p == null ? null : p.createBeanSession());
		parse(in, p);
	}

	/**
	 * Construct a map initialized with the specified key/value pairs.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bcode w800'>
	 * 	OMap m = <jk>new</jk> OMap(<js>"key1"</js>,<js>"val1"</js>,<js>"key2"</js>,<js>"val2"</js>);
	 * </p>
	 *
	 * @param keyValuePairs A list of key/value pairs to add to this map.
	 */
	public OMap(Object... keyValuePairs) {
		if (keyValuePairs.length % 2 != 0)
			throw new RuntimeException("Odd number of parameters passed into OMap(Object...)");
		for (int i = 0; i < keyValuePairs.length; i+=2)
			put(stringify(keyValuePairs[i]), keyValuePairs[i+1]);
	}

	//------------------------------------------------------------------------------------------------------------------
	// Creators.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Construct an empty map.
	 *
	 * @return An empty map.
	 */
	public static OMap create() {
		return new OMap();
	}

	/**
	 * Construct a map initialized with the specified map.
	 *
	 * @param values
	 * 	The map to copy.
	 * 	<br>Can be <jk>null</jk>.
	 * 	<br>Keys will be converted to strings using {@link Object#toString()}.
	 * @return A new map or <jk>null</jk> if the map was <jk>null</jk>.
	 */
	public static OMap of(Map<?,?> values) {
		return values == null ? null : new OMap(values);
	}

	/**
	 * Construct a map initialized with the specified JSON string.
	 *
	 * @param json
	 * 	The JSON text to parse.
	 * 	<br>Can be normal or simplified JSON.
	 * @return A new map or <jk>null</jk> if the string was null.
	 * @throws ParseException Malformed input encountered.
	 */
	public static OMap ofJson(CharSequence json) throws ParseException {
		return json == null ? null : new OMap(json);
	}

	/**
	 * Construct a map initialized with the specified string.
	 *
	 * @param in
	 * 	The input being parsed.
	 * 	<br>Can be <jk>null</jk>.
	 * @param p
	 * 	The parser to use to parse the input.
	 * 	<br>If <jk>null</jk>, uses {@link JsonParser}.
	 * @return A new map or <jk>null</jk> if the input was <jk>null</jk>.
	 * @throws ParseException Malformed input encountered.
	 */
	public static OMap ofText(CharSequence in, Parser p) throws ParseException {
		return in == null ? null : new OMap(in, p);
	}

	/**
	 * Construct a map initialized with the specified reader containing JSON.
	 *
	 * @param json
	 * 	The reader containing JSON text to parse.
	 * 	<br>Can contain normal or simplified JSON.
	 * @return A new map or <jk>null</jk> if the input was <jk>null</jk>.
	 * @throws ParseException Malformed input encountered.
	 */
	public static OMap ofJson(Reader json) throws ParseException {
		return json == null ? null : new OMap(json);
	}

	/**
	 * Construct a map initialized with the specified string.
	 *
	 * @param in
	 * 	The reader containing the input being parsed.
	 * 	<br>Can contain normal or simplified JSON.
	 * @param p
	 * 	The parser to use to parse the input.
	 * 	<br>If <jk>null</jk>, uses {@link JsonParser}.
	 * @return A new map or <jk>null</jk> if the input was <jk>null</jk>.
	 * @throws ParseException Malformed input encountered.
	 */
	public static OMap ofText(Reader in, Parser p) throws ParseException {
		return in == null ? null : new OMap(in);
	}

	/**
	 * Construct a map initialized with the specified key/value pairs.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bcode w800'>
	 * 	OMap m = <jk>new</jk> OMap(<js>"key1"</js>,<js>"val1"</js>,<js>"key2"</js>,<js>"val2"</js>);
	 * </p>
	 *
	 * @param keyValuePairs A list of key/value pairs to add to this map.
	 * @return A new map, never <jk>null</jk>.
	 */
	public static OMap of(Object... keyValuePairs) {
		return new OMap(keyValuePairs);
	}

	//------------------------------------------------------------------------------------------------------------------
	// Initializers.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Set an inner map in this map to allow for chained get calls.
	 *
	 * <p>
	 * If {@link #get(Object)} returns <jk>null</jk>, then {@link #get(Object)} will be called on the inner map.
	 *
	 * <p>
	 * In addition to providing the ability to chain maps, this method also provides the ability to wrap an existing map
	 * inside another map so that you can add entries to the outer map without affecting the values on the inner map.
	 *
	 * <p class='bcode w800'>
	 * 	OMap m1 = OMap.<jsm>ofJson</jsm>(<js>"{foo:1}"</js>);
	 * 	OMap m2 = OMap.<jsm>of</jsm>().setInner(m1);
	 * 	m2.put(<js>"foo"</js>, 2);                      <jc>// Overwrite the entry</jc>
	 * 	<jk>int</jk> foo1 = m1.getInt(<js>"foo"</js>);           <jc>// foo1 == 1 </jc>
	 * 	<jk>int</jk> foo2 = m2.getInt(<js>"foo"</js>);           <jc>// foo2 == 2 </jc>
	 * </p>
	 *
	 * @param inner
	 * 	The inner map.
	 * 	Can be <jk>null</jk> to remove the inner map from an existing map.
	 * @return This object (for method chaining).
	 */
	public OMap inner(Map<String,Object> inner) {
		this.inner = inner;
		return this;
	}

	/**
	 * Override the default bean session used for converting POJOs.
	 *
	 * <p>
	 * Default is {@link BeanContext#DEFAULT}, which is sufficient in most cases.
	 *
	 * <p>
	 * Useful if you're serializing/parsing beans with transforms defined.
	 *
	 * @param session The new bean session.
	 * @return This object (for method chaining).
	 */
	public OMap session(BeanSession session) {
		this.session = session;
		return this;
	}

	//------------------------------------------------------------------------------------------------------------------
	// Appenders.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Adds an entry to this map.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap append(String key, Object value) {
		put(key, value);
		return this;
	}

	/**
	 * Appends all the entries in the specified map to this map.
	 *
	 * @param values The map to copy.
	 * @return This object (for method chaining).
	 */
	public OMap append(Map<String,Object> values) {
		super.putAll(values);
		return this;
	}

	/**
	 * Same as {@link #append(String,Object)}.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap a(String key, Object value) {
		return append(key, value);
	}

	/**
	 * Same as {@link #append(Map)}.
	 *
	 * @param values The map to copy.
	 * @return This object (for method chaining).
	 */
	public OMap a(Map<String,Object> values) {
		return append(values);
	}

	/**
	 * Add if flag is <jk>true</jk>.
	 *
	 * @param flag The flag to check.
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap appendIf(boolean flag, String key, Object value) {
		if (flag)
			append(key, value);
		return this;
	}

	/**
	 * Add if predicate matches value.
	 *
	 * @param test The predicate to match against.
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap appendIf(Predicate<Object> test, String key, Object value) {
		return appendIf(test.test(value), key, value);
	}

	/**
	 * Conditionally adds an entry to this map.
	 *
	 * @param overwrite Overwrite the previous value if there was one.
	 * @param skipNullValue Skip adding the value if the value is <jk>null</jk>.
	 * @param skipEmptyValue Skip adding the value if the value is an empty string.
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap appendIf(boolean overwrite, boolean skipNullValue, boolean skipEmptyValue, String key, Object value) {
		if (value == null && skipNullValue)
			return this;
		if (skipEmptyValue && ObjectUtils.isEmpty(value))
			return this;
		Object current = get(key);
		if (current == null || overwrite)
			put(key, value);
		return this;
	}

	/**
	 * Adds any non-<jk>null</jk>/non-empty values to this map.
	 *
	 * @param key The key.
	 * @param values The values.
	 * @return This object (for method chaining).
	 */
	public OMap appendSkipEmpty(String key, Object...values) {
		for (Object v : values)
			appendIf(true, true, true, key, v);
		return this;
	}

	/**
	 * Adds any non-false values to this map.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap appendSkipFalse(String key, boolean value) {
		if (value)
			a(key, value);
		return this;
	}

	/**
	 * Adds any non--1 values to this map.
	 *
	 * @param key The key.
	 * @param values The values.
	 * @return This object (for method chaining).
	 */
	public OMap appendSkipMinusOne(String key, Number...values) {
		for (Number v : values)
			if (v != null && v.intValue() != -1)
				a(key, v);
		return this;
	}

	/**
	 * Adds a value to this map if the value is not <jk>null</jk>.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public OMap appendSkipNull(String key, Object value) {
		if (value != null)
			a(key, value);
		return this;
	}

	/**
	 * Adds a value in this map if the entry does not exist or the current value is <jk>null</jk>.
	 *
	 * @param key The map key.
	 * @param value The value to set if the current value does not exist or is <jk>null</jk>.
	 * @return This object (for method chaining).
	 */
	public OMap appendIfNull(String key, Object value) {
		Object o = get(key);
		if (o == null)
			put(key, value);
		return this;
	}

	/**
	 * Adds a value in this map if the entry does not exist or the current value is <jk>null</jk> or an empty string.
	 *
	 * @param key The map key.
	 * @param value The value to set if the current value does not exist or is <jk>null</jk> or an empty string.
	 * @return This object (for method chaining).
	 */
	public OMap appendIfEmpty(String key, Object value) {
		Object o = get(key);
		if (o == null || o.toString().isEmpty())
			put(key, value);
		return this;
	}

	/**
	 * Adds a mapping if the specified key doesn't exist.
	 *
	 * @param key The map key.
	 * @param value The value to set if the current value does not exist or is <jk>null</jk> or an empty string.
	 * @return This object (for method chaining).
	 */
	public OMap appendIfNotExists(String key, Object value) {
		if (! containsKey(key))
			put(key, value);
		return this;
	}

	//------------------------------------------------------------------------------------------------------------------
	// Retrievers.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Same as {@link Map#get(Object) get()}, but casts or converts the value to the specified class type.
	 *
	 * <p>
	 * This is the preferred get method for simple types.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bcode w800'>
	 * 	OMap m = OMap.<jsm>ofJson</jsm>(<js>"..."</js>);
	 *
	 * 	<jc>// Value converted to a string.</jc>
	 * 	String s = m.get(<js>"key1"</js>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a bean.</jc>
	 * 	MyBean b = m.get(<js>"key2"</js>, MyBean.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a bean array.</jc>
	 * 	MyBean[] ba = m.get(<js>"key3"</js>, MyBean[].<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a linked-list of objects.</jc>
	 * 	List l = m.get(<js>"key4"</js>, LinkedList.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a map of object keys/values.</jc>
	 * 	Map m2 = m.get(<js>"key5"</js>, TreeMap.<jk>class</jk>);
	 * </p>
	 *
	 * <p>
	 * See {@link BeanSession#convertToType(Object, ClassMeta)} for the list of valid data conversions.
	 *
	 * @param key The key.
	 * @param <T> The class type returned.
	 * @param type The class type returned.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public <T> T get(String key, Class<T> type) {
		return getWithDefault(key, (T)null, type);
	}

	/**
	 * Same as {@link #get(String,Class)}, but allows for complex data types consisting of collections or maps.
	 *
	 * <p>
	 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bcode w800'>
	 * 	OMap m = OMap.<jsm>ofJson</jsm>(<js>"..."</js>);
	 *
	 * 	<jc>// Value converted to a linked-list of strings.</jc>
	 * 	List&lt;String&gt; l1 = m.get(<js>"key1"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a linked-list of beans.</jc>
	 * 	List&lt;MyBean&gt; l2 = m.get(<js>"key2"</js>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a linked-list of linked-lists of strings.</jc>
	 * 	List&lt;List&lt;String&gt;&gt; l3 = m.get(<js>"key3"</js>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a map of string keys/values.</jc>
	 * 	Map&lt;String,String&gt; m1 = m.get(<js>"key4"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Value converted to a map containing string keys and values of lists containing beans.</jc>
	 * 	Map&lt;String,List&lt;MyBean&gt;&gt; m2 = m.get(<js>"key5"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
	 * </p>
	 *
	 * <p>
	 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
	 *
	 * <p>
	 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types.
	 *
	 * <p>
	 * The array can be arbitrarily long to indicate arbitrarily complex data structures.
	 *
	 * <p>
	 * See {@link BeanSession#convertToType(Object, ClassMeta)} for the list of valid data conversions.
	 *
	 * <ul class='notes'>
	 * 	<li>
	 * 		Use the {@link #get(String, Class)} method instead if you don't need a parameterized map/collection.
	 * </ul>
	 *
	 * @param key The key.
	 * @param <T> The class type returned.
	 * @param type The class type returned.
	 * @param args The class type parameters.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public <T> T get(String key, Type type, Type...args) {
		return getWithDefault(key, null, type, args);
	}

	/**
	 * Same as {@link Map#get(Object) get()}, but returns the default value if the key could not be found.
	 *
	 * @param key The key.
	 * @param def The default value if the entry doesn't exist.
	 * @return The value, or the default value if the entry doesn't exist.
	 */
	public Object getWithDefault(String key, Object def) {
		Object o = get(key);
		return (o == null ? def : o);
	}

	/**
	 * Same as {@link #get(String,Class)} but returns a default value if the value does not exist.
	 *
	 * @param key The key.
	 * @param def The default value.  Can be <jk>null</jk>.
	 * @param <T> The class type returned.
	 * @param type The class type returned.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public <T> T getWithDefault(String key, T def, Class<T> type) {
		return getWithDefault(key, def, type, new Type[0]);
	}

	/**
	 * Same as {@link #get(String,Type,Type...)} but returns a default value if the value does not exist.
	 *
	 * @param key The key.
	 * @param def The default value.  Can be <jk>null</jk>.
	 * @param <T> The class type returned.
	 * @param type The class type returned.
	 * @param args The class type parameters.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public <T> T getWithDefault(String key, T def, Type type, Type...args) {
		Object o = get(key);
		if (o == null)
			return def;
		T t = bs().convertToType(o, type, args);
		return t == null ? def : t;
	}

	/**
	 * Searches for the specified key in this map ignoring case.
	 *
	 * @param key
	 * 	The key to search for.
	 * 	For performance reasons, it's preferable that the key be all lowercase.
	 * @return The key, or <jk>null</jk> if map does not contain this key.
	 */
	public String findKeyIgnoreCase(String key) {
		for (String k : keySet())
			if (key.equalsIgnoreCase(k))
				return k;
		return null;
	}

	/**
	 * Same as {@link Map#get(Object) get()}, but converts the raw value to the specified class type using the specified
	 * POJO swap.
	 *
	 * @param key The key.
	 * @param pojoSwap The swap class used to convert the raw type to a transformed type.
	 * @param <T> The transformed class type.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 * @throws ParseException Malformed input encountered.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public <T> T getSwapped(String key, PojoSwap<T,?> pojoSwap) throws ParseException {
		try {
			Object o = super.get(key);
			if (o == null)
				return null;
			PojoSwap swap = pojoSwap;
			return (T) swap.unswap(bs(), o, null);
		} catch (ParseException e) {
			throw e;
		} catch (Exception e) {
			throw new ParseException(e);
		}
	}

	/**
	 * Returns the value for the first key in the list that has an entry in this map.
	 *
	 * @param keys The keys to look up in order.
	 * @return The value of the first entry whose key exists, or <jk>null</jk> if none of the keys exist in this map.
	 */
	public Object find(String...keys) {
		for (String key : keys)
			if (containsKey(key))
				return get(key);
		return null;
	}

	/**
	 * Returns the value for the first key in the list that has an entry in this map.
	 *
	 * <p>
	 * Casts or converts the value to the specified class type.
	 *
	 * <p>
	 * See {@link BeanSession#convertToType(Object, ClassMeta)} for the list of valid data conversions.
	 *
	 * @param type The class type to convert the value to.
	 * @param <T> The class type to convert the value to.
	 * @param keys The keys to look up in order.
	 * @return The value of the first entry whose key exists, or <jk>null</jk> if none of the keys exist in this map.
	 */
	public <T> T find(Class<T> type, String...keys) {
		for (String key : keys)
			if (containsKey(key))
				return get(key, type);
		return null;
	}

	/**
	 * Returns the specified entry value converted to a {@link String}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, String.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 */
	public String getString(String key) {
		return get(key, String.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link String}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, String[].<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 */
	public String[] getStringArray(String key) {
		return getStringArray(key, null);
	}

	/**
	 * Same as {@link #getStringArray(String)} but returns a default value if the value cannot be found.
	 *
	 * @param key The map key.
	 * @param def The default value if value is not found.
	 * @return The value converted to a string array.
	 */
	public String[] getStringArray(String key, String[] def) {
		Object s = get(key, Object.class);
		if (s == null)
			return def;
		String[] r = null;
		if (s instanceof Collection)
			r = ArrayUtils.toStringArray((Collection<?>)s);
		else if (s instanceof String[])
			r = (String[])s;
		else if (s instanceof Object[])
			r = ArrayUtils.toStringArray(Arrays.asList((Object[])s));
		else
			r = split(stringify(s));
		return (r.length == 0 ? def : r);
	}

	/**
	 * Returns the specified entry value converted to a {@link String}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, String.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 */
	public String getString(String key, String defVal) {
		return getWithDefault(key, defVal, String.class);
	}

	/**
	 * Returns the specified entry value converted to an {@link Integer}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, Integer.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Integer getInt(String key) {
		return get(key, Integer.class);
	}

	/**
	 * Returns the specified entry value converted to an {@link Integer}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, Integer.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Integer getInt(String key, Integer defVal) {
		return getWithDefault(key, defVal, Integer.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link Long}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, Long.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Long getLong(String key) {
		return get(key, Long.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link Long}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, Long.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Long getLong(String key, Long defVal) {
		return getWithDefault(key, defVal, Long.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link Boolean}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, Boolean.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Boolean getBoolean(String key) {
		return get(key, Boolean.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link Boolean}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, Boolean.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Boolean getBoolean(String key, Boolean defVal) {
		return getWithDefault(key, defVal, Boolean.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link Map}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, OMap.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OMap getMap(String key) {
		return get(key, OMap.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link OMap}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, OMap.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OMap getMap(String key, OMap defVal) {
		return getWithDefault(key, defVal, OMap.class);
	}

	/**
	 * Same as {@link #getMap(String)} but creates a new empty {@link OMap} if it doesn't already exist.
	 *
	 * @param key The key.
	 * @param createIfNotExists If mapping doesn't already exist, create one with an empty {@link OMap}.
	 * @return The converted value, or an empty value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OMap getMap(String key, boolean createIfNotExists) {
		OMap m = getWithDefault(key, null, OMap.class);
		if (m == null && createIfNotExists) {
			m = new OMap();
			put(key, m);
		}
		return m;
	}

	/**
	 * Same as {@link #getMap(String, OMap)} except converts the keys and values to the specified types.
	 *
	 * @param key The key.
	 * @param keyType The key type class.
	 * @param valType The value type class.
	 * @param def The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public <K,V> Map<K,V> getMap(String key, Class<K> keyType, Class<V> valType, Map<K,V> def) {
		Object o = get(key);
		if (o == null)
			return def;
		return bs().convertToType(o, Map.class, keyType, valType);
	}

	/**
	 * Returns the specified entry value converted to a {@link OList}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, OList.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OList getList(String key) {
		return get(key, OList.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link OList}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, OList.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OList getList(String key, OList defVal) {
		return getWithDefault(key, defVal, OList.class);
	}

	/**
	 * Same as {@link #getList(String)} but creates a new empty {@link OList} if it doesn't already exist.
	 *
	 * @param key The key.
	 * @param createIfNotExists If mapping doesn't already exist, create one with an empty {@link OList}.
	 * @return The converted value, or an empty value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OList getList(String key, boolean createIfNotExists) {
		OList m = getWithDefault(key, null, OList.class);
		if (m == null && createIfNotExists) {
			m = new OList();
			put(key, m);
		}
		return m;
	}

	/**
	 * Same as {@link #getList(String, OList)} except converts the elements to the specified types.
	 *
	 * @param key The key.
	 * @param elementType The element type class.
	 * @param def The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public <E> List<E> getList(String key, Class<E> elementType, List<E> def) {
		Object o = get(key);
		if (o == null)
			return def;
		return bs().convertToType(o, List.class, elementType);
	}

	/**
	 * Returns the first entry that exists converted to a {@link String}.
	 *
	 * <p>
	 * Shortcut for <code>find(String.<jk>class</jk>, keys)</code>.
	 *
	 * @param keys The list of keys to look for.
	 * @return
	 * 	The converted value of the first key in the list that has an entry in this map, or <jk>null</jk> if the map
	 * 	contains no mapping for any of the keys.
	 */
	public String findString(String... keys) {
		return find(String.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to an {@link Integer}.
	 *
	 * <p>
	 * Shortcut for <code>find(Integer.<jk>class</jk>, keys)</code>.
	 *
	 * @param keys The list of keys to look for.
	 * @return
	 * 	The converted value of the first key in the list that has an entry in this map, or <jk>null</jk> if the map
	 * 	contains no mapping for any of the keys.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Integer findInt(String... keys) {
		return find(Integer.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link Long}.
	 *
	 * <p>
	 * Shortcut for <code>find(Long.<jk>class</jk>, keys)</code>.
	 *
	 * @param keys The list of keys to look for.
	 * @return
	 * 	The converted value of the first key in the list that has an entry in this map, or <jk>null</jk> if the map
	 * 	contains no mapping for any of the keys.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Long findLong(String... keys) {
		return find(Long.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link Boolean}.
	 *
	 * <p>
	 * Shortcut for <code>find(Boolean.<jk>class</jk>, keys)</code>.
	 *
	 * @param keys The list of keys to look for.
	 * @return
	 * 	The converted value of the first key in the list that has an entry in this map, or <jk>null</jk> if the map
	 * 	contains no mapping for any of the keys.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Boolean findBoolean(String... keys) {
		return find(Boolean.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link OMap}.
	 *
	 * <p>
	 * Shortcut for <code>find(OMap.<jk>class</jk>, keys)</code>.
	 *
	 * @param keys The list of keys to look for.
	 * @return
	 * 	The converted value of the first key in the list that has an entry in this map, or <jk>null</jk> if the map
	 * 	contains no mapping for any of the keys.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OMap findMap(String... keys) {
		return find(OMap.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link OList}.
	 *
	 * <p>
	 * Shortcut for <code>find(OList.<jk>class</jk>, keys)</code>.
	 *
	 * @param keys The list of keys to look for.
	 * @return
	 * 	The converted value of the first key in the list that has an entry in this map, or <jk>null</jk> if the map
	 * 	contains no mapping for any of the keys.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public OList findList(String... keys) {
		return find(OList.class, keys);
	}

	/**
	 * Returns the first key in the map.
	 *
	 * @return The first key in the map, or <jk>null</jk> if the map is empty.
	 */
	public String getFirstKey() {
		return isEmpty() ? null : keySet().iterator().next();
	}

	/**
	 * Returns the class type of the object at the specified index.
	 *
	 * @param key The key into this map.
	 * @return
	 * 	The data type of the object at the specified key, or <jk>null</jk> if the value is null or does not exist.
	 */
	public ClassMeta<?> getClassMeta(String key) {
		return bs().getClassMetaForObject(get(key));
	}

	/**
	 * Equivalent to calling <c>get(class,key,def)</c> followed by <c>remove(key);</c>
	 * @param key The key.
	 * @param defVal The default value if the map doesn't contain the specified mapping.
	 * @param type The class type.
	 *
	 * @param <T> The class type.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public <T> T removeWithDefault(String key, T defVal, Class<T> type) {
		T t = getWithDefault(key, defVal, type);
		remove(key);
		return t;
	}

	/**
	 * Equivalent to calling <code>removeWithDefault(key,<jk>null</jk>,String.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public String removeString(String key) {
		return removeString(key, null);
	}

	/**
	 * Equivalent to calling <code>removeWithDefault(key,def,String.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param def The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public String removeString(String key, String def) {
		return removeWithDefault(key, def, String.class);
	}

	/**
	 * Equivalent to calling <code>removeWithDefault(key,<jk>null</jk>,Integer.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Integer removeInt(String key) {
		return removeInt(key, null);
	}

	/**
	 * Equivalent to calling <code>removeWithDefault(key,def,Integer.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param def The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Integer removeInt(String key, Integer def) {
		return removeWithDefault(key, def, Integer.class);
	}

	/**
	 * Equivalent to calling <code>removeWithDefault(key,<jk>null</jk>,Boolean.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @return The converted value, or <jk>null</jk> if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Boolean removeBoolean(String key) {
		return removeBoolean(key, null);
	}

	/**
	 * Equivalent to calling <code>removeWithDefault(key,def,Boolean.<jk>class</jk>)</code>.
	 *
	 * @param key The key.
	 * @param def The default value if the map doesn't contain the specified mapping.
	 * @return The converted value, or the default value if the map contains no mapping for this key.
	 * @throws InvalidDataConversionException If value cannot be converted.
	 */
	public Boolean removeBoolean(String key, Boolean def) {
		return removeWithDefault(key, def, Boolean.class);
	}

	/**
	 * Convenience method for removing several keys at once.
	 *
	 * @param keys The list of keys to remove.
	 */
	public void removeAll(Collection<String> keys) {
		for (String k : keys)
			remove(k);
	}

	/**
	 * Convenience method for removing several keys at once.
	 *
	 * @param keys The list of keys to remove.
	 */
	public void removeAll(String... keys) {
		for (String k : keys)
			remove(k);
	}

	/**
	 * The opposite of {@link #removeAll(String...)}.
	 *
	 * <p>
	 * Discards all keys from this map that aren't in the specified list.
	 *
	 * @param keys The keys to keep.
	 * @return This map.
	 */
	public OMap keepAll(String...keys) {
		for (Iterator<String> i = keySet().iterator(); i.hasNext();) {
			boolean remove = true;
			String key = i.next();
			for (String k : keys) {
				if (k.equals(key)) {
					remove = false;
					break;
				}
			}
			if (remove)
				i.remove();
		}
		return this;
	}

	/**
	 * Returns <jk>true</jk> if the map contains the specified entry and the value is not null nor an empty string.
	 *
	 * <p>
	 * Always returns <jk>false</jk> if the value is not a {@link CharSequence}.
	 *
	 * @param key The key.
	 * @return <jk>true</jk> if the map contains the specified entry and the value is not null nor an empty string.
	 */
	public boolean containsKeyNotEmpty(String key) {
		Object val = get(key);
		if (val == null)
			return false;
		if (val instanceof CharSequence)
			return ! StringUtils.isEmpty(val);
		return false;
	}

	/**
	 * Returns <jk>true</jk> if this map contains the specified key, ignoring the inner map if it exists.
	 *
	 * @param key The key to look up.
	 * @return <jk>true</jk> if this map contains the specified key.
	 */
	public boolean containsOuterKey(Object key) {
		return super.containsKey(key);
	}

	/**
	 * Returns a copy of this <c>OMap</c> with only the specified keys.
	 *
	 * @param keys The keys of the entries to copy.
	 * @return A new map with just the keys and values from this map.
	 */
	public OMap include(String...keys) {
		OMap m2 = new OMap();
		for (Map.Entry<String,Object> e : this.entrySet())
			for (String k : keys)
				if (k.equals(e.getKey()))
					m2.put(k, e.getValue());
		return m2;
	}

	/**
	 * Returns a copy of this <c>OMap</c> without the specified keys.
	 *
	 * @param keys The keys of the entries not to copy.
	 * @return A new map without the keys and values from this map.
	 */
	public OMap exclude(String...keys) {
		OMap m2 = new OMap();
		for (Map.Entry<String,Object> e : this.entrySet()) {
			boolean exclude = false;
			for (String k : keys)
				if (k.equals(e.getKey()))
					exclude = true;
			if (! exclude)
				m2.put(e.getKey(), e.getValue());
		}
		return m2;
	}

	/**
	 * Converts this map into an object of the specified type.
	 *
	 * <p>
	 * If this map contains a <js>"_type"</js> entry, it must be the same as or a subclass of the <c>type</c>.
	 *
	 * @param <T> The class type to convert this map object to.
	 * @param type The class type to convert this map object to.
	 * @return The new object.
	 * @throws ClassCastException
	 * 	If the <js>"_type"</js> entry is present and not assignable from <c>type</c>
	 */
	@SuppressWarnings("unchecked")
	public <T> T cast(Class<T> type) {
		BeanSession bs = bs();
		ClassMeta<?> c2 = bs.getClassMeta(type);
		String typePropertyName = bs.getBeanTypePropertyName(c2);
		ClassMeta<?> c1 = bs.getBeanRegistry().getClassMeta((String)get(typePropertyName));
		ClassMeta<?> c = c1 == null ? c2 : narrowClassMeta(c1, c2);
		if (c.isObject())
			return (T)this;
		return (T)cast2(c);
	}

	/**
	 * Same as {@link #cast(Class)}, except allows you to specify a {@link ClassMeta} parameter.
	 *
	 * @param <T> The class type to convert this map object to.
	 * @param cm The class type to convert this map object to.
	 * @return The new object.
	 * @throws ClassCastException
	 * 	If the <js>"_type"</js> entry is present and not assignable from <c>type</c>
	 */
	@SuppressWarnings({"unchecked"})
	public <T> T cast(ClassMeta<T> cm) {
		BeanSession bs = bs();
		ClassMeta<?> c1 = bs.getBeanRegistry().getClassMeta((String)get(bs.getBeanTypePropertyName(cm)));
		ClassMeta<?> c = narrowClassMeta(c1, cm);
		return (T)cast2(c);
	}

	//------------------------------------------------------------------------------------------------------------------
	// POJO REST methods.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Same as {@link #get(String,Class) get(String,Class)}, but the key is a slash-delimited path used to traverse
	 * entries in this POJO.
	 *
	 * <p>
	 * For example, the following code is equivalent:
	 * </p>
	 * <p class='bcode w800'>
	 * 	OMap m = OMap.<jsm>ofJson</jsm>(<js>"..."</js>);
	 *
	 * 	<jc>// Long way</jc>
	 * 	<jk>long</jk> l = m.getMap(<js>"foo"</js>).getList(<js>"bar"</js>).getMap(<js>"0"</js>).getLong(<js>"baz"</js>);
	 *
	 * 	<jc>// Using this method</jc>
	 * 	<jk>long</jk> l = m.getAt(<js>"foo/bar/0/baz"</js>, <jk>long</jk>.<jk>class</jk>);
	 * </p>
	 *
	 * <p>
	 * This method uses the {@link PojoRest} class to perform the lookup, so the map can contain any of the various
	 * class types that the {@link PojoRest} class supports (e.g. beans, collections, arrays).
	 *
	 * @param path The path to the entry.
	 * @param type The class type.
	 *
	 * @param <T> The class type.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public <T> T getAt(String path, Class<T> type) {
		return getPojoRest().get(path, type);
	}

	/**
	 * Same as {@link #getAt(String,Class)}, but allows for conversion to complex maps and collections.
	 *
	 * <p>
	 * This method uses the {@link PojoRest} class to perform the lookup, so the map can contain any of the various
	 * class types that the {@link PojoRest} class supports (e.g. beans, collections, arrays).
	 *
	 * @param path The path to the entry.
	 * @param type The class type.
	 * @param args The class parameter types.
	 *
	 * @param <T> The class type.
	 * @return The value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public <T> T getAt(String path, Type type, Type...args) {
		return getPojoRest().get(path, type, args);
	}

	/**
	 * Same as <c>put(String,Object)</c>, but the key is a slash-delimited path used to traverse entries in this
	 * POJO.
	 *
	 * <p>
	 * For example, the following code is equivalent:
	 * </p>
	 * <p class='bcode w800'>
	 * 	OMap m = OMap.<jsm>ofJson</jsm>(<js>"..."</js>);
	 *
	 * 	<jc>// Long way</jc>
	 * 	m.getMap(<js>"foo"</js>).getList(<js>"bar"</js>).getMap(<js>"0"</js>).put(<js>"baz"</js>, 123);
	 *
	 * 	<jc>// Using this method</jc>
	 * 	m.putAt(<js>"foo/bar/0/baz"</js>, 123);
	 * </p>
	 *
	 * <p>
	 * This method uses the {@link PojoRest} class to perform the lookup, so the map can contain any of the various
	 * class types that the {@link PojoRest} class supports (e.g. beans, collections, arrays).
	 *
	 * @param path The path to the entry.
	 * @param o The new value.
	 * @return The previous value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public Object putAt(String path, Object o) {
		return getPojoRest().put(path, o);
	}

	/**
	 * Similar to {@link #putAt(String,Object) putAt(String,Object)}, but used to append to collections and arrays.
	 *
	 * <p>
	 * For example, the following code is equivalent:
	 * </p>
	 * <p class='bcode w800'>
	 * 	OMap m = OMap.<jsm>ofJson</jsm>(<js>"..."</js>);
	 *
	 * 	<jc>// Long way</jc>
	 * 	m.getMap(<js>"foo"</js>).getList(<js>"bar"</js>).append(123);
	 *
	 * 	<jc>// Using this method</jc>
	 * 	m.postAt(<js>"foo/bar"</js>, 123);
	 * </p>
	 *
	 * <p>
	 * This method uses the {@link PojoRest} class to perform the lookup, so the map can contain any of the various
	 * class types that the {@link PojoRest} class supports (e.g. beans, collections, arrays).
	 *
	 * @param path The path to the entry.
	 * @param o The new value.
	 * @return The previous value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public Object postAt(String path, Object o) {
		return getPojoRest().post(path, o);
	}

	/**
	 * Similar to {@link #remove(Object) remove(Object)}, but the key is a slash-delimited path used to traverse entries
	 * in this POJO.
	 *
	 * <p>
	 * For example, the following code is equivalent:
	 * </p>
	 * <p class='bcode w800'>
	 * 	OMap m = OMap.<jsm>ofJson</jsm>(<js>"..."</js>);
	 *
	 * 	<jc>// Long way</jc>
	 * 	m.getMap(<js>"foo"</js>).getList(<js>"bar"</js>).getMap(0).remove(<js>"baz"</js>);
	 *
	 * 	<jc>// Using this method</jc>
	 * 	m.deleteAt(<js>"foo/bar/0/baz"</js>);
	 * </p>
	 *
	 * <p>
	 * This method uses the {@link PojoRest} class to perform the lookup, so the map can contain any of the various
	 * class types that the {@link PojoRest} class supports (e.g. beans, collections, arrays).
	 *
	 * @param path The path to the entry.
	 * @return The previous value, or <jk>null</jk> if the entry doesn't exist.
	 */
	public Object deleteAt(String path) {
		return getPojoRest().delete(path);
	}

	//------------------------------------------------------------------------------------------------------------------
	// Other methods.
	//------------------------------------------------------------------------------------------------------------------

	/**
	 * Returns the {@link BeanSession} currently associated with this map.
	 *
	 * @return The {@link BeanSession} currently associated with this map.
	 */
	public BeanSession getBeanSession() {
		return session;
	}

	/**
	 * Sets the {@link BeanSession} currently associated with this map.
	 *
	 * @param value The {@link BeanSession} currently associated with this map.
	 * @return This object (for method chaining).
	 */
	public OMap setBeanSession(BeanSession value) {
		this.session = value;
		return this;
	}

	/**
	 * Convenience method for inserting JSON directly into an attribute on this object.
	 *
	 * <p>
	 * The JSON text can be an object (i.e. <js>"{...}"</js>) or an array (i.e. <js>"[...]"</js>).
	 *
	 * @param key The key.
	 * @param json The JSON text that will be parsed into an Object and then inserted into this map.
	 * @throws ParseException Malformed input encountered.
	 */
	public void putJson(String key, String json) throws ParseException {
		this.put(key, JsonParser.DEFAULT.parse(json, Object.class));
	}

	/**
	 * Serialize this object into a string using the specified serializer.
	 *
	 * @param serializer The serializer to use to convert this object to a string.
	 * @return This object serialized as a string.
	 */
	public String asString(WriterSerializer serializer) {
		return serializer.toString(this);
	}

	/**
	 * Serialize this object to Simplified JSON.
	 *
	 * @return This object serialized as a string.
	 */
	public String asString() {
		return SimpleJsonSerializer.DEFAULT.toString(this);
	}

	/**
	 * Convenience method for serializing this map to the specified <c>Writer</c> using the
	 * {@link JsonSerializer#DEFAULT} serializer.
	 *
	 * @param w The writer to serialize this object to.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred trying to write to the writer.
	 * @throws SerializeException If a problem occurred trying to convert the output.
	 */
	public OMap writeTo(Writer w) throws IOException, SerializeException {
		JsonSerializer.DEFAULT.serialize(this, w);
		return this;
	}

	/**
	 * Returns <jk>true</jk> if this map is unmodifiable.
	 *
	 * @return <jk>true</jk> if this map is unmodifiable.
	 */
	public boolean isUnmodifiable() {
		return false;
	}

	/**
	 * Returns a modifiable copy of this map if it's unmodifiable.
	 *
	 * @return A modifiable copy of this map if it's unmodifiable, or this map if it is already modifiable.
	 */
	public OMap modifiable() {
		if (isUnmodifiable())
			return new OMap(this);
		return this;
	}

	/**
	 * Returns an unmodifiable copy of this map if it's modifiable.
	 *
	 * @return An unmodifiable copy of this map if it's modifiable, or this map if it is already unmodifiable.
	 */
	public OMap unmodifiable() {
		if (this instanceof UnmodifiableOMap)
			return this;
		return new UnmodifiableOMap(this);
	}

	//------------------------------------------------------------------------------------------------------------------
	// Utility methods.
	//------------------------------------------------------------------------------------------------------------------

	private BeanSession bs() {
		if (session == null)
			session = BeanContext.DEFAULT.createBeanSession();
		return session;
	}

	private PojoRest getPojoRest() {
		if (pojoRest == null)
			pojoRest = new PojoRest(this);
		return pojoRest;
	}

	/*
	 * Combines the class specified by a "_type" attribute with the ClassMeta
	 * passed in through the cast(ClassMeta) method.
	 * The rule is that child classes supersede parent classes, and c2 supersedes c1
	 * if one isn't the parent of another.
	 */
	private ClassMeta<?> narrowClassMeta(ClassMeta<?> c1, ClassMeta<?> c2) {
		if (c1 == null)
			return c2;
		ClassMeta<?> c = getNarrowedClassMeta(c1, c2);
		if (c1.isMap()) {
			ClassMeta<?> k = getNarrowedClassMeta(c1.getKeyType(), c2.getKeyType());
			ClassMeta<?> v = getNarrowedClassMeta(c1.getValueType(), c2.getValueType());
			return bs().getClassMeta(c.getInnerClass(), k, v);
		}
		if (c1.isCollection()) {
			ClassMeta<?> e = getNarrowedClassMeta(c1.getElementType(), c2.getElementType());
			return bs().getClassMeta(c.getInnerClass(), e);
		}
		return c;
	}

	/*
	 * If c1 is a child of c2 or the same as c2, returns c1.
	 * Otherwise, returns c2.
	 */
	private static ClassMeta<?> getNarrowedClassMeta(ClassMeta<?> c1, ClassMeta<?> c2) {
		if (c2 == null || c2.getInfo().isParentOf(c1.getInnerClass()))
			return c1;
		return c2;
	}

	/*
	 * Converts this map to the specified class type.
	 */
	@SuppressWarnings({"unchecked","rawtypes"})
	private <T> T cast2(ClassMeta<T> cm) {

		BeanSession bs = bs();
		try {
			Object value = get("value");

			if (cm.isMap()) {
				Map m2 = (cm.canCreateNewInstance() ? (Map)cm.newInstance() : new OMap(bs));
				ClassMeta<?> kType = cm.getKeyType(), vType = cm.getValueType();
				for (Map.Entry<String,Object> e : entrySet()) {
					Object k = e.getKey();
					Object v = e.getValue();
					if (! k.equals(bs.getBeanTypePropertyName(cm))) {

						// Attempt to recursively cast child maps.
						if (v instanceof OMap)
							v = ((OMap)v).cast(vType);

						k = (kType.isString() ? k : bs.convertToType(k, kType));
						v = (vType.isObject() ? v : bs.convertToType(v, vType));

						m2.put(k, v);
					}
				}
				return (T)m2;

			} else if (cm.isBean()) {
				BeanMap<? extends T> bm = bs.newBeanMap(cm.getInnerClass());

				// Iterate through all the entries in the map and set the individual field values.
				for (Map.Entry<String,Object> e : entrySet()) {
					String k = e.getKey();
					Object v = e.getValue();
					if (! k.equals(bs.getBeanTypePropertyName(cm))) {

						// Attempt to recursively cast child maps.
						if (v instanceof OMap)
							v = ((OMap)v).cast(bm.getProperty(k).getMeta().getClassMeta());

						bm.put(k, v);
					}
				}

				return bm.getBean();

			} else if (cm.isCollectionOrArray()) {
				List items = (List)get("items");
				return bs.convertToType(items, cm);

			} else if (value != null) {
				return bs.convertToType(value, cm);
			}

		} catch (Exception e) {
			throw new BeanRuntimeException(e, cm.getInnerClass(),
				"Error occurred attempting to cast to an object of type ''{0}''", cm.getInnerClass().getName());
		}

		throw new BeanRuntimeException(cm.getInnerClass(),
			"Cannot convert to class type ''{0}''.  Only beans and maps can be converted using this method.",
			cm.getInnerClass().getName());
	}

	private void parse(Reader r, Parser p) throws ParseException {
		if (p == null)
			p = JsonParser.DEFAULT;
		p.parseIntoMap(r, this, bs().string(), bs().object());
	}

	private static final class UnmodifiableOMap extends OMap {
		private static final long serialVersionUID = 1L;

		UnmodifiableOMap(OMap contents) {
			super();
			if (contents != null) {
				for (Map.Entry<String,Object> e : contents.entrySet()) {
					super.put(e.getKey(), e.getValue());
				}
			}
		}

		@Override
		public final Object put(String key, Object val) {
			throw new UnsupportedOperationException("OMap is read-only.");
		}

		@Override
		public final Object remove(Object key) {
			throw new UnsupportedOperationException("OMap is read-only.");
		}

		@Override
		public final boolean isUnmodifiable() {
			return true;
		}
	}

	//------------------------------------------------------------------------------------------------------------------
	// Overridden methods.
	//------------------------------------------------------------------------------------------------------------------

	@Override /* Map */
	public Object get(Object key) {
		Object o = super.get(key);
		if (o == null && inner != null)
			o = inner.get(key);
		return o;
	}

	@Override /* Map */
	public boolean containsKey(Object key) {
		if (super.containsKey(key))
			return true;
		if (inner != null)
			return inner.containsKey(key);
		return false;
	}

	@Override /* Map */
	public Set<String> keySet() {
		if (inner == null)
			return super.keySet();
		LinkedHashSet<String> s = new LinkedHashSet<>();
		s.addAll(inner.keySet());
		s.addAll(super.keySet());
		return s;
	}

	@Override /* Map */
	public Set<Map.Entry<String,Object>> entrySet() {
		if (inner == null)
			return super.entrySet();

		final Set<String> keySet = keySet();
		final Iterator<String> keys = keySet.iterator();

		return new AbstractSet<Map.Entry<String,Object>>() {

			@Override /* Iterable */
			public Iterator<Map.Entry<String,Object>> iterator() {

				return new Iterator<Map.Entry<String,Object>>() {

					@Override /* Iterator */
					public boolean hasNext() {
						return keys.hasNext();
					}

					@Override /* Iterator */
					public Map.Entry<String,Object> next() {
						return new Map.Entry<String,Object>() {
							String key = keys.next();

							@Override /* Map.Entry */
							public String getKey() {
								return key;
							}

							@Override /* Map.Entry */
							public Object getValue() {
								return get(key);
							}

							@Override /* Map.Entry */
							public Object setValue(Object object) {
								return put(key, object);
							}
						};
					}

					@Override /* Iterator */
					public void remove() {
						throw new UnsupportedOperationException();
					}
				};
			}

			@Override /* Set */
			public int size() {
				return keySet.size();
			}
		};
	}

	@Override /* Object */
	public String toString() {
		return SimpleJson.DEFAULT.toString(this);
	}
}
