mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
add ConfigUtil.joinPath, .splitPath, .quoteString
To help people get their escaping and quoting right.
This commit is contained in:
parent
aa8a258b59
commit
6991862def
@ -34,6 +34,10 @@ import java.util.Set;
|
||||
* {@code ConfigObject} is a tree of nested maps from <em>keys</em> to values.
|
||||
*
|
||||
* <p>
|
||||
* Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
|
||||
* between path expressions and individual path elements (keys).
|
||||
*
|
||||
* <p>
|
||||
* Another difference between {@code Config} and {@code ConfigObject} is that
|
||||
* conceptually, {@code ConfigValue}s with a {@link ConfigValue#valueType()
|
||||
* valueType()} of {@link ConfigValueType#NULL NULL} exist in a
|
||||
@ -264,7 +268,7 @@ public interface Config extends ConfigMergeable {
|
||||
* recursing {@link #root() the root object}. Note that this is very
|
||||
* different from <code>root().entrySet()</code> which returns the set of
|
||||
* immediate-child keys in the root object and includes null values.
|
||||
*
|
||||
*
|
||||
* @return set of paths with non-null values, built up by recursing the
|
||||
* entire tree of {@link ConfigObject}
|
||||
*/
|
||||
|
@ -8,34 +8,38 @@ import java.util.Map;
|
||||
/**
|
||||
* Subtype of {@link ConfigValue} representing an object (dictionary, map)
|
||||
* value, as in JSON's <code>{ "a" : 42 }</code> syntax.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* {@code ConfigObject} implements {@code java.util.Map<String, ConfigValue>} so
|
||||
* you can use it like a regular Java map. Or call {@link #unwrapped()} to
|
||||
* unwrap the map to a map with plain Java values rather than
|
||||
* {@code ConfigValue}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Like all {@link ConfigValue} subtypes, {@code ConfigObject} is immutable.
|
||||
* This makes it threadsafe and you never have to create "defensive copies." The
|
||||
* mutator methods from {@link java.util.Map} all throw
|
||||
* {@link java.lang.UnsupportedOperationException}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The {@link ConfigValue#valueType} method on an object returns
|
||||
* {@link ConfigValueType#OBJECT}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* In most cases you want to use the {@link Config} interface rather than this
|
||||
* one. Call {@link #toConfig()} to convert a {@code ConfigObject} to a
|
||||
* {@code Config}.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The API for a {@code ConfigObject} is in terms of keys, while the API for a
|
||||
* {@link Config} is in terms of path expressions. Conceptually,
|
||||
* {@code ConfigObject} is a tree of maps from keys to values, while a
|
||||
* {@code ConfigObject} is a one-level map from paths to values.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert
|
||||
* between path expressions and individual path elements (keys).
|
||||
*
|
||||
* <p>
|
||||
* A {@code ConfigObject} may contain null values, which will have
|
||||
* {@link ConfigValue#valueType()} equal to {@link ConfigValueType#NULL}. If
|
||||
@ -43,7 +47,7 @@ import java.util.Map;
|
||||
* file (or wherever this value tree came from). If {@code get()} returns a
|
||||
* {@link ConfigValue} with type {@code ConfigValueType#NULL} then the key was
|
||||
* set to null explicitly in the config file.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <em>Do not implement {@code ConfigObject}</em>; it should only be implemented
|
||||
* by the config library. Arbitrary implementations will not work because the
|
||||
|
70
config/src/main/java/com/typesafe/config/ConfigUtil.java
Normal file
70
config/src/main/java/com/typesafe/config/ConfigUtil.java
Normal file
@ -0,0 +1,70 @@
|
||||
package com.typesafe.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.typesafe.config.impl.ConfigImplUtil;
|
||||
|
||||
public final class ConfigUtil {
|
||||
private ConfigUtil() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes and escapes a string, as in the JSON specification.
|
||||
*
|
||||
* @param s
|
||||
* a string
|
||||
* @return the string quoted and escaped
|
||||
*/
|
||||
public static String quoteString(String s) {
|
||||
return ConfigImplUtil.renderJsonString(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of keys to a path expression, by quoting the path
|
||||
* elements as needed and then joining them separated by a period. A path
|
||||
* expression is usable with a {@link Config}, while individual path
|
||||
* elements are usable with a {@link ConfigObject}.
|
||||
*
|
||||
* @param elements
|
||||
* the keys in the path
|
||||
* @return a path expression
|
||||
* @throws ConfigException
|
||||
* if there are no elements
|
||||
*/
|
||||
public static String joinPath(String... elements) {
|
||||
return ConfigImplUtil.joinPath(elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of strings to a path expression, by quoting the path
|
||||
* elements as needed and then joining them separated by a period. A path
|
||||
* expression is usable with a {@link Config}, while individual path
|
||||
* elements are usable with a {@link ConfigObject}.
|
||||
*
|
||||
* @param elements
|
||||
* the keys in the path
|
||||
* @return a path expression
|
||||
* @throws ConfigException
|
||||
* if the list is empty
|
||||
*/
|
||||
public static String joinPath(List<String> elements) {
|
||||
return ConfigImplUtil.joinPath(elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path expression into a list of keys, by splitting on period
|
||||
* and unquoting the individual path elements. A path expression is usable
|
||||
* with a {@link Config}, while individual path elements are usable with a
|
||||
* {@link ConfigObject}.
|
||||
*
|
||||
* @param path
|
||||
* a path expression
|
||||
* @return the individual keys in the path
|
||||
* @throws ConfigException
|
||||
* if the path expression is invalid
|
||||
*/
|
||||
public static List<String> splitPath(String path) {
|
||||
return ConfigImplUtil.splitPath(path);
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ package com.typesafe.config.impl;
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.typesafe.config.ConfigException;
|
||||
|
||||
@ -23,7 +25,11 @@ final public class ConfigImplUtil {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
static String renderJsonString(String s) {
|
||||
/**
|
||||
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
|
||||
* may change.
|
||||
*/
|
||||
public static String renderJsonString(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('"');
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
@ -146,4 +152,34 @@ final public class ConfigImplUtil {
|
||||
return new File(url.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
|
||||
* may change. You can use the version in ConfigUtil instead.
|
||||
*/
|
||||
public static String joinPath(String... elements) {
|
||||
return (new Path(elements)).render();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
|
||||
* may change. You can use the version in ConfigUtil instead.
|
||||
*/
|
||||
public static String joinPath(List<String> elements) {
|
||||
return joinPath(elements.toArray(new String[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is public ONLY for use by the "config" package, DO NOT USE this ABI
|
||||
* may change. You can use the version in ConfigUtil instead.
|
||||
*/
|
||||
public static List<String> splitPath(String path) {
|
||||
Path p = Path.newPath(path);
|
||||
List<String> elements = new ArrayList<String>();
|
||||
while (p != null) {
|
||||
elements.add(p.first());
|
||||
p = p.remainder();
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
@ -433,4 +433,35 @@ class PublicApiTest extends TestUtils {
|
||||
assertFalse("same urls in " + v1.origin + " " + v2.origin, v1.origin.url == v2.origin.url)
|
||||
assertFalse(v1.origin.filename == v2.origin.filename)
|
||||
}
|
||||
|
||||
@Test
|
||||
def splitAndJoinPath() {
|
||||
// the actual join-path logic should be tested OK in the non-public-API tests,
|
||||
// this is just to test the public wrappers.
|
||||
|
||||
assertEquals("\"\".a.b.\"$\"", ConfigUtil.joinPath("", "a", "b", "$"))
|
||||
assertEquals("\"\".a.b.\"$\"", ConfigUtil.joinPath(Seq("", "a", "b", "$").asJava))
|
||||
assertEquals(Seq("", "a", "b", "$"), ConfigUtil.splitPath("\"\".a.b.\"$\"").asScala)
|
||||
|
||||
// invalid stuff throws
|
||||
intercept[ConfigException] {
|
||||
ConfigUtil.splitPath("$")
|
||||
}
|
||||
intercept[ConfigException] {
|
||||
ConfigUtil.joinPath()
|
||||
}
|
||||
intercept[ConfigException] {
|
||||
ConfigUtil.joinPath(Collections.emptyList[String]())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def quoteString() {
|
||||
// the actual quote logic shoudl be tested OK in the non-public-API tests,
|
||||
// this is just to test the public wrapper.
|
||||
|
||||
assertEquals("\"\"", ConfigUtil.quoteString(""))
|
||||
assertEquals("\"a\"", ConfigUtil.quoteString("a"))
|
||||
assertEquals("\"\\n\"", ConfigUtil.quoteString("\n"))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user