    001/**
    002 *   Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
    003 */
    004package com.typesafe.config;
    005
    006import java.time.Duration;
    007import java.util.List;
    008import java.util.Map;
    009import java.util.Set;
    010import java.util.concurrent.TimeUnit;
    011
    012/**
    013 * An immutable map from config paths to config values. Paths are dot-separated
    014 * expressions such as <code>foo.bar.baz</code>. Values are as in JSON
    015 * (booleans, strings, numbers, lists, or objects), represented by
    016 * {@link ConfigValue} instances. Values accessed through the
    017 * <code>Config</code> interface are never null.
    018 *
    019 * <p>
    020 * {@code Config} is an immutable object and thus safe to use from multiple
    021 * threads. There's never a need for "defensive copies."
    022 *
    023 * <p>
    024 * Fundamental operations on a {@code Config} include getting configuration
    025 * values, <em>resolving</em> substitutions with {@link Config#resolve()}, and
    026 * merging configs using {@link Config#withFallback(ConfigMergeable)}.
    027 *
    028 * <p>
    029 * All operations return a new immutable {@code Config} rather than modifying
    030 * the original instance.
    031 *
    032 * <p>
    033 * <strong>Examples</strong>
    034 *
    035 * <p>
    036 * You can find an example app and library <a
    037 * href="https://github.com/typesafehub/config/tree/master/examples">on
    038 * GitHub</a>. Also be sure to read the <a
    039 * href="package-summary.html#package_description">package overview</a> which
    040 * describes the big picture as shown in those examples.
    041 *
    042 * <p>
    043 * <strong>Paths, keys, and Config vs. ConfigObject</strong>
    044 *
    045 * <p>
    046 * <code>Config</code> is a view onto a tree of {@link ConfigObject}; the
    047 * corresponding object tree can be found through {@link Config#root()}.
    048 * <code>ConfigObject</code> is a map from config <em>keys</em>, rather than
    049 * paths, to config values. Think of <code>ConfigObject</code> as a JSON object
    050 * and <code>Config</code> as a configuration API.
    051 *
    052 * <p>
    053 * The API tries to consistently use the terms "key" and "path." A key is a key
    054 * in a JSON object; it's just a string that's the key in a map. A "path" is a
    055 * parseable expression with a syntax and it refers to a series of keys. Path
    056 * expressions are described in the <a
    057 * href="https://github.com/typesafehub/config/blob/master/HOCON.md">spec for
    058 * Human-Optimized Config Object Notation</a>. In brief, a path is
    059 * period-separated so "a.b.c" looks for key c in object b in object a in the
    060 * root object. Sometimes double quotes are needed around special characters in
    061 * path expressions.
    062 *
    063 * <p>
    064 * The API for a {@code Config} is in terms of path expressions, while the API
    065 * for a {@code ConfigObject} is in terms of keys. Conceptually, {@code Config}
    066 * is a one-level map from <em>paths</em> to values, while a
    067 * {@code ConfigObject} is a tree of nested maps from <em>keys</em> to values.
    068 *
    069 * <p>
    070 * Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
    071 * between path expressions and individual path elements (keys).
    072 *
    073 * <p>
    074 * Another difference between {@code Config} and {@code ConfigObject} is that
    075 * conceptually, {@code ConfigValue}s with a {@link ConfigValue#valueType()
    076 * valueType()} of {@link ConfigValueType#NULL NULL} exist in a
    077 * {@code ConfigObject}, while a {@code Config} treats null values as if they
    078 * were missing. (With the exception of two methods: {@link Config#hasPathOrNull}
    079 * and {@link Config#getIsNull} let you detect <code>null</code> values.)
    080 *
    081 * <p>
    082 * <strong>Getting configuration values</strong>
    083 *
    084 * <p>
    085 * The "getters" on a {@code Config} all work in the same way. They never return
    086 * null, nor do they return a {@code ConfigValue} with
    087 * {@link ConfigValue#valueType() valueType()} of {@link ConfigValueType#NULL
    088 * NULL}. Instead, they throw {@link ConfigException.Missing} if the value is
    089 * completely absent or set to null. If the value is set to null, a subtype of
    090 * {@code ConfigException.Missing} called {@link ConfigException.Null} will be
    091 * thrown. {@link ConfigException.WrongType} will be thrown anytime you ask for
    092 * a type and the value has an incompatible type. Reasonable type conversions
    093 * are performed for you though.
    094 *
    095 * <p>
    096 * <strong>Iteration</strong>
    097 *
    098 * <p>
    099 * If you want to iterate over the contents of a {@code Config}, you can get its
    100 * {@code ConfigObject} with {@link #root()}, and then iterate over the
    101 * {@code ConfigObject} (which implements <code>java.util.Map</code>). Or, you
    102 * can use {@link #entrySet()} which recurses the object tree for you and builds
    103 * up a <code>Set</code> of all path-value pairs where the value is not null.
    104 *
    105 * <p>
    106 * <strong>Resolving substitutions</strong>
    107 *
    108 * <p>
    109 * <em>Substitutions</em> are the <code>${foo.bar}</code> syntax in config
    110 * files, described in the <a href=
    111 * "https://github.com/typesafehub/config/blob/master/HOCON.md#substitutions"
    112 * >specification</a>. Resolving substitutions replaces these references with real
    113 * values.
    114 *
    115 * <p>
    116 * Before using a {@code Config} it's necessary to call {@link Config#resolve()}
    117 * to handle substitutions (though {@link ConfigFactory#load()} and similar
    118 * methods will do the resolve for you already).
    119 *
    120 * <p>
    121 * <strong>Merging</strong>
    122 *
    123 * <p>
    124 * The full <code>Config</code> for your application can be constructed using
    125 * the associative operation {@link Config#withFallback(ConfigMergeable)}. If
    126 * you use {@link ConfigFactory#load()} (recommended), it merges system
    127 * properties over the top of <code>application.conf</code> over the top of
    128 * <code>reference.conf</code>, using <code>withFallback</code>. You can add in
    129 * additional sources of configuration in the same way (usually, custom layers
    130 * should go either just above or just below <code>application.conf</code>,
    131 * keeping <code>reference.conf</code> at the bottom and system properties at
    132 * the top).
    133 *
    134 * <p>
    135 * <strong>Serialization</strong>
    136 *
    137 * <p>
    138 * Convert a <code>Config</code> to a JSON or HOCON string by calling
    139 * {@link ConfigObject#render()} on the root object,
    140 * <code>myConfig.root().render()</code>. There's also a variant
    141 * {@link ConfigObject#render(ConfigRenderOptions)} which allows you to control
    142 * the format of the rendered string. (See {@link ConfigRenderOptions}.) Note
    143 * that <code>Config</code> does not remember the formatting of the original
    144 * file, so if you load, modify, and re-save a config file, it will be
    145 * substantially reformatted.
    146 *
    147 * <p>
    148 * As an alternative to {@link ConfigObject#render()}, the
    149 * <code>toString()</code> method produces a debug-output-oriented
    150 * representation (which is not valid JSON).
    151 *
    152 * <p>
    153 * Java serialization is supported as well for <code>Config</code> and all
    154 * subtypes of <code>ConfigValue</code>.
    155 *
    156 * <p>
    157 * <strong>This is an interface but don't implement it yourself</strong>
    158 *
    159 * <p>
    160 * <em>Do not implement {@code Config}</em>; it should only be implemented by
    161 * the config library. Arbitrary implementations will not work because the
    162 * library internals assume a specific concrete implementation. Also, this
    163 * interface is likely to grow new methods over time, so third-party
    164 * implementations will break.
    165 */
    166public interface Config extends ConfigMergeable {
    167    /**
    168     * Gets the {@code Config} as a tree of {@link ConfigObject}. This is a
    169     * constant-time operation (it is not proportional to the number of values
    170     * in the {@code Config}).
    171     *
    172     * @return the root object in the configuration
    173     */
    174    ConfigObject root();
    175
    176    /**
    177     * Gets the origin of the {@code Config}, which may be a file, or a file
    178     * with a line number, or just a descriptive phrase.
    179     *
    180     * @return the origin of the {@code Config} for use in error messages
    181     */
    182    ConfigOrigin origin();
    183
    184    @Override
    185    Config withFallback(ConfigMergeable other);
    186
    187    /**
    188     * Returns a replacement config with all substitutions (the
    189     * <code>${foo.bar}</code> syntax, see <a
    190     * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the
    191     * spec</a>) resolved. Substitutions are looked up using this
    192     * <code>Config</code> as the root object, that is, a substitution
    193     * <code>${foo.bar}</code> will be replaced with the result of
    194     * <code>getValue("foo.bar")</code>.
    195     *
    196     * <p>
    197     * This method uses {@link ConfigResolveOptions#defaults()}, there is
    198     * another variant {@link Config#resolve(ConfigResolveOptions)} which lets
    199     * you specify non-default options.
    200     *
    201     * <p>
    202     * A given {@link Config} must be resolved before using it to retrieve
    203     * config values, but ideally should be resolved one time for your entire
    204     * stack of fallbacks (see {@link Config#withFallback}). Otherwise, some
    205     * substitutions that could have resolved with all fallbacks available may
    206     * not resolve, which will be potentially confusing for your application's
    207     * users.
    208     *
    209     * <p>
    210     * <code>resolve()</code> should be invoked on root config objects, rather
    211     * than on a subtree (a subtree is the result of something like
    212     * <code>config.getConfig("foo")</code>). The problem with
    213     * <code>resolve()</code> on a subtree is that substitutions are relative to
    214     * the root of the config and the subtree will have no way to get values
    215     * from the root. For example, if you did
    216     * <code>config.getConfig("foo").resolve()</code> on the below config file,
    217     * it would not work:
    218     *
    219     * <pre>
    220     *   common-value = 10
    221     *   foo {
    222     *      whatever = ${common-value}
    223     *   }
    224     * </pre>
    225     *
    226     * <p>
    227     * Many methods on {@link ConfigFactory} such as
    228     * {@link ConfigFactory#load()} automatically resolve the loaded
    229     * <code>Config</code> on the loaded stack of config files.
    230     *
    231     * <p>
    232     * Resolving an already-resolved config is a harmless no-op, but again, it
    233     * is best to resolve an entire stack of fallbacks (such as all your config
    234     * files combined) rather than resolving each one individually.
    235     *
    236     * @return an immutable object with substitutions resolved
    237     * @throws ConfigException.UnresolvedSubstitution
    238     *             if any substitutions refer to nonexistent paths
    239     * @throws ConfigException
    240     *             some other config exception if there are other problems
    241     */
    242    Config resolve();
    243
    244    /**
    245     * Like {@link Config#resolve()} but allows you to specify non-default
    246     * options.
    247     *
    248     * @param options
    249     *            resolve options
    250     * @return the resolved <code>Config</code> (may be only partially resolved if options are set to allow unresolved)
    251     */
    252    Config resolve(ConfigResolveOptions options);
    253
    254    /**
    255     * Checks whether the config is completely resolved. After a successful call
    256     * to {@link Config#resolve()} it will be completely resolved, but after
    257     * calling {@link Config#resolve(ConfigResolveOptions)} with
    258     * <code>allowUnresolved</code> set in the options, it may or may not be
    259     * completely resolved. A newly-loaded config may or may not be completely
    260     * resolved depending on whether there were substitutions present in the
    261     * file.
    262     *
    263     * @return true if there are no unresolved substitutions remaining in this
    264     *         configuration.
    265     * @since 1.2.0
    266     */
    267    boolean isResolved();
    268
    269    /**
    270     * Like {@link Config#resolve()} except that substitution values are looked
    271     * up in the given source, rather than in this instance. This is a
    272     * special-purpose method which doesn't make sense to use in most cases;
    273     * it's only needed if you're constructing some sort of app-specific custom
    274     * approach to configuration. The more usual approach if you have a source
    275     * of substitution values would be to merge that source into your config
    276     * stack using {@link Config#withFallback} and then resolve.
    277     * <p>
    278     * Note that this method does NOT look in this instance for substitution
    279     * values. If you want to do that, you could either merge this instance into
    280     * your value source using {@link Config#withFallback}, or you could resolve
    281     * multiple times with multiple sources (using
    282     * {@link ConfigResolveOptions#setAllowUnresolved(boolean)} so the partial
    283     * resolves don't fail).
    284     *
    285     * @param source
    286     *            configuration to pull values from
    287     * @return an immutable object with substitutions resolved
    288     * @throws ConfigException.UnresolvedSubstitution
    289     *             if any substitutions refer to paths which are not in the
    290     *             source
    291     * @throws ConfigException
    292     *             some other config exception if there are other problems
    293     * @since 1.2.0
    294     */
    295    Config resolveWith(Config source);
    296
    297    /**
    298     * Like {@link Config#resolveWith(Config)} but allows you to specify
    299     * non-default options.
    300     *
    301     * @param source
    302     *            source configuration to pull values from
    303     * @param options
    304     *            resolve options
    305     * @return the resolved <code>Config</code> (may be only partially resolved
    306     *         if options are set to allow unresolved)
    307     * @since 1.2.0
    308     */
    309    Config resolveWith(Config source, ConfigResolveOptions options);
    310
    311    /**
    312     * Validates this config against a reference config, throwing an exception
    313     * if it is invalid. The purpose of this method is to "fail early" with a
    314     * comprehensive list of problems; in general, anything this method can find
    315     * would be detected later when trying to use the config, but it's often
    316     * more user-friendly to fail right away when loading the config.
    317     *
    318     * <p>
    319     * Using this method is always optional, since you can "fail late" instead.
    320     *
    321     * <p>
    322     * You must restrict validation to paths you "own" (those whose meaning are
    323     * defined by your code module). If you validate globally, you may trigger
    324     * errors about paths that happen to be in the config but have nothing to do
    325     * with your module. It's best to allow the modules owning those paths to
    326     * validate them. Also, if every module validates only its own stuff, there
    327     * isn't as much redundant work being done.
    328     *
    329     * <p>
    330     * If no paths are specified in <code>checkValid()</code>'s parameter list,
    331     * validation is for the entire config.
    332     *
    333     * <p>
    334     * If you specify paths that are not in the reference config, those paths
    335     * are ignored. (There's nothing to validate.)
    336     *
    337     * <p>
    338     * Here's what validation involves:
    339     *
    340     * <ul>
    341     * <li>All paths found in the reference config must be present in this
    342     * config or an exception will be thrown.
    343     * <li>
    344     * Some changes in type from the reference config to this config will cause
    345     * an exception to be thrown. Not all potential type problems are detected,
    346     * in particular it's assumed that strings are compatible with everything
    347     * except objects and lists. This is because string types are often "really"
    348     * some other type (system properties always start out as strings, or a
    349     * string like "5ms" could be used with {@link #getMilliseconds}). Also,
    350     * it's allowed to set any type to null or override null with any type.
    351     * <li>
    352     * Any unresolved substitutions in this config will cause a validation
    353     * failure; both the reference config and this config should be resolved
    354     * before validation. If the reference config is unresolved, it's a bug in
    355     * the caller of this method.
    356     * </ul>
    357     *
    358     * <p>
    359     * If you want to allow a certain setting to have a flexible type (or
    360     * otherwise want validation to be looser for some settings), you could
    361     * either remove the problematic setting from the reference config provided
    362     * to this method, or you could intercept the validation exception and
    363     * screen out certain problems. Of course, this will only work if all other
    364     * callers of this method are careful to restrict validation to their own
    365     * paths, as they should be.
    366     *
    367     * <p>
    368     * If validation fails, the thrown exception contains a list of all problems
    369     * found. See {@link ConfigException.ValidationFailed#problems}. The
    370     * exception's <code>getMessage()</code> will have all the problems
    371     * concatenated into one huge string, as well.
    372     *
    373     * <p>
    374     * Again, <code>checkValid()</code> can't guess every domain-specific way a
    375     * setting can be invalid, so some problems may arise later when attempting
    376     * to use the config. <code>checkValid()</code> is limited to reporting
    377     * generic, but common, problems such as missing settings and blatant type
    378     * incompatibilities.
    379     *
    380     * @param reference
    381     *            a reference configuration
    382     * @param restrictToPaths
    383     *            only validate values underneath these paths that your code
    384     *            module owns and understands
    385     * @throws ConfigException.ValidationFailed
    386     *             if there are any validation issues
    387     * @throws ConfigException.NotResolved
    388     *             if this config is not resolved
    389     * @throws ConfigException.BugOrBroken
    390     *             if the reference config is unresolved or caller otherwise
    391     *             misuses the API
    392     */
    393    void checkValid(Config reference, String... restrictToPaths);
    394
    395    /**
    396     * Checks whether a value is present and non-null at the given path. This
    397     * differs in two ways from {@code Map.containsKey()} as implemented by
    398     * {@link ConfigObject}: it looks for a path expression, not a key; and it
    399     * returns false for null values, while {@code containsKey()} returns true
    400     * indicating that the object contains a null value for the key.
    401     *
    402     * <p>
    403     * If a path exists according to {@link #hasPath(String)}, then
    404     * {@link #getValue(String)} will never throw an exception. However, the
    405     * typed getters, such as {@link #getInt(String)}, will still throw if the
    406     * value is not convertible to the requested type.
    407     *
    408     * <p>
    409     * Note that path expressions have a syntax and sometimes require quoting
    410     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    411     *
    412     * @param path
    413     *            the path expression
    414     * @return true if a non-null value is present at the path
    415     * @throws ConfigException.BadPath
    416     *             if the path expression is invalid
    417     */
    418    boolean hasPath(String path);
    419
    420    /**
    421     * Checks whether a value is present at the given path, even
    422     * if the value is null. Most of the getters on
    423     * <code>Config</code> will throw if you try to get a null
    424     * value, so if you plan to call {@link #getValue(String)},
    425     * {@link #getInt(String)}, or another getter you may want to
    426     * use plain {@link #hasPath(String)} rather than this method.
    427     *
    428     * <p>
    429     * To handle all three cases (unset, null, and a non-null value)
    430     * the code might look like:
    431     * <pre><code>
    432     * if (config.hasPathOrNull(path)) {
    433     *     if (config.getIsNull(path)) {
    434     *        // handle null setting
    435     *     } else {
    436     *        // get and use non-null setting
    437     *     }
    438     * } else {
    439     *     // handle entirely unset path
    440     * }
    441     * </code></pre>
    442     *
    443     * <p> However, the usual thing is to allow entirely unset
    444     * paths to be a bug that throws an exception (because you set
    445     * a default in your <code>reference.conf</code>), so in that
    446     * case it's OK to call {@link #getIsNull(String)} without
    447     * checking <code>hasPathOrNull</code> first.
    448     *
    449     * <p>
    450     * Note that path expressions have a syntax and sometimes require quoting
    451     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    452     *
    453     * @param path
    454     *            the path expression
    455     * @return true if a value is present at the path, even if the value is null
    456     * @throws ConfigException.BadPath
    457     *             if the path expression is invalid
    458     */
    459    boolean hasPathOrNull(String path);
    460
    461    /**
    462     * Returns true if the {@code Config}'s root object contains no key-value
    463     * pairs.
    464     *
    465     * @return true if the configuration is empty
    466     */
    467    boolean isEmpty();
    468
    469    /**
    470     * Returns the set of path-value pairs, excluding any null values, found by
    471     * recursing {@link #root() the root object}. Note that this is very
    472     * different from <code>root().entrySet()</code> which returns the set of
    473     * immediate-child keys in the root object and includes null values.
    474     * <p>
    475     * Entries contain <em>path expressions</em> meaning there may be quoting
    476     * and escaping involved. Parse path expressions with
    477     * {@link ConfigUtil#splitPath}.
    478     * <p>
    479     * Because a <code>Config</code> is conceptually a single-level map from
    480     * paths to values, there will not be any {@link ConfigObject} values in the
    481     * entries (that is, all entries represent leaf nodes). Use
    482     * {@link ConfigObject} rather than <code>Config</code> if you want a tree.
    483     * (OK, this is a slight lie: <code>Config</code> entries may contain
    484     * {@link ConfigList} and the lists may contain objects. But no objects are
    485     * directly included as entry values.)
    486     *
    487     * @return set of paths with non-null values, built up by recursing the
    488     *         entire tree of {@link ConfigObject} and creating an entry for
    489     *         each leaf value.
    490     */
    491    Set<Map.Entry<String, ConfigValue>> entrySet();
    492
    493    /**
    494     * Checks whether a value is set to null at the given path,
    495     * but throws an exception if the value is entirely
    496     * unset. This method will not throw if {@link
    497     * #hasPathOrNull(String)} returned true for the same path, so
    498     * to avoid any possible exception check
    499     * <code>hasPathOrNull()</code> first.  However, an exception
    500     * for unset paths will usually be the right thing (because a
    501     * <code>reference.conf</code> should exist that has the path
    502     * set, the path should never be unset unless something is
    503     * broken).
    504     *
    505     * <p>
    506     * Note that path expressions have a syntax and sometimes require quoting
    507     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    508     *
    509     * @param path
    510     *            the path expression
    511     * @return true if the value exists and is null, false if it
    512     * exists and is not null
    513     * @throws ConfigException.BadPath
    514     *             if the path expression is invalid
    515     * @throws ConfigException.Missing
    516     *             if value is not set at all
    517     */
    518    boolean getIsNull(String path);
    519
    520    /**
    521     *
    522     * @param path
    523     *            path expression
    524     * @return the boolean value at the requested path
    525     * @throws ConfigException.Missing
    526     *             if value is absent or null
    527     * @throws ConfigException.WrongType
    528     *             if value is not convertible to boolean
    529     */
    530    boolean getBoolean(String path);
    531
    532    /**
    533     * @param path
    534     *            path expression
    535     * @return the numeric value at the requested path
    536     * @throws ConfigException.Missing
    537     *             if value is absent or null
    538     * @throws ConfigException.WrongType
    539     *             if value is not convertible to a number
    540     */
    541    Number getNumber(String path);
    542
    543    /**
    544     * Gets the integer at the given path. If the value at the
    545     * path has a fractional (floating point) component, it
    546     * will be discarded and only the integer part will be
    547     * returned (it works like a "narrowing primitive conversion"
    548     * in the Java language specification).
    549     *
    550     * @param path
    551     *            path expression
    552     * @return the 32-bit integer value at the requested path
    553     * @throws ConfigException.Missing
    554     *             if value is absent or null
    555     * @throws ConfigException.WrongType
    556     *             if value is not convertible to an int (for example it is out
    557     *             of range, or it's a boolean value)
    558     */
    559    int getInt(String path);
    560
    561    /**
    562     * Gets the long integer at the given path.  If the value at
    563     * the path has a fractional (floating point) component, it
    564     * will be discarded and only the integer part will be
    565     * returned (it works like a "narrowing primitive conversion"
    566     * in the Java language specification).
    567     *
    568     * @param path
    569     *            path expression
    570     * @return the 64-bit long value at the requested path
    571     * @throws ConfigException.Missing
    572     *             if value is absent or null
    573     * @throws ConfigException.WrongType
    574     *             if value is not convertible to a long
    575     */
    576    long getLong(String path);
    577
    578    /**
    579     * @param path
    580     *            path expression
    581     * @return the floating-point value at the requested path
    582     * @throws ConfigException.Missing
    583     *             if value is absent or null
    584     * @throws ConfigException.WrongType
    585     *             if value is not convertible to a double
    586     */
    587    double getDouble(String path);
    588
    589    /**
    590     * @param path
    591     *            path expression
    592     * @return the string value at the requested path
    593     * @throws ConfigException.Missing
    594     *             if value is absent or null
    595     * @throws ConfigException.WrongType
    596     *             if value is not convertible to a string
    597     */
    598    String getString(String path);
    599
    600    /**
    601     * @param enumClass
    602     *            an enum class
    603     * @param <T>
    604     *            a generic denoting a specific type of enum
    605     * @param path
    606     *            path expression
    607     * @return the {@code Enum} value at the requested path
    608     *              of the requested enum class
    609     * @throws ConfigException.Missing
    610     *             if value is absent or null
    611     * @throws ConfigException.WrongType
    612     *             if value is not convertible to an Enum
    613     */
    614    public <T extends Enum<T>> T getEnum(Class<T> enumClass, String path);
    615
    616    /**
    617     * @param path
    618     *            path expression
    619     * @return the {@link ConfigObject} value at the requested path
    620     * @throws ConfigException.Missing
    621     *             if value is absent or null
    622     * @throws ConfigException.WrongType
    623     *             if value is not convertible to an object
    624     */
    625    ConfigObject getObject(String path);
    626
    627    /**
    628     * @param path
    629     *            path expression
    630     * @return the nested {@code Config} value at the requested path
    631     * @throws ConfigException.Missing
    632     *             if value is absent or null
    633     * @throws ConfigException.WrongType
    634     *             if value is not convertible to a Config
    635     */
    636    Config getConfig(String path);
    637
    638    /**
    639     * Gets the value at the path as an unwrapped Java boxed value (
    640     * {@link java.lang.Boolean Boolean}, {@link java.lang.Integer Integer}, and
    641     * so on - see {@link ConfigValue#unwrapped()}).
    642     *
    643     * @param path
    644     *            path expression
    645     * @return the unwrapped value at the requested path
    646     * @throws ConfigException.Missing
    647     *             if value is absent or null
    648     */
    649    Object getAnyRef(String path);
    650
    651    /**
    652     * Gets the value at the given path, unless the value is a
    653     * null value or missing, in which case it throws just like
    654     * the other getters. Use {@code get()} on the {@link
    655     * Config#root()} object (or other object in the tree) if you
    656     * want an unprocessed value.
    657     *
    658     * @param path
    659     *            path expression
    660     * @return the value at the requested path
    661     * @throws ConfigException.Missing
    662     *             if value is absent or null
    663     */
    664    ConfigValue getValue(String path);
    665
    666    /**
    667     * Gets a value as a size in bytes (parses special strings like "128M"). If
    668     * the value is already a number, then it's left alone; if it's a string,
    669     * it's parsed understanding unit suffixes such as "128K", as documented in
    670     * the <a
    671     * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the
    672     * spec</a>.
    673     *
    674     * @param path
    675     *            path expression
    676     * @return the value at the requested path, in bytes
    677     * @throws ConfigException.Missing
    678     *             if value is absent or null
    679     * @throws ConfigException.WrongType
    680     *             if value is not convertible to Long or String
    681     * @throws ConfigException.BadValue
    682     *             if value cannot be parsed as a size in bytes
    683     */
    684    Long getBytes(String path);
    685
    686    /**
    687     * Gets a value as an amount of memory (parses special strings like "128M"). If
    688     * the value is already a number, then it's left alone; if it's a string,
    689     * it's parsed understanding unit suffixes such as "128K", as documented in
    690     * the <a
    691     * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the
    692     * spec</a>.
    693     *
    694     * @since 1.3.0
    695     *
    696     * @param path
    697     *            path expression
    698     * @return the value at the requested path, in bytes
    699     * @throws ConfigException.Missing
    700     *             if value is absent or null
    701     * @throws ConfigException.WrongType
    702     *             if value is not convertible to Long or String
    703     * @throws ConfigException.BadValue
    704     *             if value cannot be parsed as a size in bytes
    705     */
    706    ConfigMemorySize getMemorySize(String path);
    707
    708    /**
    709     * Get value as a duration in milliseconds. If the value is already a
    710     * number, then it's left alone; if it's a string, it's parsed understanding
    711     * units suffixes like "10m" or "5ns" as documented in the <a
    712     * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the
    713     * spec</a>.
    714     *
    715     * @deprecated  As of release 1.1, replaced by {@link #getDuration(String, TimeUnit)}
    716     *
    717     * @param path
    718     *            path expression
    719     * @return the duration value at the requested path, in milliseconds
    720     * @throws ConfigException.Missing
    721     *             if value is absent or null
    722     * @throws ConfigException.WrongType
    723     *             if value is not convertible to Long or String
    724     * @throws ConfigException.BadValue
    725     *             if value cannot be parsed as a number of milliseconds
    726     */
    727    @Deprecated Long getMilliseconds(String path);
    728
    729    /**
    730     * Get value as a duration in nanoseconds. If the value is already a number
    731     * it's taken as milliseconds and converted to nanoseconds. If it's a
    732     * string, it's parsed understanding unit suffixes, as for
    733     * {@link #getDuration(String, TimeUnit)}.
    734     *
    735     * @deprecated  As of release 1.1, replaced by {@link #getDuration(String, TimeUnit)}
    736     *
    737     * @param path
    738     *            path expression
    739     * @return the duration value at the requested path, in nanoseconds
    740     * @throws ConfigException.Missing
    741     *             if value is absent or null
    742     * @throws ConfigException.WrongType
    743     *             if value is not convertible to Long or String
    744     * @throws ConfigException.BadValue
    745     *             if value cannot be parsed as a number of nanoseconds
    746     */
    747    @Deprecated Long getNanoseconds(String path);
    748
    749    /**
    750     * Gets a value as a duration in a specified
    751     * {@link java.util.concurrent.TimeUnit TimeUnit}. If the value is already a
    752     * number, then it's taken as milliseconds and then converted to the
    753     * requested TimeUnit; if it's a string, it's parsed understanding units
    754     * suffixes like "10m" or "5ns" as documented in the <a
    755     * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the
    756     * spec</a>.
    757     *
    758     * @since 1.2.0
    759     *
    760     * @param path
    761     *            path expression
    762     * @param unit
    763     *            convert the return value to this time unit
    764     * @return the duration value at the requested path, in the given TimeUnit
    765     * @throws ConfigException.Missing
    766     *             if value is absent or null
    767     * @throws ConfigException.WrongType
    768     *             if value is not convertible to Long or String
    769     * @throws ConfigException.BadValue
    770     *             if value cannot be parsed as a number of the given TimeUnit
    771     */
    772    long getDuration(String path, TimeUnit unit);
    773
    774    /**
    775     * Gets a value as a java.time.Duration. If the value is
    776     * already a number, then it's taken as milliseconds; if it's
    777     * a string, it's parsed understanding units suffixes like
    778     * "10m" or "5ns" as documented in the <a
    779     * href="https://github.com/typesafehub/config/blob/master/HOCON.md">the
    780     * spec</a>. This method never returns null.
    781     *
    782     * @since 1.3.0
    783     *
    784     * @param path
    785     *            path expression
    786     * @return the duration value at the requested path
    787     * @throws ConfigException.Missing
    788     *             if value is absent or null
    789     * @throws ConfigException.WrongType
    790     *             if value is not convertible to Long or String
    791     * @throws ConfigException.BadValue
    792     *             if value cannot be parsed as a number of the given TimeUnit
    793     */
    794    Duration getDuration(String path);
    795
    796    /**
    797     * Gets a list value (with any element type) as a {@link ConfigList}, which
    798     * implements {@code java.util.List<ConfigValue>}. Throws if the path is
    799     * unset or null.
    800     *
    801     * @param path
    802     *            the path to the list value.
    803     * @return the {@link ConfigList} at the path
    804     * @throws ConfigException.Missing
    805     *             if value is absent or null
    806     * @throws ConfigException.WrongType
    807     *             if value is not convertible to a ConfigList
    808     */
    809    ConfigList getList(String path);
    810
    811    /**
    812     * Gets a list value with boolean elements.  Throws if the
    813     * path is unset or null or not a list or contains values not
    814     * convertible to boolean.
    815     *
    816     * @param path
    817     *            the path to the list value.
    818     * @return the list at the path
    819     * @throws ConfigException.Missing
    820     *             if value is absent or null
    821     * @throws ConfigException.WrongType
    822     *             if value is not convertible to a list of booleans
    823     */
    824    List<Boolean> getBooleanList(String path);
    825
    826    /**
    827     * Gets a list value with number elements.  Throws if the
    828     * path is unset or null or not a list or contains values not
    829     * convertible to number.
    830     *
    831     * @param path
    832     *            the path to the list value.
    833     * @return the list at the path
    834     * @throws ConfigException.Missing
    835     *             if value is absent or null
    836     * @throws ConfigException.WrongType
    837     *             if value is not convertible to a list of numbers
    838     */
    839    List<Number> getNumberList(String path);
    840
    841    /**
    842     * Gets a list value with int elements.  Throws if the
    843     * path is unset or null or not a list or contains values not
    844     * convertible to int.
    845     *
    846     * @param path
    847     *            the path to the list value.
    848     * @return the list at the path
    849     * @throws ConfigException.Missing
    850     *             if value is absent or null
    851     * @throws ConfigException.WrongType
    852     *             if value is not convertible to a list of ints
    853     */
    854    List<Integer> getIntList(String path);
    855
    856    /**
    857     * Gets a list value with long elements.  Throws if the
    858     * path is unset or null or not a list or contains values not
    859     * convertible to long.
    860     *
    861     * @param path
    862     *            the path to the list value.
    863     * @return the list at the path
    864     * @throws ConfigException.Missing
    865     *             if value is absent or null
    866     * @throws ConfigException.WrongType
    867     *             if value is not convertible to a list of longs
    868     */
    869    List<Long> getLongList(String path);
    870
    871    /**
    872     * Gets a list value with double elements.  Throws if the
    873     * path is unset or null or not a list or contains values not
    874     * convertible to double.
    875     *
    876     * @param path
    877     *            the path to the list value.
    878     * @return the list at the path
    879     * @throws ConfigException.Missing
    880     *             if value is absent or null
    881     * @throws ConfigException.WrongType
    882     *             if value is not convertible to a list of doubles
    883     */
    884    List<Double> getDoubleList(String path);
    885
    886    /**
    887     * Gets a list value with string elements.  Throws if the
    888     * path is unset or null or not a list or contains values not
    889     * convertible to string.
    890     *
    891     * @param path
    892     *            the path to the list value.
    893     * @return the list at the path
    894     * @throws ConfigException.Missing
    895     *             if value is absent or null
    896     * @throws ConfigException.WrongType
    897     *             if value is not convertible to a list of strings
    898     */
    899    List<String> getStringList(String path);
    900
    901    /**
    902     * Gets a list value with {@code Enum} elements.  Throws if the
    903     * path is unset or null or not a list or contains values not
    904     * convertible to {@code Enum}.
    905     *
    906     * @param enumClass
    907     *            the enum class
    908     * @param <T>
    909     *            a generic denoting a specific type of enum
    910     * @param path
    911     *            the path to the list value.
    912     * @return the list at the path
    913     * @throws ConfigException.Missing
    914     *             if value is absent or null
    915     * @throws ConfigException.WrongType
    916     *             if value is not convertible to a list of {@code Enum}
    917     */
    918    <T extends Enum<T>> List<T> getEnumList(Class<T> enumClass, String path);
    919
    920    /**
    921     * Gets a list value with object elements.  Throws if the
    922     * path is unset or null or not a list or contains values not
    923     * convertible to <code>ConfigObject</code>.
    924     *
    925     * @param path
    926     *            the path to the list value.
    927     * @return the list at the path
    928     * @throws ConfigException.Missing
    929     *             if value is absent or null
    930     * @throws ConfigException.WrongType
    931     *             if value is not convertible to a list of objects
    932     */
    933    List<? extends ConfigObject> getObjectList(String path);
    934
    935    /**
    936     * Gets a list value with <code>Config</code> elements.
    937     * Throws if the path is unset or null or not a list or
    938     * contains values not convertible to <code>Config</code>.
    939     *
    940     * @param path
    941     *            the path to the list value.
    942     * @return the list at the path
    943     * @throws ConfigException.Missing
    944     *             if value is absent or null
    945     * @throws ConfigException.WrongType
    946     *             if value is not convertible to a list of configs
    947     */
    948    List<? extends Config> getConfigList(String path);
    949
    950    /**
    951     * Gets a list value with any kind of elements.  Throws if the
    952     * path is unset or null or not a list. Each element is
    953     * "unwrapped" (see {@link ConfigValue#unwrapped()}).
    954     *
    955     * @param path
    956     *            the path to the list value.
    957     * @return the list at the path
    958     * @throws ConfigException.Missing
    959     *             if value is absent or null
    960     * @throws ConfigException.WrongType
    961     *             if value is not convertible to a list
    962     */
    963    List<? extends Object> getAnyRefList(String path);
    964
    965    /**
    966     * Gets a list value with elements representing a size in
    967     * bytes.  Throws if the path is unset or null or not a list
    968     * or contains values not convertible to memory sizes.
    969     *
    970     * @param path
    971     *            the path to the list value.
    972     * @return the list at the path
    973     * @throws ConfigException.Missing
    974     *             if value is absent or null
    975     * @throws ConfigException.WrongType
    976     *             if value is not convertible to a list of memory sizes
    977     */
    978    List<Long> getBytesList(String path);
    979
    980    /**
    981     * Gets a list, converting each value in the list to a memory size, using the
    982     * same rules as {@link #getMemorySize(String)}.
    983     *
    984     * @since 1.3.0
    985     * @param path
    986     *            a path expression
    987     * @return list of memory sizes
    988     * @throws ConfigException.Missing
    989     *             if value is absent or null
    990     * @throws ConfigException.WrongType
    991     *             if value is not convertible to a list of memory sizes
    992     */
    993    List<ConfigMemorySize> getMemorySizeList(String path);
    994
    995    /**
    996     * @deprecated  As of release 1.1, replaced by {@link #getDurationList(String, TimeUnit)}
    997     * @param path the path
    998     * @return list of millisecond values
    999     */
    1000    @Deprecated List<Long> getMillisecondsList(String path);
    1001
    1002    /**
    1003     * @deprecated  As of release 1.1, replaced by {@link #getDurationList(String, TimeUnit)}
    1004     * @param path the path
    1005     * @return list of nanosecond values
    1006     */
    1007    @Deprecated List<Long> getNanosecondsList(String path);
    1008
    1009    /**
    1010     * Gets a list, converting each value in the list to a duration, using the
    1011     * same rules as {@link #getDuration(String, TimeUnit)}.
    1012     *
    1013     * @since 1.2.0
    1014     * @param path
    1015     *            a path expression
    1016     * @param unit
    1017     *            time units of the returned values
    1018     * @return list of durations, in the requested units
    1019     */
    1020    List<Long> getDurationList(String path, TimeUnit unit);
    1021
    1022    /**
    1023     * Gets a list, converting each value in the list to a duration, using the
    1024     * same rules as {@link #getDuration(String)}.
    1025     *
    1026     * @since 1.3.0
    1027     * @param path
    1028     *            a path expression
    1029     * @return list of durations
    1030     */
    1031    List<Duration> getDurationList(String path);
    1032
    1033    /**
    1034     * Clone the config with only the given path (and its children) retained;
    1035     * all sibling paths are removed.
    1036     * <p>
    1037     * Note that path expressions have a syntax and sometimes require quoting
    1038     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    1039     *
    1040     * @param path
    1041     *            path to keep
    1042     * @return a copy of the config minus all paths except the one specified
    1043     */
    1044    Config withOnlyPath(String path);
    1045
    1046    /**
    1047     * Clone the config with the given path removed.
    1048     * <p>
    1049     * Note that path expressions have a syntax and sometimes require quoting
    1050     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    1051     *
    1052     * @param path
    1053     *            path expression to remove
    1054     * @return a copy of the config minus the specified path
    1055     */
    1056    Config withoutPath(String path);
    1057
    1058    /**
    1059     * Places the config inside another {@code Config} at the given path.
    1060     * <p>
    1061     * Note that path expressions have a syntax and sometimes require quoting
    1062     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    1063     *
    1064     * @param path
    1065     *            path expression to store this config at.
    1066     * @return a {@code Config} instance containing this config at the given
    1067     *         path.
    1068     */
    1069    Config atPath(String path);
    1070
    1071    /**
    1072     * Places the config inside a {@code Config} at the given key. See also
    1073     * atPath(). Note that a key is NOT a path expression (see
    1074     * {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    1075     *
    1076     * @param key
    1077     *            key to store this config at.
    1078     * @return a {@code Config} instance containing this config at the given
    1079     *         key.
    1080     */
    1081    Config atKey(String key);
    1082
    1083    /**
    1084     * Returns a {@code Config} based on this one, but with the given path set
    1085     * to the given value. Does not modify this instance (since it's immutable).
    1086     * If the path already has a value, that value is replaced. To remove a
    1087     * value, use withoutPath().
    1088     * <p>
    1089     * Note that path expressions have a syntax and sometimes require quoting
    1090     * (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
    1091     *
    1092     * @param path
    1093     *            path expression for the value's new location
    1094     * @param value
    1095     *            value at the new path
    1096     * @return the new instance with the new map entry
    1097     */
    1098    Config withValue(String path, ConfigValue value);
    1099}