mirror of
https://github.com/lightbend/config.git
synced 2025-03-22 23:30:27 +08:00
Merge f2ae46d140
into eeb95825bf
This commit is contained in:
commit
3d5d65c410
@ -17,40 +17,40 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* (booleans, strings, numbers, lists, or objects), represented by
|
* (booleans, strings, numbers, lists, or objects), represented by
|
||||||
* {@link ConfigValue} instances. Values accessed through the
|
* {@link ConfigValue} instances. Values accessed through the
|
||||||
* <code>Config</code> interface are never null.
|
* <code>Config</code> interface are never null.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* {@code Config} is an immutable object and thus safe to use from multiple
|
* {@code Config} is an immutable object and thus safe to use from multiple
|
||||||
* threads. There's never a need for "defensive copies."
|
* threads. There's never a need for "defensive copies."
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Fundamental operations on a {@code Config} include getting configuration
|
* Fundamental operations on a {@code Config} include getting configuration
|
||||||
* values, <em>resolving</em> substitutions with {@link Config#resolve()}, and
|
* values, <em>resolving</em> substitutions with {@link Config#resolve()}, and
|
||||||
* merging configs using {@link Config#withFallback(ConfigMergeable)}.
|
* merging configs using {@link Config#withFallback(ConfigMergeable)}.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* All operations return a new immutable {@code Config} rather than modifying
|
* All operations return a new immutable {@code Config} rather than modifying
|
||||||
* the original instance.
|
* the original instance.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Examples</strong>
|
* <strong>Examples</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* You can find an example app and library <a
|
* You can find an example app and library <a
|
||||||
* href="https://github.com/lightbend/config/tree/master/examples">on
|
* href="https://github.com/lightbend/config/tree/master/examples">on
|
||||||
* GitHub</a>. Also be sure to read the <a
|
* GitHub</a>. Also be sure to read the <a
|
||||||
* href="package-summary.html#package_description">package overview</a> which
|
* href="package-summary.html#package_description">package overview</a> which
|
||||||
* describes the big picture as shown in those examples.
|
* describes the big picture as shown in those examples.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Paths, keys, and Config vs. ConfigObject</strong>
|
* <strong>Paths, keys, and Config vs. ConfigObject</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <code>Config</code> is a view onto a tree of {@link ConfigObject}; the
|
* <code>Config</code> is a view onto a tree of {@link ConfigObject}; the
|
||||||
* corresponding object tree can be found through {@link Config#root()}.
|
* corresponding object tree can be found through {@link Config#root()}.
|
||||||
* <code>ConfigObject</code> is a map from config <em>keys</em>, rather than
|
* <code>ConfigObject</code> is a map from config <em>keys</em>, rather than
|
||||||
* paths, to config values. Think of <code>ConfigObject</code> as a JSON object
|
* paths, to config values. Think of <code>ConfigObject</code> as a JSON object
|
||||||
* and <code>Config</code> as a configuration API.
|
* and <code>Config</code> as a configuration API.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The API tries to consistently use the terms "key" and "path." A key is a key
|
* The API tries to consistently use the terms "key" and "path." A key is a key
|
||||||
* in a JSON object; it's just a string that's the key in a map. A "path" is a
|
* in a JSON object; it's just a string that's the key in a map. A "path" is a
|
||||||
@ -61,17 +61,17 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* period-separated so "a.b.c" looks for key c in object b in object a in the
|
* period-separated so "a.b.c" looks for key c in object b in object a in the
|
||||||
* root object. Sometimes double quotes are needed around special characters in
|
* root object. Sometimes double quotes are needed around special characters in
|
||||||
* path expressions.
|
* path expressions.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The API for a {@code Config} is in terms of path expressions, while the API
|
* The API for a {@code Config} is in terms of path expressions, while the API
|
||||||
* for a {@code ConfigObject} is in terms of keys. Conceptually, {@code Config}
|
* for a {@code ConfigObject} is in terms of keys. Conceptually, {@code Config}
|
||||||
* is a one-level map from <em>paths</em> to values, while a
|
* is a one-level map from <em>paths</em> to values, while a
|
||||||
* {@code ConfigObject} is a tree of nested maps from <em>keys</em> to values.
|
* {@code ConfigObject} is a tree of nested maps from <em>keys</em> to values.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
|
* Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
|
||||||
* between path expressions and individual path elements (keys).
|
* between path expressions and individual path elements (keys).
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Another difference between {@code Config} and {@code ConfigObject} is that
|
* Another difference between {@code Config} and {@code ConfigObject} is that
|
||||||
* conceptually, {@code ConfigValue}s with a {@link ConfigValue#valueType()
|
* conceptually, {@code ConfigValue}s with a {@link ConfigValue#valueType()
|
||||||
@ -82,7 +82,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Getting configuration values</strong>
|
* <strong>Getting configuration values</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The "getters" on a {@code Config} all work in the same way. They never return
|
* The "getters" on a {@code Config} all work in the same way. They never return
|
||||||
* null, nor do they return a {@code ConfigValue} with
|
* null, nor do they return a {@code ConfigValue} with
|
||||||
@ -93,35 +93,35 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* thrown. {@link ConfigException.WrongType} will be thrown anytime you ask for
|
* thrown. {@link ConfigException.WrongType} will be thrown anytime you ask for
|
||||||
* a type and the value has an incompatible type. Reasonable type conversions
|
* a type and the value has an incompatible type. Reasonable type conversions
|
||||||
* are performed for you though.
|
* are performed for you though.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Iteration</strong>
|
* <strong>Iteration</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If you want to iterate over the contents of a {@code Config}, you can get its
|
* If you want to iterate over the contents of a {@code Config}, you can get its
|
||||||
* {@code ConfigObject} with {@link #root()}, and then iterate over the
|
* {@code ConfigObject} with {@link #root()}, and then iterate over the
|
||||||
* {@code ConfigObject} (which implements <code>java.util.Map</code>). Or, you
|
* {@code ConfigObject} (which implements <code>java.util.Map</code>). Or, you
|
||||||
* can use {@link #entrySet()} which recurses the object tree for you and builds
|
* can use {@link #entrySet()} which recurses the object tree for you and builds
|
||||||
* up a <code>Set</code> of all path-value pairs where the value is not null.
|
* up a <code>Set</code> of all path-value pairs where the value is not null.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Resolving substitutions</strong>
|
* <strong>Resolving substitutions</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <em>Substitutions</em> are the <code>${foo.bar}</code> syntax in config
|
* <em>Substitutions</em> are the <code>${foo.bar}</code> syntax in config
|
||||||
* files, described in the <a href=
|
* files, described in the <a href=
|
||||||
* "https://github.com/lightbend/config/blob/master/HOCON.md#substitutions"
|
* "https://github.com/lightbend/config/blob/master/HOCON.md#substitutions"
|
||||||
* >specification</a>. Resolving substitutions replaces these references with real
|
* >specification</a>. Resolving substitutions replaces these references with real
|
||||||
* values.
|
* values.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Before using a {@code Config} it's necessary to call {@link Config#resolve()}
|
* Before using a {@code Config} it's necessary to call {@link Config#resolve()}
|
||||||
* to handle substitutions (though {@link ConfigFactory#load()} and similar
|
* to handle substitutions (though {@link ConfigFactory#load()} and similar
|
||||||
* methods will do the resolve for you already).
|
* methods will do the resolve for you already).
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Merging</strong>
|
* <strong>Merging</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The full <code>Config</code> for your application can be constructed using
|
* The full <code>Config</code> for your application can be constructed using
|
||||||
* the associative operation {@link Config#withFallback(ConfigMergeable)}. If
|
* the associative operation {@link Config#withFallback(ConfigMergeable)}. If
|
||||||
@ -132,10 +132,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* should go either just above or just below <code>application.conf</code>,
|
* should go either just above or just below <code>application.conf</code>,
|
||||||
* keeping <code>reference.conf</code> at the bottom and system properties at
|
* keeping <code>reference.conf</code> at the bottom and system properties at
|
||||||
* the top).
|
* the top).
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>Serialization</strong>
|
* <strong>Serialization</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Convert a <code>Config</code> to a JSON or HOCON string by calling
|
* Convert a <code>Config</code> to a JSON or HOCON string by calling
|
||||||
* {@link ConfigObject#render()} on the root object,
|
* {@link ConfigObject#render()} on the root object,
|
||||||
@ -145,19 +145,19 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* that <code>Config</code> does not remember the formatting of the original
|
* that <code>Config</code> does not remember the formatting of the original
|
||||||
* file, so if you load, modify, and re-save a config file, it will be
|
* file, so if you load, modify, and re-save a config file, it will be
|
||||||
* substantially reformatted.
|
* substantially reformatted.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* As an alternative to {@link ConfigObject#render()}, the
|
* As an alternative to {@link ConfigObject#render()}, the
|
||||||
* <code>toString()</code> method produces a debug-output-oriented
|
* <code>toString()</code> method produces a debug-output-oriented
|
||||||
* representation (which is not valid JSON).
|
* representation (which is not valid JSON).
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Java serialization is supported as well for <code>Config</code> and all
|
* Java serialization is supported as well for <code>Config</code> and all
|
||||||
* subtypes of <code>ConfigValue</code>.
|
* subtypes of <code>ConfigValue</code>.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <strong>This is an interface but don't implement it yourself</strong>
|
* <strong>This is an interface but don't implement it yourself</strong>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <em>Do not implement {@code Config}</em>; it should only be implemented by
|
* <em>Do not implement {@code Config}</em>; it should only be implemented by
|
||||||
* the config library. Arbitrary implementations will not work because the
|
* the config library. Arbitrary implementations will not work because the
|
||||||
@ -194,12 +194,12 @@ public interface Config extends ConfigMergeable {
|
|||||||
* <code>Config</code> as the root object, that is, a substitution
|
* <code>Config</code> as the root object, that is, a substitution
|
||||||
* <code>${foo.bar}</code> will be replaced with the result of
|
* <code>${foo.bar}</code> will be replaced with the result of
|
||||||
* <code>getValue("foo.bar")</code>.
|
* <code>getValue("foo.bar")</code>.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This method uses {@link ConfigResolveOptions#defaults()}, there is
|
* This method uses {@link ConfigResolveOptions#defaults()}, there is
|
||||||
* another variant {@link Config#resolve(ConfigResolveOptions)} which lets
|
* another variant {@link Config#resolve(ConfigResolveOptions)} which lets
|
||||||
* you specify non-default options.
|
* you specify non-default options.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* A given {@link Config} must be resolved before using it to retrieve
|
* A given {@link Config} must be resolved before using it to retrieve
|
||||||
* config values, but ideally should be resolved one time for your entire
|
* config values, but ideally should be resolved one time for your entire
|
||||||
@ -207,7 +207,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* substitutions that could have resolved with all fallbacks available may
|
* substitutions that could have resolved with all fallbacks available may
|
||||||
* not resolve, which will be potentially confusing for your application's
|
* not resolve, which will be potentially confusing for your application's
|
||||||
* users.
|
* users.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <code>resolve()</code> should be invoked on root config objects, rather
|
* <code>resolve()</code> should be invoked on root config objects, rather
|
||||||
* than on a subtree (a subtree is the result of something like
|
* than on a subtree (a subtree is the result of something like
|
||||||
@ -217,24 +217,24 @@ public interface Config extends ConfigMergeable {
|
|||||||
* from the root. For example, if you did
|
* from the root. For example, if you did
|
||||||
* <code>config.getConfig("foo").resolve()</code> on the below config file,
|
* <code>config.getConfig("foo").resolve()</code> on the below config file,
|
||||||
* it would not work:
|
* it would not work:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* common-value = 10
|
* common-value = 10
|
||||||
* foo {
|
* foo {
|
||||||
* whatever = ${common-value}
|
* whatever = ${common-value}
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Many methods on {@link ConfigFactory} such as
|
* Many methods on {@link ConfigFactory} such as
|
||||||
* {@link ConfigFactory#load()} automatically resolve the loaded
|
* {@link ConfigFactory#load()} automatically resolve the loaded
|
||||||
* <code>Config</code> on the loaded stack of config files.
|
* <code>Config</code> on the loaded stack of config files.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Resolving an already-resolved config is a harmless no-op, but again, it
|
* Resolving an already-resolved config is a harmless no-op, but again, it
|
||||||
* is best to resolve an entire stack of fallbacks (such as all your config
|
* is best to resolve an entire stack of fallbacks (such as all your config
|
||||||
* files combined) rather than resolving each one individually.
|
* files combined) rather than resolving each one individually.
|
||||||
*
|
*
|
||||||
* @return an immutable object with substitutions resolved
|
* @return an immutable object with substitutions resolved
|
||||||
* @throws ConfigException.UnresolvedSubstitution
|
* @throws ConfigException.UnresolvedSubstitution
|
||||||
* if any substitutions refer to nonexistent paths
|
* if any substitutions refer to nonexistent paths
|
||||||
@ -261,7 +261,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* completely resolved. A newly-loaded config may or may not be completely
|
* completely resolved. A newly-loaded config may or may not be completely
|
||||||
* resolved depending on whether there were substitutions present in the
|
* resolved depending on whether there were substitutions present in the
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* @return true if there are no unresolved substitutions remaining in this
|
* @return true if there are no unresolved substitutions remaining in this
|
||||||
* configuration.
|
* configuration.
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
@ -283,7 +283,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* multiple times with multiple sources (using
|
* multiple times with multiple sources (using
|
||||||
* {@link ConfigResolveOptions#setAllowUnresolved(boolean)} so the partial
|
* {@link ConfigResolveOptions#setAllowUnresolved(boolean)} so the partial
|
||||||
* resolves don't fail).
|
* resolves don't fail).
|
||||||
*
|
*
|
||||||
* @param source
|
* @param source
|
||||||
* configuration to pull values from
|
* configuration to pull values from
|
||||||
* @return an immutable object with substitutions resolved
|
* @return an immutable object with substitutions resolved
|
||||||
@ -299,7 +299,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
/**
|
/**
|
||||||
* Like {@link Config#resolveWith(Config)} but allows you to specify
|
* Like {@link Config#resolveWith(Config)} but allows you to specify
|
||||||
* non-default options.
|
* non-default options.
|
||||||
*
|
*
|
||||||
* @param source
|
* @param source
|
||||||
* source configuration to pull values from
|
* source configuration to pull values from
|
||||||
* @param options
|
* @param options
|
||||||
@ -400,17 +400,17 @@ public interface Config extends ConfigMergeable {
|
|||||||
* {@link ConfigObject}: it looks for a path expression, not a key; and it
|
* {@link ConfigObject}: it looks for a path expression, not a key; and it
|
||||||
* returns false for null values, while {@code containsKey()} returns true
|
* returns false for null values, while {@code containsKey()} returns true
|
||||||
* indicating that the object contains a null value for the key.
|
* indicating that the object contains a null value for the key.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If a path exists according to {@link #hasPath(String)}, then
|
* If a path exists according to {@link #hasPath(String)}, then
|
||||||
* {@link #getValue(String)} will never throw an exception. However, the
|
* {@link #getValue(String)} will never throw an exception. However, the
|
||||||
* typed getters, such as {@link #getInt(String)}, will still throw if the
|
* typed getters, such as {@link #getInt(String)}, will still throw if the
|
||||||
* value is not convertible to the requested type.
|
* value is not convertible to the requested type.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Note that path expressions have a syntax and sometimes require quoting
|
* Note that path expressions have a syntax and sometimes require quoting
|
||||||
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* the path expression
|
* the path expression
|
||||||
* @return true if a non-null value is present at the path
|
* @return true if a non-null value is present at the path
|
||||||
@ -485,7 +485,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* (OK, this is a slight lie: <code>Config</code> entries may contain
|
* (OK, this is a slight lie: <code>Config</code> entries may contain
|
||||||
* {@link ConfigList} and the lists may contain objects. But no objects are
|
* {@link ConfigList} and the lists may contain objects. But no objects are
|
||||||
* directly included as entry values.)
|
* directly included as entry values.)
|
||||||
*
|
*
|
||||||
* @return set of paths with non-null values, built up by recursing the
|
* @return set of paths with non-null values, built up by recursing the
|
||||||
* entire tree of {@link ConfigObject} and creating an entry for
|
* entire tree of {@link ConfigObject} and creating an entry for
|
||||||
* each leaf value.
|
* each leaf value.
|
||||||
@ -756,9 +756,9 @@ public interface Config extends ConfigMergeable {
|
|||||||
* suffixes like "10m" or "5ns" as documented in the <a
|
* suffixes like "10m" or "5ns" as documented in the <a
|
||||||
* href="https://github.com/lightbend/config/blob/master/HOCON.md">the
|
* href="https://github.com/lightbend/config/blob/master/HOCON.md">the
|
||||||
* spec</a>.
|
* spec</a>.
|
||||||
*
|
*
|
||||||
* @since 1.2.0
|
* @since 1.2.0
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* path expression
|
* path expression
|
||||||
* @param unit
|
* @param unit
|
||||||
@ -803,7 +803,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* href="https://github.com/lightbend/config/blob/master/HOCON.md">the
|
* href="https://github.com/lightbend/config/blob/master/HOCON.md">the
|
||||||
* spec</a>. This method never returns null.
|
* spec</a>. This method never returns null.
|
||||||
*
|
*
|
||||||
* @since 1.3.0
|
* @since 1.3.2
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* path expression
|
* path expression
|
||||||
@ -822,7 +822,11 @@ public interface Config extends ConfigMergeable {
|
|||||||
* This method will first try get get the value as a java.time.Duration, and if unsuccessful,
|
* This method will first try get get the value as a java.time.Duration, and if unsuccessful,
|
||||||
* then as a java.time.Period.
|
* then as a java.time.Period.
|
||||||
* This means that values like "5m" will be parsed as 5 minutes rather than 5 months
|
* This means that values like "5m" will be parsed as 5 minutes rather than 5 months
|
||||||
* @param path path expression
|
*
|
||||||
|
* @since 1.3.2
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* path expression
|
||||||
* @return the temporal value at the requested path
|
* @return the temporal value at the requested path
|
||||||
* @throws ConfigException.Missing
|
* @throws ConfigException.Missing
|
||||||
* if value is absent or null
|
* if value is absent or null
|
||||||
@ -1070,13 +1074,50 @@ public interface Config extends ConfigMergeable {
|
|||||||
*/
|
*/
|
||||||
List<Duration> getDurationList(String path);
|
List<Duration> getDurationList(String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list, converting each value in the list to a period,
|
||||||
|
* using same rules as {@link #getPeriod(String)}.
|
||||||
|
*
|
||||||
|
* @since 1.3.3
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* path expression
|
||||||
|
* @return list of periods
|
||||||
|
* @throws ConfigException.Missing
|
||||||
|
* if value is absent or null
|
||||||
|
* @throws ConfigException.WrongType
|
||||||
|
* if value is not convertible to Long or String
|
||||||
|
* @throws ConfigException.BadValue
|
||||||
|
* if value cannot be parsed as a number of the given TimeUnit
|
||||||
|
*/
|
||||||
|
List<Period> getPeriodList(String path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list, converting each value in the list to a temporal amount,
|
||||||
|
* using the same rules as {@link #getTemporal(String)}.
|
||||||
|
*
|
||||||
|
* @since 1.3.3
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* path expression
|
||||||
|
* @return list of temporal values
|
||||||
|
* @throws ConfigException.Missing
|
||||||
|
* if value is absent or null
|
||||||
|
* @throws ConfigException.WrongType
|
||||||
|
* if value is not convertible to Long or String
|
||||||
|
* @throws ConfigException.BadValue
|
||||||
|
* if value cannot be parsed as a TemporalAmount
|
||||||
|
*/
|
||||||
|
List<TemporalAmount> getTemporalList(String path);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the config with only the given path (and its children) retained;
|
* Clone the config with only the given path (and its children) retained;
|
||||||
* all sibling paths are removed.
|
* all sibling paths are removed.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that path expressions have a syntax and sometimes require quoting
|
* Note that path expressions have a syntax and sometimes require quoting
|
||||||
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* path to keep
|
* path to keep
|
||||||
* @return a copy of the config minus all paths except the one specified
|
* @return a copy of the config minus all paths except the one specified
|
||||||
@ -1088,7 +1129,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* <p>
|
* <p>
|
||||||
* Note that path expressions have a syntax and sometimes require quoting
|
* Note that path expressions have a syntax and sometimes require quoting
|
||||||
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* path expression to remove
|
* path expression to remove
|
||||||
* @return a copy of the config minus the specified path
|
* @return a copy of the config minus the specified path
|
||||||
@ -1100,7 +1141,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* <p>
|
* <p>
|
||||||
* Note that path expressions have a syntax and sometimes require quoting
|
* Note that path expressions have a syntax and sometimes require quoting
|
||||||
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* path expression to store this config at.
|
* path expression to store this config at.
|
||||||
* @return a {@code Config} instance containing this config at the given
|
* @return a {@code Config} instance containing this config at the given
|
||||||
@ -1112,7 +1153,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* Places the config inside a {@code Config} at the given key. See also
|
* Places the config inside a {@code Config} at the given key. See also
|
||||||
* atPath(). Note that a key is NOT a path expression (see
|
* atPath(). Note that a key is NOT a path expression (see
|
||||||
* {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
* {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* key to store this config at.
|
* key to store this config at.
|
||||||
* @return a {@code Config} instance containing this config at the given
|
* @return a {@code Config} instance containing this config at the given
|
||||||
@ -1128,7 +1169,7 @@ public interface Config extends ConfigMergeable {
|
|||||||
* <p>
|
* <p>
|
||||||
* Note that path expressions have a syntax and sometimes require quoting
|
* Note that path expressions have a syntax and sometimes require quoting
|
||||||
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
* (see {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath}).
|
||||||
*
|
*
|
||||||
* @param path
|
* @param path
|
||||||
* path expression for the value's new location
|
* path expression for the value's new location
|
||||||
* @param value
|
* @param value
|
||||||
|
@ -545,6 +545,50 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Period> getPeriodList(String path) {
|
||||||
|
List<Period> l = new ArrayList<Period>();
|
||||||
|
List<? extends ConfigValue> list = getList(path);
|
||||||
|
for (ConfigValue v : list) {
|
||||||
|
String value;
|
||||||
|
if (v.valueType() == ConfigValueType.STRING) {
|
||||||
|
value = (String) v.unwrapped();
|
||||||
|
} else if (v.valueType() == ConfigValueType.NUMBER) {
|
||||||
|
value = "" + ((Number) v.unwrapped()).longValue();
|
||||||
|
} else {
|
||||||
|
throw new ConfigException.WrongType(v.origin(), path,
|
||||||
|
"period string",
|
||||||
|
v.valueType().name());
|
||||||
|
}
|
||||||
|
l.add(parsePeriod(value, v.origin(), path));
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TemporalAmount> getTemporalList(String path) {
|
||||||
|
List<TemporalAmount> l = new ArrayList<TemporalAmount>();
|
||||||
|
List<? extends ConfigValue> list = getList(path);
|
||||||
|
for (ConfigValue v : list) {
|
||||||
|
String value;
|
||||||
|
if (v.valueType() == ConfigValueType.STRING) {
|
||||||
|
value = (String) v.unwrapped();
|
||||||
|
} else if (v.valueType() == ConfigValueType.NUMBER) {
|
||||||
|
value = "" + ((Number) v.unwrapped()).longValue();
|
||||||
|
} else {
|
||||||
|
throw new ConfigException.WrongType(v.origin(), path,
|
||||||
|
"duration or period string",
|
||||||
|
v.valueType().name());
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
l.add(Duration.ofNanos(parseDuration(value, v.origin(), path)));
|
||||||
|
} catch (ConfigException.BadValue e){
|
||||||
|
l.add(parsePeriod(value, v.origin(), path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public List<Long> getMillisecondsList(String path) {
|
public List<Long> getMillisecondsList(String path) {
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
"ofBoolean" : [true, false],
|
"ofBoolean" : [true, false],
|
||||||
"ofArray" : [${arrays.ofString}, ${arrays.ofString}, ${arrays.ofString}],
|
"ofArray" : [${arrays.ofString}, ${arrays.ofString}, ${arrays.ofString}],
|
||||||
"ofObject" : [${ints}, ${booleans}, ${strings}],
|
"ofObject" : [${ints}, ${booleans}, ${strings}],
|
||||||
|
"ofPeriod" : [1d, 2, 3 weeks, 5 mo, 8y],
|
||||||
|
"ofTemporal" : [1d, 2, 3 weeks, 5 mo, 8y, 13m],
|
||||||
"firstElementNotASubst" : [ "a", ${strings.b} ]
|
"firstElementNotASubst" : [ "a", ${strings.b} ]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.typesafe.config.impl
|
package com.typesafe.config.impl
|
||||||
|
|
||||||
import java.time.temporal.{ ChronoUnit, TemporalUnit }
|
import java.time.{ Duration, Period }
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
import org.junit.Assert._
|
import org.junit.Assert._
|
||||||
import org.junit._
|
import org.junit._
|
||||||
@ -602,6 +603,10 @@ class ConfigTest extends TestUtils {
|
|||||||
val listOfLists = conf.getAnyRefList("arrays.ofArray").asScala map { _.asInstanceOf[java.util.List[_]].asScala }
|
val listOfLists = conf.getAnyRefList("arrays.ofArray").asScala map { _.asInstanceOf[java.util.List[_]].asScala }
|
||||||
assertEquals(Seq(Seq("a", "b", "c"), Seq("a", "b", "c"), Seq("a", "b", "c")), listOfLists)
|
assertEquals(Seq(Seq("a", "b", "c"), Seq("a", "b", "c"), Seq("a", "b", "c")), listOfLists)
|
||||||
assertEquals(3, conf.getObjectList("arrays.ofObject").asScala.length)
|
assertEquals(3, conf.getObjectList("arrays.ofObject").asScala.length)
|
||||||
|
val listOfPeriods = Seq(Period.ofDays(1), Period.ofDays(2), Period.ofWeeks(3), Period.ofMonths(5), Period.ofYears(8))
|
||||||
|
assertEquals(listOfPeriods, conf.getPeriodList("arrays.ofPeriod").asScala)
|
||||||
|
val listOfTemporals = Seq(Duration.ofHours(24), Duration.ofMillis(2), Period.ofWeeks(3), Period.ofMonths(5), Period.ofYears(8), Duration.ofMinutes(13))
|
||||||
|
assertEquals(listOfTemporals, conf.getTemporalList("arrays.ofTemporal").asScala)
|
||||||
|
|
||||||
assertEquals(Seq("a", "b"), conf.getStringList("arrays.firstElementNotASubst").asScala)
|
assertEquals(Seq("a", "b"), conf.getStringList("arrays.firstElementNotASubst").asScala)
|
||||||
|
|
||||||
|
@ -280,13 +280,13 @@ class ConfigValueTest extends TestUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reproduces the issue <a href=https://github.com/lightbend/config/issues/461>#461</a>.
|
* Reproduces the issue <a href=https://github.com/lightbend/config/issues/461>#461</a>.
|
||||||
* <p>
|
* <p>
|
||||||
* We use a custom de-/serializer that encodes String objects in a JDK-incompatible way. Encoding used here
|
* We use a custom de-/serializer that encodes String objects in a JDK-incompatible way. Encoding used here
|
||||||
* is rather simplistic: a long indicating the length in bytes (JDK uses a variable length integer) followed
|
* is rather simplistic: a long indicating the length in bytes (JDK uses a variable length integer) followed
|
||||||
* by the string's bytes. Running this test with the original SerializedConfigValue.readExternal()
|
* by the string's bytes. Running this test with the original SerializedConfigValue.readExternal()
|
||||||
* implementation results in an EOFException thrown during deserialization.
|
* implementation results in an EOFException thrown during deserialization.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
def configConfigCustomSerializable() {
|
def configConfigCustomSerializable() {
|
||||||
val aMap = configMap("a" -> 1, "b" -> 2, "c" -> 3)
|
val aMap = configMap("a" -> 1, "b" -> 2, "c" -> 3)
|
||||||
@ -295,7 +295,7 @@ class ConfigValueTest extends TestUtils {
|
|||||||
|
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
def configListEquality() {
|
def configListEquality() {
|
||||||
val aScalaSeq = Seq(1, 2, 3) map { intValue(_): AbstractConfigValue }
|
val aScalaSeq = Seq(1, 2, 3) map { intValue(_): AbstractConfigValue }
|
||||||
|
Loading…
Reference in New Issue
Block a user