add ConfigUtil.joinPath, .splitPath, .quoteString

To help people get their escaping and quoting right.
This commit is contained in:
Havoc Pennington 2011-12-09 10:20:02 -05:00
parent aa8a258b59
commit 6991862def
5 changed files with 154 additions and 9 deletions

View File

@ -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

View File

@ -37,6 +37,10 @@ import java.util.Map;
* {@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
* {@code get()} returns Java's null then the key was not present in the parsed

View 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);
}
}

View File

@ -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;
}
}

View File

@ -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"))
}
}