mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
implement ConfigObject.hasPath()
This commit is contained in:
parent
f32c8bdd78
commit
f81ab20caa
@ -18,10 +18,13 @@ import java.util.Map;
|
||||
* files, sometimes double quotes are needed around special characters.)
|
||||
*
|
||||
* ConfigObject implements the standard Java Map interface, but the mutator
|
||||
* methods all throw UnsupportedOperationException.
|
||||
* methods all throw UnsupportedOperationException. This Map is immutable.
|
||||
*
|
||||
* TODO add OrNull variants of all these getters? Or better to avoid convenience
|
||||
* API for that?
|
||||
* The Map may contain null values, which will have ConfigValue.valueType() ==
|
||||
* ConfigValueType.NULL. When using methods from the Map interface, such as
|
||||
* get() or containsKey(), these null ConfigValue will be visible. But hasPath()
|
||||
* returns false for null values, and getInt() etc. throw ConfigException.Null
|
||||
* for null values.
|
||||
*/
|
||||
public interface ConfigObject extends ConfigValue, Map<String, ConfigValue> {
|
||||
|
||||
@ -38,6 +41,25 @@ public interface ConfigObject extends ConfigValue, Map<String, ConfigValue> {
|
||||
@Override
|
||||
ConfigObject withFallbacks(ConfigValue... others);
|
||||
|
||||
/**
|
||||
* Checks whether a value is present and non-null at the given path. This
|
||||
* differs in two ways from containsKey(): it looks for a path expression,
|
||||
* not a key; and it returns false for null values, while containsKey()
|
||||
* returns true indicating that the object contains a null value for the
|
||||
* key.
|
||||
*
|
||||
* If a path exists according to hasPath(), then getValue() will never throw
|
||||
* an exception. However, the typed getters, such as getInt(), will still
|
||||
* throw if the value is not convertible to the requested type.
|
||||
*
|
||||
* @param path
|
||||
* the path expression
|
||||
* @return true if a non-null value is present at the path
|
||||
* @throws ConfigException.BadPath
|
||||
* if the path expression is invalid
|
||||
*/
|
||||
boolean hasPath(String path);
|
||||
|
||||
boolean getBoolean(String path);
|
||||
|
||||
Number getNumber(String path);
|
||||
|
@ -121,6 +121,13 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements
|
||||
return ConfigValueType.OBJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPath(String pathExpression) {
|
||||
Path path = Path.newPath(pathExpression);
|
||||
ConfigValue peeked = peekPath(path, null, 0, null);
|
||||
return peeked != null && peeked.valueType() != ConfigValueType.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractConfigObject transformed(ConfigTransformer newTransformer) {
|
||||
if (newTransformer != transformer)
|
||||
|
@ -371,4 +371,38 @@ class ConfigValueTest extends TestUtils {
|
||||
// merge three
|
||||
assertEquals("merge of a,b,c", m(o("a", false), o("b", false), o("c", false)))
|
||||
}
|
||||
|
||||
@Test
|
||||
def hasPathWorks() {
|
||||
val empty = parseObject("{}")
|
||||
|
||||
assertFalse(empty.hasPath("foo"))
|
||||
|
||||
val obj = parseObject("a=null, b.c.d=11, foo=bar")
|
||||
|
||||
// returns true for the non-null values
|
||||
assertTrue(obj.hasPath("foo"))
|
||||
assertTrue(obj.hasPath("b.c.d"))
|
||||
assertTrue(obj.hasPath("b.c"))
|
||||
assertTrue(obj.hasPath("b"))
|
||||
|
||||
// hasPath() is false for null values but containsKey is true
|
||||
assertEquals(nullValue(), obj.get("a"))
|
||||
assertTrue(obj.containsKey("a"))
|
||||
assertFalse(obj.hasPath("a"))
|
||||
|
||||
// false for totally absent values
|
||||
assertFalse(obj.containsKey("notinhere"))
|
||||
assertFalse(obj.hasPath("notinhere"))
|
||||
|
||||
// throws proper exceptions
|
||||
intercept[ConfigException.BadPath] {
|
||||
empty.hasPath("a.")
|
||||
}
|
||||
|
||||
intercept[ConfigException.BadPath] {
|
||||
empty.hasPath("..")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user