// ***************************************************************************************************************************
// * 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.ExceptionUtils.*;
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;
	private transient Predicate<Object> valueFilter = x -> true;

	/**
	 * 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 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;
	}

	/**
	 * Enables filtering based on default values.
	 *
	 * <p>
	 * Any of the following types will be ignored when set as values in this map:
	 * <ul>
	 * 	<li><jk>null</jk>
	 * 	<li><jk>false</jk>
	 * 	<li><c>-1</c> (any Number type)
	 * 	<li>Empty arrays/collections/maps.
	 * </ul>
	 * @return This object (for method chaining).
	 */
	public OMap filtered() {
		return filtered(x -> ! (
			x == null
			|| (x instanceof Boolean && x.equals(false))
			|| (x instanceof Number && ((Number)x).intValue() == -1)
			|| (x.getClass().isArray() && Array.getLength(x) == 0)
			|| (x instanceof Map && ((Map<?,?>)x).isEmpty())
			|| (x instanceof Collection && ((Collection<?>)x).isEmpty())
		));
	}

	/**
	 * Enables filtering based on a predicate test.
	 *
	 * <p>
	 * If the predicate evaluates to <jk>false</jk> on values added to this map, the entry will be skipped.
	 *
	 * @param value The value tester predicate.
	 * @return This object (for method chaining).
	 */
	public OMap filtered(Predicate<Object> value) {
		valueFilter = 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.
	//------------------------------------------------------------------------------------------------------------------

	@Override
	public Object put(String key, Object value) {
		if (valueFilter.test(value))
			super.put(key, value);
		return null;
	}

	/**
	 * 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);
	}
}
