// ***************************************************************************************************************************
// * 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.config;

import static org.apache.juneau.config.ConfigMod.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ThrowableUtils.*;

import java.beans.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.config.encode.*;
import org.apache.juneau.config.encode.ConfigEncoder;
import org.apache.juneau.config.event.*;
import org.apache.juneau.config.internal.*;
import org.apache.juneau.config.store.*;
import org.apache.juneau.config.vars.*;
import org.apache.juneau.http.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.svl.*;

/**
 * Main configuration API class.
 *
 * <ul class='seealso'>
 * 	<li class='link'>{@doc juneau-config}
 * 	<li class='extlink'>{@source}
 * </ul>
 */
@ConfigurableContext
public final class Config extends Context implements ConfigEventListener, Writable {

	private static boolean DISABLE_AUTO_SYSTEM_PROPS = Boolean.getBoolean("juneau.disableAutoSystemProps");
	private static volatile Config SYSTEM_DEFAULT = findSystemDefault();

	/**
	 * Sets a system default configuration.
	 *
	 * @param systemDefault The new system default configuration.
	 */
	public synchronized static void setSystemDefault(Config systemDefault) {
		SYSTEM_DEFAULT = systemDefault;
	}

	/**
	 * Returns the system default configuration.
	 *
	 * @return The system default configuration, or <jk>null</jk> if it doesn't exist.
	 */
	public synchronized static Config getSystemDefault() {
		return SYSTEM_DEFAULT;
	}

	private synchronized static Config findSystemDefault() {

		for (String n : getCandidateSystemDefaultConfigNames()) {
			Config config = find(n);
			if (config != null) {
				if (! DISABLE_AUTO_SYSTEM_PROPS)
					config.setSystemProperties();
				return config;
			}
		}

		return null;
	}

	/**
	 * Returns the list of candidate system default configuration file names.
	 *
	 * <p>
	 * If the <js>"juneau.configFile"</js> system property is set, returns a singleton of that value.
	 * <br>Otherwise, returns a list consisting of the following values:
	 * <ol>
	 * 	<li>File with same name as jar file but with <js>".cfg"</js> extension.  (e.g. <js>"myjar.cfg"</js>)
	 * 	<li>Any file ending in <js>".cfg"</js> in the home directory (names ordered alphabetically).
	 * 	<li><js>"juneau.cfg"</js>
	 * 	<li><js>"default.cfg"</js>
	 * 	<li><js>"application.cfg"</js>
	 * 	<li><js>"app.cfg"</js>
	 * 	<li><js>"settings.cfg"</js>
	 * 	<li><js>"application.properties"</js>
	 * </ol>
	 * <p>
	 *
	 * @return
	 * 	A list of candidate file names.
	 * 	<br>The returned list is modifiable.
	 * 	<br>Each call constructs a new list.
	 */
	public synchronized static List<String> getCandidateSystemDefaultConfigNames() {
		List<String> l = new ArrayList<>();

		String s = System.getProperty("juneau.configFile");
		if (s != null) {
			l.add(s);
			return l;
		}

		String cmd = System.getProperty("sun.java.command", "not_found").split("\\s+")[0];
		if (cmd.endsWith(".jar") && ! cmd.contains("surefirebooter")) {
			cmd = cmd.replaceAll(".*?([^\\\\\\/]+)\\.jar$", "$1");
			l.add(cmd + ".cfg");
			cmd = cmd.replaceAll("[\\.\\_].*$", "");  // Try also without version in jar name.
			l.add(cmd + ".cfg");
		}

		Set<File> files = new TreeSet<>(Arrays.asList(new File(".").listFiles()));
		for (File f : files)
			if (f.getName().endsWith(".cfg"))
				l.add(f.getName());

		l.add("juneau.cfg");
		l.add("default.cfg");
		l.add("application.cfg");
		l.add("app.cfg");
		l.add("settings.cfg");
		l.add("application.properties");

		return l;
	}

	private synchronized static Config find(String name) {
		if (name == null)
			return null;
		if (ConfigFileStore.DEFAULT.exists(name))
			return Config.create(name).store(ConfigFileStore.DEFAULT).build();
		if (ConfigClasspathStore.DEFAULT.exists(name))
			return Config.create(name).store(ConfigClasspathStore.DEFAULT).build();
		return null;
	}

	//-------------------------------------------------------------------------------------------------------------------
	// Configurable properties
	//-------------------------------------------------------------------------------------------------------------------

	static final String PREFIX = "Config";

	/**
	 * Configuration property:  Configuration name.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_name CONFIG_name}
	 * 	<li><b>Name:</b>  <js>"Config.name.s"</js>
	 * 	<li><b>Data type:</b>  <c>String</c>
	 * 	<li><b>System property:</b>  <c>Config.name</c>
	 * 	<li><b>Environment variable:</b>  <c>CONFIG_NAME</c>
	 * 	<li><b>Default:</b>  <js>"Configuration.cfg"</js>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigBuilder#name(String)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * Specifies the configuration name.
	 * <br>This is typically the configuration file name, although
	 * the name can be anything identifiable by the {@link ConfigStore} used for retrieving and storing the configuration.
	 */
	public static final String CONFIG_name = PREFIX + ".name.s";

	/**
	 * Configuration property:  Configuration store.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_store CONFIG_store}
	 * 	<li><b>Name:</b>  <js>"Config.store.o"</js>
	 * 	<li><b>Data type:</b>  {@link org.apache.juneau.config.store.ConfigStore}
	 * 	<li><b>Default:</b>  {@link org.apache.juneau.config.store.ConfigFileStore#DEFAULT}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#store(ConfigStore)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * The configuration store used for retrieving and storing configurations.
	 */
	public static final String CONFIG_store = PREFIX + ".store.o";

	/**
	 * Configuration property:  POJO serializer.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_serializer CONFIG_serializer}
	 * 	<li><b>Name:</b>  <js>"Config.serializer.o"</js>
	 * 	<li><b>Data type:</b>  {@link org.apache.juneau.serializer.WriterSerializer}
	 * 	<li><b>Default:</b>  {@link org.apache.juneau.json.SimpleJsonSerializer#DEFAULT}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#serializer(Class)}
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#serializer(WriterSerializer)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * The serializer to use for serializing POJO values.
	 */
	public static final String CONFIG_serializer = PREFIX + ".serializer.o";

	/**
	 * Configuration property:  POJO parser.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_parser CONFIG_parser}
	 * 	<li><b>Name:</b>  <js>"Config.parser.o"</js>
	 * 	<li><b>Data type:</b>  {@link org.apache.juneau.parser.ReaderParser}
	 * 	<li><b>Default:</b>  {@link org.apache.juneau.json.JsonParser#DEFAULT}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#parser(Class)}
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#parser(ReaderParser)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * The parser to use for parsing values to POJOs.
	 */
	public static final String CONFIG_parser = PREFIX + ".parser.o";

	/**
	 * Configuration property:  Value encoder.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_encoder CONFIG_encoder}
	 * 	<li><b>Name:</b>  <js>"Config.encoder.o"</js>
	 * 	<li><b>Data type:</b>  {@link org.apache.juneau.config.encode.ConfigEncoder}
	 * 	<li><b>Default:</b>  {@link org.apache.juneau.config.encode.ConfigXorEncoder#INSTANCE}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#encoder(Class)}
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#encoder(ConfigEncoder)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * The encoder to use for encoding encoded configuration values.
	 */
	public static final String CONFIG_encoder = PREFIX + ".encoder.o";

	/**
	 * Configuration property:  SVL variable resolver.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_varResolver CONFIG_varResolver}
	 * 	<li><b>Name:</b>  <js>"Config.varResolver.o"</js>
	 * 	<li><b>Data type:</b>  {@link org.apache.juneau.svl.VarResolver}
	 * 	<li><b>Default:</b>  {@link org.apache.juneau.svl.VarResolver#DEFAULT}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#varResolver(Class)}
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#varResolver(VarResolver)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * The resolver to use for resolving SVL variables.
	 */
	public static final String CONFIG_varResolver = PREFIX + ".varResolver.o";

	/**
	 * Configuration property:  Binary value line length.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_binaryLineLength CONFIG_binaryLineLength}
	 * 	<li><b>Name:</b>  <js>"Config.binaryLineLength.i"</js>
	 * 	<li><b>Data type:</b>  <jk>int</jk>
	 * 	<li><b>System property:</b>  <c>Config.binaryLineLength</c>
	 * 	<li><b>Environment variable:</b>  <c>CONFIG_BINARYLINELENGTH</c>
	 * 	<li><b>Default:</b>  <c>-1</c>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#binaryLineLength(int)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * When serializing binary values, lines will be split after this many characters.
	 * <br>Use <c>-1</c> to represent no line splitting.
	 */
	public static final String CONFIG_binaryLineLength = PREFIX + ".binaryLineLength.i";

	/**
	 * Configuration property:  Binary value format.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_binaryFormat CONFIG_binaryFormat}
	 * 	<li><b>Name:</b>  <js>"Config.binaryFormat.s"</js>
	 * 	<li><b>Data type:</b>  {@link org.apache.juneau.BinaryFormat}
	 * 	<li><b>System property:</b>  <c>Config.binaryFormat</c>
	 * 	<li><b>Environment variable:</b>  <c>CONFIG_BINARYFORMAT</c>
	 * 	<li><b>Default:</b>  {@link org.apache.juneau.BinaryFormat#BASE64}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#binaryFormat(BinaryFormat)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * The format to use when persisting byte arrays.
	 *
	 * <p>
	 * Possible values:
	 * <ul>
	 * 	<li>{@link BinaryFormat#BASE64} - BASE64-encoded string.
	 * 	<li>{@link BinaryFormat#HEX} - Hexadecimal.
	 * 	<li>{@link BinaryFormat#SPACED_HEX} - Hexadecimal with spaces between bytes.
	 * </ul>
	 */
	public static final String CONFIG_binaryFormat = PREFIX + ".binaryFormat.s";

	/**
	 * Configuration property:  Multi-line values should always be on separate lines.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_multiLineValuesOnSeparateLines CONFIG_multiLineValuesOnSeparateLines}
	 * 	<li><b>Name:</b>  <js>"Config.multiLineValuesOnSeparateLines.b"</js>
	 * 	<li><b>Data type:</b>  <jk>boolean</jk>
	 * 	<li><b>System property:</b>  <c>Config.multiLineValuesOnSeparateLine</c>
	 * 	<li><b>Environment variable:</b>  <c>CONFIG_MULTILINEVALUESONSEPARATELINE</c>
	 * 	<li><b>Default:</b>  <jk>false</jk>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#multiLineValuesOnSeparateLines()}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * When enabled, multi-line values will always be placed on a separate line from the key.
	 */
	public static final String CONFIG_multiLineValuesOnSeparateLines = PREFIX + ".multiLineValuesOnSeparateLines.b";

	/**
	 * Configuration property:  Read-only.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul class='spaced-list'>
	 * 	<li><b>ID:</b>  {@link org.apache.juneau.config.Config#CONFIG_readOnly CONFIG_readOnly}
	 * 	<li><b>Name:</b>  <js>"Config.readOnly.b"</js>
	 * 	<li><b>Data type:</b>  <jk>boolean</jk>
	 * 	<li><b>System property:</b>  <c>Config.readOnly</c>
	 * 	<li><b>Environment variable:</b>  <c>CONFIG_READONLY</c>
	 * 	<li><b>Default:</b>  <jk>false</jk>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link org.apache.juneau.config.ConfigBuilder#readOnly()}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * When enabled, attempts to call any setters on this object will throw an {@link UnsupportedOperationException}.
	 */
	public static final String CONFIG_readOnly = PREFIX + ".readOnly.b";

	//-------------------------------------------------------------------------------------------------------------------
	// Instance
	//-------------------------------------------------------------------------------------------------------------------

	private final String name;
	private final ConfigStore store;
	private final WriterSerializer serializer;
	private final ReaderParser parser;
	private final ConfigEncoder encoder;
	private final VarResolverSession varSession;
	private final int binaryLineLength;
	private final BinaryFormat binaryFormat;
	private final boolean multiLineValuesOnSeparateLines, readOnly;
	private final ConfigMap configMap;
	private final BeanSession beanSession;
	private final List<ConfigEventListener> listeners = Collections.synchronizedList(new LinkedList<ConfigEventListener>());


	/**
	 * Instantiates a new clean-slate {@link ConfigBuilder} object.
	 *
	 * <p>
	 * This is equivalent to simply calling <code><jk>new</jk> ConfigBuilder()</code>.
	 *
	 * @return A new {@link ConfigBuilder} object.
	 */
	public static ConfigBuilder create() {
		return new ConfigBuilder();
	}

	/**
	 * Same as {@link #create()} but initializes the builder with the specified config name.
	 *
	 * <p>
	 * This is equivalent to simply calling <code><jk>new</jk> ConfigBuilder().name(name)</code>.
	 *
	 * @param name The configuration name.
	 * @return A new {@link ConfigBuilder} object.
	 */
	public static ConfigBuilder create(String name) {
		return new ConfigBuilder().name(name);
	}

	@Override /* Context */
	public ConfigBuilder builder() {
		return new ConfigBuilder(getPropertyStore());
	}

	/**
	 * Constructor.
	 *
	 * @param ps
	 * 	The property store containing all the settings for this object.
	 * @throws IOException Thrown by underlying stream.
	 */
	public Config(PropertyStore ps) throws IOException {
		super(ps, true);

		name = getStringProperty(CONFIG_name, "Configuration.cfg");
		store = getInstanceProperty(CONFIG_store, ConfigStore.class, ConfigFileStore.DEFAULT);
		configMap = store.getMap(name);
		configMap.register(this);
		serializer = getInstanceProperty(CONFIG_serializer, WriterSerializer.class, SimpleJsonSerializer.DEFAULT);
		parser = getInstanceProperty(CONFIG_parser, ReaderParser.class, JsonParser.DEFAULT);
		beanSession = parser.createBeanSession();
		encoder = getInstanceProperty(CONFIG_encoder, ConfigEncoder.class, ConfigXorEncoder.INSTANCE);
		varSession = getInstanceProperty(CONFIG_varResolver, VarResolver.class, VarResolver.DEFAULT)
			.builder()
			.vars(ConfigVar.class)
			.contextObject(ConfigVar.SESSION_config, this)
			.build()
			.createSession();
		binaryLineLength = getIntegerProperty(CONFIG_binaryLineLength, -1);
		binaryFormat = getProperty(CONFIG_binaryFormat, BinaryFormat.class, BinaryFormat.BASE64);
		multiLineValuesOnSeparateLines = getBooleanProperty(CONFIG_multiLineValuesOnSeparateLines, false);
		readOnly = getBooleanProperty(CONFIG_readOnly, false);
	}

	Config(Config copyFrom, VarResolverSession varSession) {
		super(null, true);
		name = copyFrom.name;
		store = copyFrom.store;
		configMap = copyFrom.configMap;
		configMap.register(this);
		serializer = copyFrom.serializer;
		parser = copyFrom.parser;
		encoder = copyFrom.encoder;
		this.varSession = varSession;
		binaryLineLength = copyFrom.binaryLineLength;
		binaryFormat = copyFrom.binaryFormat;
		multiLineValuesOnSeparateLines = copyFrom.multiLineValuesOnSeparateLines;
		readOnly = copyFrom.readOnly;
		beanSession = copyFrom.beanSession;
	}

	/**
	 * Creates a copy of this config using the specified var session for resolving variables.
	 *
	 * <p>
	 * This creates a shallow copy of the config but replacing the variable resolver.
	 *
	 * @param varSession The var session used for resolving string variables.
	 * @return A new config object.
	 */
	public Config resolving(VarResolverSession varSession) {
		return new Config(this, varSession);
	}

	/**
	 * Returns the name associated with this config (usually a file name).
	 *
	 * @return The name associated with this config, or <jk>null</jk> if it has no name.
	 */
	public String getName() {
		return name;
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Workhorse getters
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Returns the specified value as a string from the config file.
	 *
	 * <p>
	 * Unlike {@link #getString(String)}, this method doesn't replace SVL variables.
	 *
	 * @param key The key.
	 * @return The value, or <jk>null</jk> if the section or value doesn't exist.
	 */
	public String get(String key) {

		String sname = sname(key);
		String skey = skey(key);

		ConfigEntry ce = configMap.getEntry(sname, skey);

		if (ce == null || ce.getValue() == null)
			return null;

		String val = ce.getValue();
		for (ConfigMod m : ConfigMod.asModifiersReverse(ce.getModifiers())) {
			if (m == ENCODED) {
				if (encoder.isEncoded(val))
					val = encoder.decode(key, val);
			}
		}

		return val;
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Utility methods
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Takes the settings defined in this configuration and sets them as system properties.
	 *
	 * @return This object (for method chaining).
	 */
	public Config setSystemProperties() {
		for (String section : getSections()) {
			for (String key : getKeys(section)) {
				String k = (section.isEmpty() ? key : section + '/' + key);
				System.setProperty(k, get(k));
			}
		}
		return this;
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Workhorse setters
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Sets a value in this config.
	 *
	 * @param key The key.
	 * @param value The value.
	 * @return This object (for method chaining).
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config set(String key, String value) {
		checkWrite();
		assertFieldNotNull(key, "key");
		String sname = sname(key);
		String skey = skey(key);

		ConfigEntry ce = configMap.getEntry(sname, skey);
		if (ce == null && value == null)
			return this;

		String mod = ce == null ? "" : ce.getModifiers();

		String s = stringify(value);
		for (ConfigMod m : ConfigMod.asModifiers(mod)) {
			if (m == ENCODED) {
				s = encoder.encode(key, s);
			}
		}

		configMap.setEntry(sname, skey, s, null, null, null);
		return this;
	}

	/**
	 * Adds or replaces an entry with the specified key with a POJO serialized to a string using the registered
	 * serializer.
	 *
	 * <p>
	 * Equivalent to calling <c>put(key, value, isEncoded(key))</c>.
	 *
	 * @param key The key.
	 * @param value The new value POJO.
	 * @return The previous value, or <jk>null</jk> if the section or key did not previously exist.
	 * @throws SerializeException
	 * 	If serializer could not serialize the value or if a serializer is not registered with this config file.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config set(String key, Object value) throws SerializeException {
		return set(key, value, null);
	}

	/**
	 * Same as {@link #set(String, Object)} but allows you to specify the serializer to use to serialize the
	 * value.
	 *
	 * @param key The key.
	 * @param value The new value.
	 * @param serializer
	 * 	The serializer to use for serializing the object.
	 * 	If <jk>null</jk>, then uses the predefined serializer on the config file.
	 * @return The previous value, or <jk>null</jk> if the section or key did not previously exist.
	 * @throws SerializeException
	 * 	If serializer could not serialize the value or if a serializer is not registered with this config file.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config set(String key, Object value, Serializer serializer) throws SerializeException {
		return set(key, serialize(value, serializer));
	}

	/**
	 * Same as {@link #set(String, Object)} but allows you to specify all aspects of a value.
	 *
	 * @param key The key.
	 * @param value The new value.
	 * @param serializer
	 * 	The serializer to use for serializing the object.
	 * 	If <jk>null</jk>, then uses the predefined serializer on the config file.
	 * @param modifier
	 * 	Optional modifier to apply to the value.
	 * 	<br>If <jk>null</jk>, then previous value will not be replaced.
	 * @param comment
	 * 	Optional same-line comment to add to this value.
	 * 	<br>If <jk>null</jk>, then previous value will not be replaced.
	 * @param preLines
	 * 	Optional comment or blank lines to add before this entry.
	 * 	<br>If <jk>null</jk>, then previous value will not be replaced.
	 * @return The previous value, or <jk>null</jk> if the section or key did not previously exist.
	 * @throws SerializeException
	 * 	If serializer could not serialize the value or if a serializer is not registered with this config file.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config set(String key, Object value, Serializer serializer, ConfigMod modifier, String comment, List<String> preLines) throws SerializeException {
		return set(key, value, serializer, modifier == null ? null : new ConfigMod[]{modifier}, comment, preLines);
	}

	/**
	 * Same as {@link #set(String, Object)} but allows you to specify all aspects of a value.
	 *
	 * @param key The key.
	 * @param value The new value.
	 * @param serializer
	 * 	The serializer to use for serializing the object.
	 * 	If <jk>null</jk>, then uses the predefined serializer on the config file.
	 * @param modifiers
	 * 	Optional modifiers to apply to the value.
	 * 	<br>If <jk>null</jk>, then previous value will not be replaced.
	 * @param comment
	 * 	Optional same-line comment to add to this value.
	 * 	<br>If <jk>null</jk>, then previous value will not be replaced.
	 * @param preLines
	 * 	Optional comment or blank lines to add before this entry.
	 * 	<br>If <jk>null</jk>, then previous value will not be replaced.
	 * @return The previous value, or <jk>null</jk> if the section or key did not previously exist.
	 * @throws SerializeException
	 * 	If serializer could not serialize the value or if a serializer is not registered with this config file.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config set(String key, Object value, Serializer serializer, ConfigMod[] modifiers, String comment, List<String> preLines) throws SerializeException {
		checkWrite();
		assertFieldNotNull(key, "key");
		String sname = sname(key);
		String skey = skey(key);

		String s = serialize(value, serializer);
		if (modifiers != null) {
			for (ConfigMod m : modifiers) {
				if (m == ENCODED) {
					s = encoder.encode(key, s);
				}
			}
		}

		configMap.setEntry(sname, skey, s, modifiers == null ? null : ConfigMod.asString(modifiers), comment, preLines);
		return this;
	}

	/**
	 * Removes an entry with the specified key.
	 *
	 * @param key The key.
	 * @return The previous value, or <jk>null</jk> if the section or key did not previously exist.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config remove(String key) {
		checkWrite();
		String sname = sname(key);
		String skey = skey(key);
		configMap.removeEntry(sname, skey);
		return this;
	}

	/**
	 * Encodes and unencoded entries in this config.
	 *
	 * <p>
	 * If any entries in the config are marked as encoded but not actually encoded,
	 * this will encode them.
	 *
	 * @return This object (for method chaining).
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config encodeEntries() {
		checkWrite();
		for (String section : configMap.getSections()) {
			for (String key : configMap.getKeys(section)) {
				ConfigEntry ce = configMap.getEntry(section, key);
				if (ce != null && ce.hasModifier('*') && ! encoder.isEncoded(ce.getValue())) {
					configMap.setEntry(section, key, encoder.encode(section + '/' + key, ce.getValue()), null, null, null);
				}
			}
		}

		return this;
	}

	//-----------------------------------------------------------------------------------------------------------------
	// API methods
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Gets the entry with the specified key.
	 *
	 * <p>
	 * The key can be in one of the following formats...
	 * <ul class='spaced-list'>
	 * 	<li>
	 * 		<js>"key"</js> - A value in the default section (i.e. defined above any <c>[section]</c> header).
	 * 	<li>
	 * 		<js>"section/key"</js> - A value from the specified section.
	 * </ul>
	 *
	 * @param key The key.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public String getString(String key) {
		String s = get(key);
		if (s == null)
			return null;
		if (varSession != null)
			s = varSession.resolve(s);
		return s;
	}

	/**
	 * Gets the entry with the specified key.
	 *
	 * <p>
	 * The key can be in one of the following formats...
	 * <ul class='spaced-list'>
	 * 	<li>
	 * 		<js>"key"</js> - A value in the default section (i.e. defined above any <c>[section]</c> header).
	 * 	<li>
	 * 		<js>"section/key"</js> - A value from the specified section.
	 * </ul>
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the section or key does not exist.
	 */
	public String getString(String key, String def) {
		String s = get(key);
		if (isEmpty(s))
			return def;
		if (varSession != null)
			s = varSession.resolve(s);
		return s;
	}

	/**
	 * Gets the entry with the specified key, splits the value on commas, and returns the values as trimmed strings.
	 *
	 * @param key The key.
	 * @return The value, or an empty array if the section or key does not exist.
	 */
	public String[] getStringArray(String key) {
		return getStringArray(key, new String[0]);
	}

	/**
	 * Same as {@link #getStringArray(String)} but returns a default value if the value cannot be found.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the section or key does not exist or is blank.
	 */
	public String[] getStringArray(String key, String[] def) {
		String s = getString(key);
		if (isEmpty(s))
			return def;
		String[] r = split(s);
		return r.length == 0 ? def : r;
	}

	/**
	 * Convenience method for getting int config values.
	 *
	 * <p>
	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <ul class='spaced-list'>
	 * 	<li>
	 * 		<code><js>"100K"</js> => 1024000</code>
	 * 	<li>
	 * 		<code><js>"100M"</js> => 104857600</code>
	 * </ul>
	 *
	 * <p>
	 * Uses {@link Integer#decode(String)} underneath, so any of the following integer formats are supported:
	 * <ul>
	 * 	<li><js>"0x..."</js>
	 * 	<li><js>"0X..."</js>
	 * 	<li><js>"#..."</js>
	 * 	<li><js>"0..."</js>
	 * </ul>
	 *
	 * @param key The key.
	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
	 */
	public int getInt(String key) {
		return getInt(key, 0);
	}

	/**
	 * Same as {@link #getInt(String)} but returns a default value if not set.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the value does not exist or the value is empty.
	 */
	public int getInt(String key, int def) {
		String s = getString(key);
		if (isEmpty(s))
			return def;
		return parseIntWithSuffix(s);
	}

	/**
	 * Convenience method for getting boolean config values.
	 *
	 * @param key The key.
	 * @return The value, or <jk>false</jk> if the section or key does not exist or cannot be parsed as a boolean.
	 */
	public boolean getBoolean(String key) {
		return getBoolean(key, false);
	}

	/**
	 * Convenience method for getting boolean config values.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the section or key does not exist or cannot be parsed as a boolean.
	 */
	public boolean getBoolean(String key, boolean def) {
		String s = getString(key);
		return isEmpty(s) ? def : Boolean.parseBoolean(s);
	}

	/**
	 * Convenience method for getting long config values.
	 *
	 * <p>
	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
	 *
	 * <h5 class='section'>Example:</h5>
	 * <ul class='spaced-list'>
	 * 	<li>
	 * 		<code><js>"100K"</js> => 1024000</code>
	 * 	<li>
	 * 		<code><js>"100M"</js> => 104857600</code>
	 * </ul>
	 *
	 * <p>
	 * Uses {@link Long#decode(String)} underneath, so any of the following number formats are supported:
	 * <ul>
	 * 	<li><js>"0x..."</js>
	 * 	<li><js>"0X..."</js>
	 * 	<li><js>"#..."</js>
	 * 	<li><js>"0..."</js>
	 * </ul>
	 *
	 * @param key The key.
	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
	 */
	public long getLong(String key) {
		return getLong(key, 0);
	}

	/**
	 * Same as {@link #getLong(String)} but returns a default value if not set.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the value does not exist or the value is empty.
	 */
	public long getLong(String key, long def) {
		String s = getString(key);
		if (isEmpty(s))
			return def;
		return parseLongWithSuffix(s);
	}

	/**
	 * Convenience method for getting double config values.
	 *
	 * <p>
	 * Uses {@link Double#valueOf(String)} underneath, so any of the following number formats are supported:
	 * <ul>
	 * 	<li><js>"0x..."</js>
	 * 	<li><js>"0X..."</js>
	 * 	<li><js>"#..."</js>
	 * 	<li><js>"0..."</js>
	 * </ul>
	 *
	 * @param key The key.
	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
	 */
	public double getDouble(String key) {
		return getDouble(key, 0);
	}

	/**
	 * Same as {@link #getDouble(String)} but returns a default value if not set.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the value does not exist or the value is empty.
	 */
	public double getDouble(String key, double def) {
		String s = getString(key);
		if (isEmpty(s))
			return def;
		return Double.valueOf(s);
	}

	/**
	 * Convenience method for getting float config values.
	 *
	 * <p>
	 * Uses {@link Float#valueOf(String)} underneath, so any of the following number formats are supported:
	 * <ul>
	 * 	<li><js>"0x..."</js>
	 * 	<li><js>"0X..."</js>
	 * 	<li><js>"#..."</js>
	 * 	<li><js>"0..."</js>
	 * </ul>
	 *
	 * @param key The key.
	 * @return The value, or <c>0</c> if the value does not exist or the value is empty.
	 */
	public float getFloat(String key) {
		return getFloat(key, 0);
	}

	/**
	 * Same as {@link #getFloat(String)} but returns a default value if not set.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the value does not exist or the value is empty.
	 */
	public float getFloat(String key, float def) {
		String s = getString(key);
		if (isEmpty(s))
			return def;
		return Float.valueOf(s);
	}

	/**
	 * Convenience method for getting byte array config values.
	 *
	 * <p>
	 * This is equivalent to calling the following:
	 * <p class='bcode w800'>
	 * 	<jk>byte</jk>[] b = config.getObject(key, <jk>byte</jk>[].<jk>class</jk>);
	 * </p>
	 *
	 * <p>
	 * Byte arrays are stored as encoded strings, typically BASE64, but dependent on the {@link #CONFIG_binaryFormat} setting.
	 *
	 * @param key The key.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 * @throws ParseException If value could not be converted to a byte array.
	 */
	public byte[] getBytes(String key) throws ParseException {
		String s = get(key);
		if (s == null)
			return null;
		if (s.isEmpty())
			return new byte[0];
		return getObject(key, byte[].class);
	}

	/**
	 * Same as {@link #getBytes(String)} but with a default value if the entry doesn't exist.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @return The value, or the default value if the section or key does not exist.
	 * @throws ParseException If value could not be converted to a byte array.
	 */
	public byte[] getBytes(String key, byte[] def) throws ParseException {
		String s = get(key);
		if (s == null)
			return def;
		if (s.isEmpty())
			return def;
		return getObjectWithDefault(key, def, byte[].class);
	}

	/**
	 * Gets the entry with the specified key and converts it to the specified value.
	 *
	 * <p>
	 * The key can be in one of the following formats...
	 * <ul class='spaced-list'>
	 * 	<li>
	 * 		<js>"key"</js> - A value in the default section (i.e. defined above any <c>[section]</c> header).
	 * 	<li>
	 * 		<js>"section/key"</js> - A value from the specified section.
	 * </ul>
	 *
	 * <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'>
	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
	 *
	 * 	<jc>// Parse into a linked-list of strings.</jc>
	 * 	List l = cf.getObject(<js>"MySection/myListOfStrings"</js>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a linked-list of beans.</jc>
	 * 	List l = cf.getObject(<js>"MySection/myListOfBeans"</js>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
	 * 	List l = cf.getObject(<js>"MySection/my2dListOfStrings"</js>, LinkedList.<jk>class</jk>,
	 * 		LinkedList.<jk>class</jk>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a map of string keys/values.</jc>
	 * 	Map m = cf.getObject(<js>"MySection/myMap"</js>, TreeMap.<jk>class</jk>, String.<jk>class</jk>,
	 * 		String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
	 * 	Map m = cf.getObject(<js>"MySection/myMapOfListsOfBeans"</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.
	 *
	 * <ul class='notes'>
	 * 	<li>
	 * 		Use the {@link #getObject(String, Class)} method instead if you don't need a parameterized map/collection.
	 * </ul>
	 *
	 * @param key The key.
	 * @param type
	 * 	The object type to create.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * @param args
	 * 	The type arguments of the class if it's a collection or map.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * 	<br>Ignored if the main type is not a map or collection.
	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public <T> T getObject(String key, Type type, Type...args) throws ParseException {
		return getObject(key, (Parser)null, type, args);
	}

	/**
	 * Same as {@link #getObject(String, Type, Type...)} but allows you to specify the parser to use to parse the value.
	 *
	 * @param key The key.
	 * @param parser
	 * 	The parser to use for parsing the object.
	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
	 * @param type
	 * 	The object type to create.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * @param args
	 * 	The type arguments of the class if it's a collection or map.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * 	<br>Ignored if the main type is not a map or collection.
	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public <T> T getObject(String key, Parser parser, Type type, Type...args) throws ParseException {
		assertFieldNotNull(type, "type");
		return parse(getString(key), parser, type, args);
	}

	/**
	 * Same as {@link #getObject(String, Type, Type...)} except optimized for a non-parameterized class.
	 *
	 * <p>
	 * This is the preferred parse method for simple types since you don't need to cast the results.
	 *
	 * <h5 class='section'>Examples:</h5>
	 * <p class='bcode w800'>
	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
	 *
	 * 	<jc>// Parse into a string.</jc>
	 * 	String s = cf.getObject(<js>"MySection/mySimpleString"</js>, String.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a bean.</jc>
	 * 	MyBean b = cf.getObject(<js>"MySection/myBean"</js>, MyBean.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a bean array.</jc>
	 * 	MyBean[] b = cf.getObject(<js>"MySection/myBeanArray"</js>, MyBean[].<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a linked-list of objects.</jc>
	 * 	List l = cf.getObject(<js>"MySection/myList"</js>, LinkedList.<jk>class</jk>);
	 *
	 * 	<jc>// Parse into a map of object keys/values.</jc>
	 * 	Map m = cf.getObject(<js>"MySection/myMap"</js>, TreeMap.<jk>class</jk>);
	 * </p>
	 *
	 * @param <T> The class type of the object being created.
	 * @param key The key.
	 * @param type The object type to create.
	 * @return The parsed object.
	 * @throws ParseException Malformed input encountered.
	 * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
	 */
	public <T> T getObject(String key, Class<T> type) throws ParseException {
		return getObject(key, (Parser)null, type);
	}

	/**
	 * Same as {@link #getObject(String, Class)} but allows you to specify the parser to use to parse the value.
	 *
	 * @param <T> The class type of the object being created.
	 * @param key The key.
	 * @param parser
	 * 	The parser to use for parsing the object.
	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
	 * @param type The object type to create.
	 * @return The parsed object.
	 * @throws ParseException Malformed input encountered.
	 * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
	 */
	public <T> T getObject(String key, Parser parser, Class<T> type) throws ParseException {
		assertFieldNotNull(type, "c");
		return parse(getString(key), parser, type);
	}

	/**
	 * Gets the entry with the specified key and converts it to the specified value.
	 *
	 * <p>
	 * Same as {@link #getObject(String, Class)}, but with a default value.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @param type The class to convert the value to.
	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public <T> T getObjectWithDefault(String key, T def, Class<T> type) throws ParseException {
		return getObjectWithDefault(key, null, def, type);
	}

	/**
	 * Same as {@link #getObjectWithDefault(String, Object, Class)} but allows you to specify the parser to use to parse
	 * the value.
	 *
	 * @param key The key.
	 * @param parser
	 * 	The parser to use for parsing the object.
	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
	 * @param def The default value if the value does not exist.
	 * @param type The class to convert the value to.
	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public <T> T getObjectWithDefault(String key, Parser parser, T def, Class<T> type) throws ParseException {
		assertFieldNotNull(type, "c");
		T t = parse(getString(key), parser, type);
		return (t == null ? def : t);
	}

	/**
	 * Gets the entry with the specified key and converts it to the specified value.
	 *
	 * <p>
	 * Same as {@link #getObject(String, Type, Type...)}, but with a default value.
	 *
	 * @param key The key.
	 * @param def The default value if the value does not exist.
	 * @param type
	 * 	The object type to create.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * @param args
	 * 	The type arguments of the class if it's a collection or map.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * 	<br>Ignored if the main type is not a map or collection.
	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public <T> T getObjectWithDefault(String key, T def, Type type, Type...args) throws ParseException {
		return getObjectWithDefault(key, null, def, type, args);
	}

	/**
	 * Same as {@link #getObjectWithDefault(String, Object, Type, Type...)} but allows you to specify the parser to use
	 * to parse the value.
	 *
	 * @param key The key.
	 * @param parser
	 * 	The parser to use for parsing the object.
	 * 	If <jk>null</jk>, then uses the predefined parser on the config file.
	 * @param def The default value if the value does not exist.
	 * @param type
	 * 	The object type to create.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * @param args
	 * 	The type arguments of the class if it's a collection or map.
	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
	 * 	<br>Ignored if the main type is not a map or collection.
	 * @throws ParseException If parser could not parse the value or if a parser is not registered with this config file.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 */
	public <T> T getObjectWithDefault(String key, Parser parser, T def, Type type, Type...args) throws ParseException {
		assertFieldNotNull(type, "type");
		T t = parse(getString(key), parser, type, args);
		return (t == null ? def : t);
	}

	/**
	 * Convenience method for returning a config entry as an {@link ObjectMap}.
	 *
	 * @param key The key.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 * @throws ParseException Malformed input encountered.
	 */
	public ObjectMap getObjectMap(String key) throws ParseException {
		return getObject(key, ObjectMap.class);
	}

	/**
	 * Convenience method for returning a config entry as an {@link ObjectMap}.
	 *
	 * @param key The key.
	 * @param def The default value.
	 * @return The value, or the default value if the section or key does not exist.
	 * @throws ParseException Malformed input encountered.
	 */
	public ObjectMap getObjectMap(String key, ObjectMap def) throws ParseException {
		return getObjectWithDefault(key, def, ObjectMap.class);
	}

	/**
	 * Convenience method for returning a config entry as an {@link ObjectList}.
	 *
	 * @param key The key.
	 * @return The value, or <jk>null</jk> if the section or key does not exist.
	 * @throws ParseException Malformed input encountered.
	 */
	public ObjectList getObjectList(String key) throws ParseException {
		return getObject(key, ObjectList.class);
	}

	/**
	 * Convenience method for returning a config entry as an {@link ObjectList}.
	 *
	 * @param key The key.
	 * @param def The default value.
	 * @return The value, or the default value if the section or key does not exist.
	 * @throws ParseException Malformed input encountered.
	 */
	public ObjectList getObjectList(String key, ObjectList def) throws ParseException {
		return getObjectWithDefault(key, def, ObjectList.class);
	}

	/**
	 * Returns the keys of the entries in the specified section.
	 *
	 * @param section
	 * 	The section name to write from.
	 * 	<br>If empty, refers to the default section.
	 * 	<br>Must not be <jk>null</jk>.
	 * @return
	 * 	An unmodifiable set of keys, or an empty set if the section doesn't exist.
	 */
	public Set<String> getKeys(String section) {
		return configMap.getKeys(section(section));
	}

	/**
	 * Copies the entries in a section to the specified bean by calling the public setters on that bean.
	 *
	 * @param section
	 * 	The section name to write from.
	 * 	<br>If empty, refers to the default section.
	 * 	<br>Must not be <jk>null</jk>.
	 * @param bean The bean to set the properties on.
	 * @param ignoreUnknownProperties
	 * 	If <jk>true</jk>, don't throw an {@link IllegalArgumentException} if this section contains a key that doesn't
	 * 	correspond to a setter method.
	 * @return An object map of the changes made to the bean.
	 * @throws ParseException If parser was not set on this config file or invalid properties were found in the section.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config writeProperties(String section, Object bean, boolean ignoreUnknownProperties) throws ParseException {
		checkWrite();
		assertFieldNotNull(bean, "bean");
		section = section(section);

		Set<String> keys = configMap.getKeys(section);
		if (keys == null)
			throw new IllegalArgumentException("Section '"+section+"' not found in configuration.");

		BeanMap<?> bm = beanSession.toBeanMap(bean);
		for (String k : keys) {
			BeanPropertyMeta bpm = bm.getPropertyMeta(k);
			if (bpm == null) {
				if (! ignoreUnknownProperties)
					throw new ParseException("Unknown property ''{0}'' encountered in configuration section ''{1}''.", k, section);
			} else {
				bm.put(k, getObject(section + '/' + k, bpm.getClassMeta().getInnerClass()));
			}
		}

		return this;
	}

	/**
	 * Shortcut for calling <code>getSectionAsBean(sectionName, c, <jk>false</jk>)</code>.
	 *
	 * @param section
	 * 	The section name to write from.
	 * 	<br>If empty, refers to the default section.
	 * 	<br>Must not be <jk>null</jk>.
	 * @param c The bean class to create.
	 * @return A new bean instance.
	 * @throws ParseException Malformed input encountered.
	 */
	public <T> T getSectionAsBean(String section, Class<T> c) throws ParseException {
		return getSectionAsBean(section, c, false);
	}

	/**
	 * Converts this config file section to the specified bean instance.
	 *
	 * <p>
	 * Key/value pairs in the config file section get copied as bean property values to the specified bean class.
	 *
	 * <h5 class='figure'>Example config file</h5>
	 * <p class='bcode w800'>
	 * 	<cs>[MyAddress]</cs>
	 * 	<ck>name</ck> = <cv>John Smith</cv>
	 * 	<ck>street</ck> = <cv>123 Main Street</cv>
	 * 	<ck>city</ck> = <cv>Anywhere</cv>
	 * 	<ck>state</ck> = <cv>NY</cv>
	 * 	<ck>zip</ck> = <cv>12345</cv>
	 * </p>
	 *
	 * <h5 class='figure'>Example bean</h5>
	 * <p class='bcode w800'>
	 * 	<jk>public class</jk> Address {
	 * 		public String name, street, city;
	 * 		public StateEnum state;
	 * 		public int zip;
	 * 	}
	 * </p>
	 *
	 * <h5 class='figure'>Example usage</h5>
	 * <p class='bcode w800'>
	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
	 * 	Address myAddress = cf.getSectionAsBean(<js>"MySection"</js>, Address.<jk>class</jk>);
	 * </p>
	 *
	 * @param section
	 * 	The section name to write from.
	 * 	<br>If empty, refers to the default section.
	 * 	<br>Must not be <jk>null</jk>.
	 * @param c The bean class to create.
	 * @param ignoreUnknownProperties
	 * 	If <jk>false</jk>, throws a {@link ParseException} if the section contains an entry that isn't a bean property
	 * 	name.
	 * @return A new bean instance, or <jk>null</jk> if the section doesn't exist.
	 * @throws ParseException Unknown property was encountered in section.
	 */
	public <T> T getSectionAsBean(String section, Class<T> c, boolean ignoreUnknownProperties) throws ParseException {
		assertFieldNotNull(c, "c");
		section = section(section);

		if (! configMap.hasSection(section))
			return null;

		Set<String> keys = configMap.getKeys(section);

		BeanMap<T> bm = beanSession.newBeanMap(c);
		for (String k : keys) {
			BeanPropertyMeta bpm = bm.getPropertyMeta(k);
			if (bpm == null) {
				if (! ignoreUnknownProperties)
					throw new ParseException("Unknown property ''{0}'' encountered in configuration section ''{1}''.", k, section);
			} else {
				bm.put(k, getObject(section + '/' + k, bpm.getClassMeta().getInnerClass()));
			}
		}

		return bm.getBean();
	}

	/**
	 * Returns a section of this config copied into an {@link ObjectMap}.
	 *
	 * @param section
	 * 	The section name to write from.
	 * 	<br>If empty, refers to the default section.
	 * 	<br>Must not be <jk>null</jk>.
	 * @return A new {@link ObjectMap}, or <jk>null</jk> if the section doesn't exist.
	 * @throws ParseException Malformed input encountered.
	 */
	public ObjectMap getSectionAsMap(String section) throws ParseException {
		section = section(section);

		if (! configMap.hasSection(section))
			return null;

		Set<String> keys = configMap.getKeys(section);

		ObjectMap om = new ObjectMap();
		for (String k : keys)
			om.put(k, getObject(section + '/' + k, Object.class));
		return om;
	}

	/**
	 * Returns the section names defined in this config.
	 *
	 * @return The section names defined in this config.
	 */
	public Set<String> getSections() {
		return Collections.unmodifiableSet(configMap.getSections());
	}

	/**
	 * Wraps a config file section inside a Java interface so that values in the section can be read and
	 * write using getters and setters.
	 *
	 * <h5 class='figure'>Example config file</h5>
	 * <p class='bcode w800'>
	 * 	<cs>[MySection]</cs>
	 * 	<ck>string</ck> = <cv>foo</cv>
	 * 	<ck>int</ck> = <cv>123</cv>
	 * 	<ck>enum</ck> = <cv>ONE</cv>
	 * 	<ck>bean</ck> = <cv>{foo:'bar',baz:123}</cv>
	 * 	<ck>int3dArray</ck> = <cv>[[[123,null],null],null]</cv>
	 * 	<ck>bean1d3dListMap</ck> = <cv>{key:[[[[{foo:'bar',baz:123}]]]]}</cv>
	 * </p>
	 *
	 * <h5 class='figure'>Example interface</h5>
	 * <p class='bcode w800'>
	 * 	<jk>public interface</jk> MyConfigInterface {
	 *
	 * 		String getString();
	 * 		<jk>void</jk> setString(String x);
	 *
	 * 		<jk>int</jk> getInt();
	 * 		<jk>void</jk> setInt(<jk>int</jk> x);
	 *
	 * 		MyEnum getEnum();
	 * 		<jk>void</jk> setEnum(MyEnum x);
	 *
	 * 		MyBean getBean();
	 * 		<jk>void</jk> setBean(MyBean x);
	 *
	 * 		<jk>int</jk>[][][] getInt3dArray();
	 * 		<jk>void</jk> setInt3dArray(<jk>int</jk>[][][] x);
	 *
	 * 		Map&lt;String,List&lt;MyBean[][][]&gt;&gt; getBean1d3dListMap();
	 * 		<jk>void</jk> setBean1d3dListMap(Map&lt;String,List&lt;MyBean[][][]&gt;&gt; x);
	 * 	}
	 * </p>
	 *
	 * <h5 class='figure'>Example usage</h5>
	 * <p class='bcode w800'>
	 * 	Config cf = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
	 *
	 * 	MyConfigInterface ci = cf.getSectionAsInterface(<js>"MySection"</js>, MyConfigInterface.<jk>class</jk>);
	 *
	 * 	<jk>int</jk> myInt = ci.getInt();
	 *
	 * 	ci.setBean(<jk>new</jk> MyBean());
	 *
	 * 	cf.save();
	 * </p>
	 *
	 * <ul class='notes'>
	 * 	<li>Calls to setters when the configuration is read-only will cause {@link UnsupportedOperationException} to be thrown.
	 * </ul>
	 *
	 * @param section
	 * 	The section name to write from.
	 * 	<br>If empty, refers to the default section.
	 * 	<br>Must not be <jk>null</jk>.
	 * @param c The proxy interface class.
	 * @return The proxy interface.
	 */
	@SuppressWarnings("unchecked")
	public <T> T getSectionAsInterface(String section, final Class<T> c) {
		assertFieldNotNull(c, "c");
		final String section2 = section(section);

		if (! c.isInterface())
			throw new IllegalArgumentException("Class '"+c.getName()+"' passed to getSectionAsInterface() is not an interface.");

		InvocationHandler h = new InvocationHandler() {

			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				BeanInfo bi = Introspector.getBeanInfo(c, null);
				for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
					Method rm = pd.getReadMethod(), wm = pd.getWriteMethod();
					if (method.equals(rm))
						return Config.this.getObject(section2 + '/' + pd.getName(), rm.getGenericReturnType());
					if (method.equals(wm))
						return Config.this.set(section2 + '/' + pd.getName(), args[0]);
				}
				throw new UnsupportedOperationException("Unsupported interface method.  method='" + method + "'");
			}
		};

		return (T)Proxy.newProxyInstance(c.getClassLoader(), new Class[] { c }, h);
	}

	/**
	 * Returns <jk>true</jk> if this section contains the specified key and the key has a non-blank value.
	 *
	 * @param key The key.
	 * @return <jk>true</jk> if this section contains the specified key and the key has a non-blank value.
	 */
	public boolean exists(String key) {
		return isNotEmpty(getString(key, null));
	}

	/**
	 * Creates the specified section if it doesn't exist.
	 *
	 * <p>
	 * Returns the existing section if it already exists.
	 *
	 * @param name
	 * 	The section name.
	 * 	<br>Must not be <jk>null</jk>.
	 * 	<br>Use blank for the default section.
	 * @param preLines
	 * 	Optional comment and blank lines to add immediately before the section.
	 * 	<br>If <jk>null</jk>, previous pre-lines will not be replaced.
	 * @return The appended or existing section.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config setSection(String name, List<String> preLines) {
		try {
			return setSection(section(name), preLines, null);
		} catch (SerializeException e) {
			throw new RuntimeException(e);  // Impossible.
		}
	}

	/**
	 * Creates the specified section if it doesn't exist.
	 *
	 * @param name
	 * 	The section name.
	 * 	<br>Must not be <jk>null</jk>.
	 * 	<br>Use blank for the default section.
	 * @param preLines
	 * 	Optional comment and blank lines to add immediately before the section.
	 * 	<br>If <jk>null</jk>, previous pre-lines will not be replaced.
	 * @param contents
	 * 	Values to set in the new section.
	 * 	<br>Can be <jk>null</jk>.
	 * @return The appended or existing section.
	 * @throws SerializeException Contents could not be serialized.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config setSection(String name, List<String> preLines, Map<String,Object> contents) throws SerializeException {
		checkWrite();
		configMap.setSection(section(name), preLines);

		if (contents != null)
			for (Map.Entry<String,Object> e : contents.entrySet())
				set(section(name) + '/' + e.getKey(), e.getValue());

		return this;
	}

	/**
	 * Removes the section with the specified name.
	 *
	 * @param name The name of the section to remove
	 * @return This object (for method chaining).
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config removeSection(String name) {
		checkWrite();
		configMap.removeSection(name);
		return this;
	}

	/**
	 * Creates the specified import statement if it doesn't exist.
	 *
	 * @param sectionName
	 * 	The section name where to place the import statement.
	 * 	<br>Must not be <jk>null</jk>.
	 * 	<br>Use blank for the default section.
	 * @param importName
	 * 	The import name.
	 * 	<br>Must not be <jk>null</jk>.
	 * @param preLines
	 * 	Optional comment and blank lines to add immediately before the import statement.
	 * 	<br>If <jk>null</jk>, previous pre-lines will not be replaced.
	 * @return The appended or existing import statement.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config setImport(String sectionName, String importName, List<String> preLines) {
		checkWrite();
		configMap.setImport(section(name), importName, preLines);
		return this;
	}

	/**
	 * Removes the import statement with the specified name from the specified section.
	 *
	 * @param sectionName
	 * 	The section name where to place the import statement.
	 * 	<br>Must not be <jk>null</jk>.
	 * 	<br>Use blank for the default section.
	 * @param importName
	 * 	The import name.
	 * 	<br>Must not be <jk>null</jk>.
	 * @return This object (for method chaining).
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config removeImport(String sectionName, String importName) {
		checkWrite();
		configMap.removeImport(sectionName, importName);
		return this;
	}

	/**
	 * Loads the contents of the specified map of maps into this config.
	 *
	 * @param m The maps to load.
	 * @return This object (for method chaining).
	 * @throws SerializeException Value could not be serialized.
	 */
	public Config load(Map<String,Map<String,Object>> m) throws SerializeException {
		if (m != null)
			for (Map.Entry<String,Map<String,Object>> e : m.entrySet()) {
				setSection(e.getKey(), null, e.getValue());
			}
		return this;
	}

	/**
	 * Commit the changes in this config to the store.
	 *
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config commit() throws IOException {
		checkWrite();
		configMap.commit();
		return this;
	}

	/**
	 * Saves this config file to the specified writer as an INI file.
	 *
	 * <p>
	 * The writer will automatically be closed.
	 *
	 * @param w The writer to send the output to.
	 * @return This object (for method chaining).
	 * @throws IOException If a problem occurred trying to send contents to the writer.
	 */
	@Override /* Writable */
	public Writer writeTo(Writer w) throws IOException {
		return configMap.writeTo(w);
	}

	/**
	 * Add a listener to this config to react to modification events.
	 *
	 * <p>
	 * Listeners should be removed using {@link #removeListener(ConfigEventListener)}.
	 *
	 * @param listener The new listener to add.
	 * @return This object (for method chaining).
	 */
	public synchronized Config addListener(ConfigEventListener listener) {
		listeners.add(listener);
		return this;
	}

	/**
	 * Removes a listener from this config.
	 *
	 * @param listener The listener to remove.
	 * @return This object (for method chaining).
	 */
	public synchronized Config removeListener(ConfigEventListener listener) {
		listeners.remove(listener);
		return this;
	}

	/**
	 * Closes this configuration object by unregistering it from the underlying config map.
	 *
	 * @throws IOException Thrown by underlying stream.
	 */
	public void close() throws IOException {
		configMap.unregister(this);
	}

	/**
	 * Overwrites the contents of the config file.
	 *
	 * @param contents The new contents of the config file.
	 * @param synchronous Wait until the change has been persisted before returning this map.
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 * @throws InterruptedException Thread was interrupted.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config load(Reader contents, boolean synchronous) throws IOException, InterruptedException {
		checkWrite();
		configMap.load(IOUtils.read(contents), synchronous);
		return this;
	}

	/**
	 * Overwrites the contents of the config file.
	 *
	 * @param contents The new contents of the config file.
	 * @param synchronous Wait until the change has been persisted before returning this map.
	 * @return This object (for method chaining).
	 * @throws IOException Thrown by underlying stream.
	 * @throws InterruptedException Thread was interrupted.
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config load(String contents, boolean synchronous) throws IOException, InterruptedException {
		checkWrite();
		configMap.load(contents, synchronous);
		return this;
	}

	/**
	 * Does a rollback of any changes on this config currently in memory.
	 *
	 * @return This object (for method chaining).
	 * @throws UnsupportedOperationException If configuration is read only.
	 */
	public Config rollback() {
		checkWrite();
		configMap.rollback();
		return this;
	}

	/**
	 * Returns the values in this config map as a map of maps.
	 *
	 * <p>
	 * This is considered a snapshot copy of the config map.
	 *
	 * <p>
	 * The returned map is modifiable, but modifications to the returned map are not reflected in the config map.
	 *
	 * @return A copy of this config as a map of maps.
	 */
	@Override /* Context */
	public ObjectMap toMap() {
		return configMap.asMap();
	}


	//-----------------------------------------------------------------------------------------------------------------
	// Test methods
	//-----------------------------------------------------------------------------------------------------------------

	ConfigMap getConfigMap() {
		return configMap;
	}

	List<ConfigEventListener> getListeners() {
		return Collections.unmodifiableList(listeners);
	}


	//-----------------------------------------------------------------------------------------------------------------
	// Interface methods
	//-----------------------------------------------------------------------------------------------------------------

	/**
	 * Unused.
	 */
	@Override /* Context */
	public Session createSession(SessionArgs args) {
		throw new UnsupportedOperationException();
	}

	/**
	 * Unused.
	 */
	@Override /* Context */
	public SessionArgs createDefaultSessionArgs() {
		throw new UnsupportedOperationException();
	}

	@Override /* ConfigEventListener */
	public void onConfigChange(ConfigEvents events) {
		for (ConfigEventListener l : listeners)
			l.onConfigChange(events);
	}

	@Override /* Writable */
	public MediaType getMediaType() {
		return MediaType.PLAIN;
	}


	//-----------------------------------------------------------------------------------------------------------------
	// Private methods
	//-----------------------------------------------------------------------------------------------------------------

	private String serialize(Object value, Serializer serializer) throws SerializeException {
		if (value == null)
			return "";
		if (serializer == null)
			serializer = this.serializer;
		Class<?> c = value.getClass();
		if (value instanceof CharSequence)
			return nlIfMl((CharSequence)value);
		if (isSimpleType(c))
			return value.toString();

		if (value instanceof byte[]) {
			String s = null;
			byte[] b = (byte[])value;
			if (binaryFormat == BinaryFormat.HEX)
				s = toHex(b);
			else if (binaryFormat == BinaryFormat.SPACED_HEX)
				s = toSpacedHex(b);
			else
				s = base64Encode(b);
			int l = binaryLineLength;
			if (l <= 0 || s.length() <= l)
				return s;
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < s.length(); i += l)
				sb.append(binaryLineLength > 0 ? "\n" : "").append(s.substring(i, Math.min(s.length(), i + l)));
			return sb.toString();
		}

		String r = null;
		if (multiLineValuesOnSeparateLines)
			r = "\n" + (String)serializer.serialize(value);
		else
			r = (String)serializer.serialize(value);

		if (r.startsWith("'"))
			return r.substring(1, r.length()-1);
		return r;
	}

	private String nlIfMl(CharSequence cs) {
		String s = cs.toString();
		if (s.indexOf('\n') != -1 && multiLineValuesOnSeparateLines)
			return "\n" + s;
		return s;
	}

	@SuppressWarnings({ "unchecked" })
	private <T> T parse(String s, Parser parser, Type type, Type...args) throws ParseException {

		if (isEmpty(s))
			return null;

		if (isSimpleType(type))
			return (T)beanSession.convertToType(s, (Class<?>)type);

		if (type == byte[].class) {
			if (s.indexOf('\n') != -1)
				s = s.replaceAll("\n", "");
			try {
				switch (binaryFormat) {
					case HEX: return (T)fromHex(s);
					case SPACED_HEX: return (T)fromSpacedHex(s);
					default: return (T)base64Decode(s);
				}
			} catch (Exception e) {
				throw new ParseException(e, "Value could not be converted to a byte array.");
			}
		}

		if (parser == null)
			parser = this.parser;

		if (parser instanceof JsonParser) {
			char s1 = firstNonWhitespaceChar(s);
			if (isArray(type) && s1 != '[')
				s = '[' + s + ']';
			else if (s1 != '[' && s1 != '{' && ! "null".equals(s))
				s = '\'' + s + '\'';
		}

		return parser.parse(s, type, args);
	}

	private boolean isSimpleType(Type t) {
		if (! (t instanceof Class))
			return false;
		Class<?> c = (Class<?>)t;
		return (c == String.class || c.isPrimitive() || c.isAssignableFrom(Number.class) || c == Boolean.class || c.isEnum());
	}

	private boolean isArray(Type t) {
		if (! (t instanceof Class))
			return false;
		Class<?> c = (Class<?>)t;
		return (c.isArray());
	}

	private String sname(String key) {
		assertFieldNotNull(key, "key");
		int i = key.indexOf('/');
		if (i == -1)
			return "";
		return key.substring(0, i);
	}

	private String skey(String key) {
		int i = key.indexOf('/');
		if (i == -1)
			return key;
		return key.substring(i+1);
	}

	private String section(String section) {
		assertFieldNotNull(section, "section");
		if (isEmpty(section))
			return "";
		return section;
	}

	private void checkWrite() {
		if (readOnly)
			throw new UnsupportedOperationException("Cannot call this method on a read-only configuration.");
	}


	//-----------------------------------------------------------------------------------------------------------------
	// Other methods
	//-----------------------------------------------------------------------------------------------------------------

	@Override /* Object */
	public String toString() {
		return configMap.toString();
	}

	@Override /* Object */
	protected void finalize() throws Throwable {
		close();
	}
}
