// ***************************************************************************************************************************
// * 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.<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();
		}
	};

	/**
	 * 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 Malformed input encountered.
	 */
	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());
	}

	/**
	 * Static constructor from JSON string.
	 *
	 * @param s JSON initialization string.  Can be <jk>null</jk>.
	 * @return A new {@link ObjectMap} object, or <jk>null</jk> if the input is <jk>null</jk>.
	 * @throws ParseException Invalid JSON string.
	 */
	public static ObjectMap parse(CharSequence s) throws ParseException {
		return s == null ? null : new ObjectMap(s);
	}

	/**
	 * Shortcut for <code><jk>new</jk> ObjectMap(string,JsonParser.<jsf>DEFAULT</jsf>);</code>
	 *
	 * @param s The JSON text to parse.
	 * @throws ParseException Malformed input encountered.
	 */
	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 Malformed input encountered.
	 * @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();
		if (m != null)
			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.
	 *
	 * <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;
	}


	/**
	 * 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;
	}

	/**
	 * 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 Malformed input encountered.
	 */
	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;
	}
}
