// ***************************************************************************************************************************
// * 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;

import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
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.
 * 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>
 * 	Map m = <jk>new</jk> ObjectMap();
 *
 * 	<jc>// Construct a Map from JSON</jc>
 * 	String json = <js>"{a:'A',b:{c:'C',d:123}}"</js>;
 * 	m = <jk>new</jk> ObjectMap(json);
 *
 * 	<jc>// Construct a Map using the append method</jc>
 * 	m = <jk>new</jk> ObjectMap().append(<js>"foo"</js>,<js>"x"</js>).append(<js>"bar"</js>,123)
 * 		.append(<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 = <jk>new</jk> ObjectMap(xml, DataFormat.<jsf>XML</jsf>);
 * 	m = (Map)XmlParser.<jsf>DEFAULT</jsf>.parse(xml); <jc>// Equivalent</jc>
 * 	m = (Map)XmlParser.<jsf>DEFAULT</jsf>.parse(Object.<jk>class</jk>, xml); <jc>// Equivalent</jc>
 * 	m = XmlParser.<jsf>DEFAULT</jsf>.parse(Map.<jk>class</jk>, xml); <jc>// Equivalent</jc>
 * 	m = XmlParser.<jsf>DEFAULT</jsf>.parse(ObjectMap.<jk>class</jk>, xml); <jc>// Equivalent</jc>
 *
 * 	<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 = <jk>new</jk> ObjectMap(urlParams, DataFormat.<jsf>URLPARAM</jsf>);
 * 	m = (Map)UrlEncodingParser.<jsf>DEFAULT</jsf>.parse(Object.<jk>class</jk>, xml); <jc>// Equivalent</jc>
 * 	m = UrlEncodingParser.<jsf>DEFAULT</jsf>.parse(Map.<jk>class</jk>, xml); <jc>// Equivalent</jc>
 * 	m = UrlEncodingParser.<jsf>DEFAULT</jsf>.parse(ObjectMap.<jk>class</jk>, xml); <jc>// Equivalent</jc>
 *
 * 	<jc>// Construct JSON from ObjectMap</jc>
 * 	m = <jk>new</jk> ObjectMap(<js>"{foo:'bar'},{baz:[123,true]}"</js>);
 * 	json = m.toString();  <jc>// Produces "{foo:'bar'},{baz:[123,true]}"</jc>
 * 	json = m.toString(JsonSerializer.<jsf>DEFAULT_CONDENSED</jsf>);  <jc>// Equivalent</jc>
 * 	json = JsonSerializer.<jsf>DEFAULT_CONDENSED</jsf>.serialize(m);  <jc>// Equivalent</jc>
 *
 * 	<jc>// Get a map entry as an Integer</jc>
 * 	m = <jk>new</jk> ObjectMap(<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 = <jk>new</jk> ObjectMap(<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 = <jk>new</jk> ObjectMap(<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 = <jk>new</jk> ObjectMap(<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>
 * 	ObjectMap m1 = <jk>new</jk> ObjectMap(<js>"{a:1}"</js>);
 * 	ObjectMap m2 = <jk>new</jk> ObjectMap(<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 ObjectMap 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 ObjectMap.
	 */
	public static final ObjectMap EMPTY_MAP = new ObjectMap() {

		private static final long serialVersionUID = 1L;

		@Override /* Map */
		public Set<Map.Entry<String,Object>> entrySet() {
			return Collections.EMPTY_MAP.entrySet();
		}

		@Override /* Map */
		public Set<String> keySet() {
			return Collections.EMPTY_MAP.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();
		}
	};

	/**
	 * Construct an ObjectMap directly from a string using the specified parser.
	 *
	 * @param s The string being parsed.
	 * @param p The parser to use to parse the input.
	 * @throws ParseException If the input contains a syntax error or is malformed.
	 */
	public ObjectMap(CharSequence s, Parser p) throws ParseException {
		this(p == null ? null : p.createBeanSession());
		if (p == null)
			p = JsonParser.DEFAULT;
		if (! StringUtils.isEmpty(s))
			p.parseIntoMap(s, this, bs().string(), bs().object());
	}

	/**
	 * Shortcut for <code><jk>new</jk> ObjectMap(string,JsonParser.<jsf>DEFAULT</jsf>);</code>
	 *
	 * @param s The JSON text to parse.
	 * @throws ParseException If the input contains a syntax error or is malformed.
	 */
	public ObjectMap(CharSequence s) throws ParseException {
		this(s, null);
	}

	/**
	 * Construct an ObjectMap directly from a reader using the specified parser.
	 *
	 * @param r The reader to read from.  The reader will be wrapped in a {@link BufferedReader} if it isn't already.
	 * @param p The parser to use to parse the input.
	 * @throws ParseException If the input contains a syntax error or is malformed.
	 * @throws IOException If a problem occurred trying to read from the reader.
	 */
	public ObjectMap(Reader r, Parser p) throws ParseException, IOException {
		this(p == null ? null : p.createBeanSession());
		parseReader(r, p);
	}

	/**
	 * Shortcut for <code><jk>new</jk> ObjectMap(reader, JsonParser.<jsf>DEFAULT</jsf>)</code>.
	 *
	 * @param r The reader to read from.  The reader will be wrapped in a {@link BufferedReader} if it isn't already.
	 * @throws ParseException If the input contains a syntax error or is malformed.
	 * @throws IOException If a problem occurred trying to read from the reader.
	 */
	public ObjectMap(Reader r) throws ParseException, IOException {
		parseReader(r, JsonParser.DEFAULT);
	}

	private void parseReader(Reader r, Parser p) throws ParseException {
		if (p == null)
			p = JsonParser.DEFAULT;
		p.parseIntoMap(r, this, bs().string(), bs().object());
	}

	/**
	 * Construct an empty JSON object (an empty {@link LinkedHashMap}).
	 */
	public ObjectMap() {
	}

	/**
	 * Construct an empty JSON object (an empty {@link LinkedHashMap}) with the specified bean context.
	 *
	 * @param session The bean session to use for creating beans.
	 */
	public ObjectMap(BeanSession session) {
		this.session = session;
	}

	/**
	 * Construct a JSON object and fill it with the contents from the specified {@link Map}.
	 *
	 * @param m The map whose entries will be copied into this map.
	 */
	public ObjectMap(Map<?,?> m) {
		this();
		for (Map.Entry<?,?> e : m.entrySet())
			put(e.getKey().toString(), e.getValue());
	}

	/**
	 * 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'>
	 * 	ObjectMap m1 = <jk>new</jk> ObjectMap(<js>"{foo:1}"</js>);
	 * 	ObjectMap m2 = <jk>new</jk> ObjectMap().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 ObjectMap setInner(Map<String,Object> inner) {
		this.inner = inner;
		return this;
	}

	/**
	 * 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;
	}

	/**
	 * 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 ObjectMap setBeanSession(BeanSession session) {
		this.session = session;
		return this;
	}

	/**
	 * Returns the {@link BeanSession} currently associated with this map.
	 *
	 * @return The {@link BeanSession} currently associated with this map.
	 */
	public BeanSession getBeanSession() {
		return session;
	}

	/**
	 * Convenience method for adding an entry to this map.
	 *
	 * <p>
	 * Equivalent to calling {@code put(key, value)}, but returns this map so that the method can be chained.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public ObjectMap append(String key, Object value) {
		put(key, value);
		return this;
	}

	/**
	 * Conditionally appends a value 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 ObjectMap 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;
	}

	/**
	 * Conditionally appends a value to this map.
	 *
	 * @param flag The boolean value that must be <jk>true</jk> in order to add this entry..
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public ObjectMap appendIf(boolean flag, String key, Object value) {
		if (flag)
			put(key, value);
		return this;
	}

	/**
	 * Convenience method for adding an entry to this map.
	 *
	 * <p>
	 * A no-op if the value is <jk>null</jk> or an empty string/map/collection.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public ObjectMap appendSkipEmpty(String key, Object value) {
		return appendIf(true, true, true, key, value);
	}

	/**
	 * Convenience method for adding an entry to this map.
	 *
	 * <p>
	 * A no-op if the value is <jk>false</jk>.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public ObjectMap appendSkipFalse(String key, boolean value) {
		if (value)
			append(key, value);
		return this;
	}

	/**
	 * Convenience method for adding an entry to this map.
	 *
	 * <p>
	 * A no-op if the value is <c>-1</c>.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public ObjectMap appendSkipMinusOne(String key, Number value) {
		if (value != null && value.intValue() != -1)
			append(key, value);
		return this;
	}

	/**
	 * Convenience method for adding an entry to this map.
	 *
	 * <p>
	 * Equivalent to calling {@code put(key, value)}, but returns this map so that the method can be chained.
	 *
	 * <p>
	 * <jk>null</jk> values are skipped.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 */
	public ObjectMap appendSkipNull(String key, Object value) {
		if (value != null)
			append(key, value);
		return this;
	}

	/**
	 * Convenience method for adding a contents of another map to this map.
	 *
	 * <p>
	 * Equivalent to calling {@code putAll(m)}, but returns this map so that the method can be chained.
	 *
	 * @param m The map whose contents should be added to this map.
	 * @return This object (for method chaining).
	 */
	public ObjectMap appendAll(Map<String,Object> m) {
		if (m != null)
			putAll(m);
		return this;
	}

	@Override /* Map */
	public Object get(Object key) {
		Object o = super.get(key);
		if (o == null && inner != null)
			o = inner.get(key);
		return o;
	}

	/**
	 * 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'>
	 * 	ObjectMap m = <jk>new</jk> ObjectMap(<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'>
	 * 	ObjectMap m = <jk>new</jk> ObjectMap(<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.
	 *
	 * <h5 class='section'>Notes:</h5>
	 * <ul class='spaced-list'>
	 * 	<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;
	}


	/**
	 * 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 Thrown by the POJO swap if a problem occurred trying to parse the value.
	 */
	@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;
	}

	/**
	 * 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'>
	 * 	ObjectMap m = getObjectMap();
	 *
	 * 	<jc>// Long way</jc>
	 * 	<jk>long</jk> l = m.getObjectMap(<js>"foo"</js>).getObjectList(<js>"bar"</js>).getObjectMap(<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'>
	 * 	ObjectMap m = getObjectMap();
	 *
	 * 	<jc>// Long way</jc>
	 * 	m.getObjectMap(<js>"foo"</js>).getObjectList(<js>"bar"</js>).getObjectMap(<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'>
	 * 	ObjectMap m = getObjectMap();
	 *
	 * 	<jc>// Long way</jc>
	 * 	m.getObjectMap(<js>"foo"</js>).getObjectList(<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'>
	 * 	ObjectMap m = getObjectMap();
	 *
	 * 	<jc>// Long way</jc>
	 * 	m.getObjectMap(<js>"foo"</js>).getObjectList(<js>"bar"</js>).getObjectMap(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);
	}

	/**
	 * 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 If the input contains a syntax error or is malformed.
	 */
	public void putJson(String key, String json) throws ParseException {
		this.put(key, JsonParser.DEFAULT.parse(json, Object.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 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, Map.<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 Map<?,?> getMap(String key) {
		return get(key, Map.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link Map}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, Map.<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 Map<?,?> getMap(String key, Map<?,?> defVal) {
		return getWithDefault(key, defVal, Map.class);
	}

	/**
	 * Same as {@link #getMap(String, Map)} 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 List}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, List.<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 List<?> getList(String key) {
		return get(key, List.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link List}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, List.<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 List<?> getList(String key, List<?> defVal) {
		return getWithDefault(key, defVal, List.class);
	}

	/**
	 * Same as {@link #getList(String, List)} 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 specified entry value converted to a {@link Map}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, ObjectMap.<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 ObjectMap getObjectMap(String key) {
		return get(key, ObjectMap.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link ObjectMap}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, ObjectMap.<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 ObjectMap getObjectMap(String key, ObjectMap defVal) {
		return getWithDefault(key, defVal, ObjectMap.class);
	}

	/**
	 * Same as {@link #getObjectMap(String)} but creates a new empty {@link ObjectMap} if it doesn't already exist.
	 *
	 * @param key The key.
	 * @param createIfNotExists If mapping doesn't already exist, create one with an empty {@link ObjectMap}.
	 * @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 ObjectMap getObjectMap(String key, boolean createIfNotExists) {
		ObjectMap m = getWithDefault(key, null, ObjectMap.class);
		if (m == null && createIfNotExists) {
			m = new ObjectMap();
			put(key, m);
		}
		return m;
	}

	/**
	 * Returns the specified entry value converted to a {@link ObjectList}.
	 *
	 * <p>
	 * Shortcut for <code>get(key, ObjectList.<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 ObjectList getObjectList(String key) {
		return get(key, ObjectList.class);
	}

	/**
	 * Returns the specified entry value converted to a {@link ObjectList}.
	 *
	 * <p>
	 * Shortcut for <code>getWithDefault(key, defVal, ObjectList.<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 ObjectList getObjectList(String key, ObjectList defVal) {
		return getWithDefault(key, defVal, ObjectList.class);
	}

	/**
	 * Same as {@link #getObjectList(String)} but creates a new empty {@link ObjectList} if it doesn't already exist.
	 *
	 * @param key The key.
	 * @param createIfNotExists If mapping doesn't already exist, create one with an empty {@link ObjectList}.
	 * @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 ObjectList getObjectList(String key, boolean createIfNotExists) {
		ObjectList m = getWithDefault(key, null, ObjectList.class);
		if (m == null && createIfNotExists) {
			m = new ObjectList();
			put(key, m);
		}
		return m;
	}

	/**
	 * 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 Map}.
	 *
	 * <p>
	 * Shortcut for <code>find(Map.<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 Map<?,?> findMap(String... keys) {
		return find(Map.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link List}.
	 *
	 * <p>
	 * Shortcut for <code>find(List.<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 List<?> findList(String... keys) {
		return find(List.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link ObjectMap}.
	 *
	 * <p>
	 * Shortcut for <code>find(ObjectMap.<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 ObjectMap findObjectMap(String... keys) {
		return find(ObjectMap.class, keys);
	}

	/**
	 * Returns the first entry that exists converted to a {@link ObjectList}.
	 *
	 * <p>
	 * Shortcut for <code>find(ObjectList.<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 ObjectList findObjectList(String... keys) {
		return find(ObjectList.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 ObjectMap 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;
	}

	@Override /* Map */
	public boolean containsKey(Object key) {
		if (super.containsKey(key))
			return true;
		if (inner != null)
			return inner.containsKey(key);
		return false;
	}

	/**
	 * 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>ObjectMap</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 ObjectMap include(String...keys) {
		ObjectMap m2 = new ObjectMap();
		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>ObjectMap</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 ObjectMap exclude(String...keys) {
		ObjectMap m2 = new ObjectMap();
		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;
	}

	/**
	 * Sets a value in this map if the entry does not exist or the value is <jk>null</jk>.
	 *
	 * @param key The map key.
	 * @param val The value to set if the current value does not exist or is <jk>null</jk>.
	 * @return This object (for method chaining).
	 */
	public ObjectMap putIfNull(String key, Object val) {
		Object o = get(key);
		if (o == null)
			put(key, val);
		return this;
	}

	/**
	 * Sets a value in this map if the entry does not exist or the value is <jk>null</jk> or an empty string.
	 *
	 * @param key The map key.
	 * @param val 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 ObjectMap putIfEmpty(String key, Object val) {
		Object o = get(key);
		if (o == null || o.toString().isEmpty())
			put(key, val);
		return this;
	}

	/**
	 * Adds a mapping if the specified key doesn't exist.
	 *
	 * @param key The map key.
	 * @param val 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 ObjectMap putIfNotExists(String key, Object val) {
		if (! containsKey(key))
			put(key, val);
		return this;
	}

	/**
	 * 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);
	}

	/*
	 * 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 ObjectMap(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 ObjectMap)
							v = ((ObjectMap)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 ObjectMap)
							v = ((ObjectMap)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.innerClass,
				"Error occurred attempting to cast to an object of type ''{0}''", cm.innerClass.getName());
		}

		throw new BeanRuntimeException(cm.innerClass,
			"Cannot convert to class type ''{0}''.  Only beans and maps can be converted using this method.",
			cm.innerClass.getName());
	}

	private PojoRest getPojoRest() {
		if (pojoRest == null)
			pojoRest = new PojoRest(this);
		return pojoRest;
	}

	/**
	 * 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.
	 * @throws SerializeException If a problem occurred trying to convert the output.
	 */
	public String toString(WriterSerializer serializer) throws SerializeException {
		return serializer.serialize(this);
	}

	/**
	 * Serialize this object into a JSON string using the {@link JsonSerializer#DEFAULT} serializer.
	 */
	@Override /* Object */
	public String toString() {
		try {
			return this.toString(SimpleJsonSerializer.DEFAULT);
		} catch (SerializeException e) {
			return e.getLocalizedMessage();
		}
	}

	/**
	 * 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 ObjectMap serializeTo(Writer w) throws IOException, SerializeException {
		JsonSerializer.DEFAULT.serialize(this);
		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 ObjectMap modifiable() {
		if (isUnmodifiable())
			return new ObjectMap(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 ObjectMap unmodifiable() {
		if (this instanceof UnmodifiableObjectMap)
			return this;
		return new UnmodifiableObjectMap(this);
	}

	@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();
			}
		};
	}

	private static final class UnmodifiableObjectMap extends ObjectMap {
		private static final long serialVersionUID = 1L;

		UnmodifiableObjectMap(ObjectMap 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("ObjectMap is read-only.");
		}

		@Override
		public final Object remove(Object key) {
			throw new UnsupportedOperationException("ObjectMap is read-only.");
		}

		@Override
		public final boolean isUnmodifiable() {
			return true;
		}
	}

	private BeanSession bs() {
		if (session == null)
			session = BeanContext.DEFAULT.createBeanSession();
		return session;
	}
}
