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