You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2022/02/08 16:29:05 UTC

[juneau] branch master updated: Config API cleanup.

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 4469a91  Config API cleanup.
4469a91 is described below

commit 4469a9152937535b7f0ddb4c0e16ad928451fdce
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Tue Feb 8 11:28:44 2022 -0500

    Config API cleanup.
---
 .../main/java/org/apache/juneau/config/Entry.java  | 389 +++------------------
 .../java/org/apache/juneau/config/Section.java     | 151 +-------
 .../org/apache/juneau/rest/test/ConfigTest.java    |   2 +-
 .../apache/juneau/config/ConfigInterfaceTest.java  |   2 +-
 .../java/org/apache/juneau/config/ConfigTest.java  | 152 ++++----
 5 files changed, 142 insertions(+), 554 deletions(-)

diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
index 93216ae..ae6c31a 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
@@ -111,15 +111,6 @@ public class Entry {
 		return isNull() ? def.get() : get();
 	}
 
-	/**
-	 * Returns this entry converted to the specified type.
-	 *
-	 * @param type The type to convert the value to.
-	 * @return This entry converted to the specified type.
-	 */
-	public <T> T to(Class<T> type) {
-		return to((Type)type);
-	}
 
 	/**
 	 * Returns this entry converted to the specified type.
@@ -128,64 +119,7 @@ public class Entry {
 	 * @return This entry converted to the specified type.
 	 */
 	public <T> Optional<T> as(Class<T> type) {
-		return ofNullable(to((Type)type));
-	}
-
-	/**
-	 * Returns this entry converted to the specified value.
-	 *
-	 * <p>
-	 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps).
-	 *
-	 * <h5 class='section'>Examples:</h5>
-	 * <p class='bjava'>
-	 * 	Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-	 *
-	 * 	<jc>// Parse into a linked-list of strings.</jc>
-	 * 	List <jv>list</jv> = <jv>config</jv>.get(<js>"MySection/myListOfStrings"</js>).to(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a linked-list of beans.</jc>
-	 * 	List <jv>list</jv> = <jv>config</jv>.get(<js>"MySection/myListOfBeans"</js>).to(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a linked-list of linked-lists of strings.</jc>
-	 * 	List <jv>list</jv> = <jv>config</jv>.get(<js>"MySection/my2dListOfStrings"</js>).to(LinkedList.<jk>class</jk>,
-	 * 		LinkedList.<jk>class</jk>, String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a map of string keys/values.</jc>
-	 * 	Map <jv>map</jv> = <jv>config</jv>.get(<js>"MySection/myMap"</js>).to(TreeMap.<jk>class</jk>, String.<jk>class</jk>,
-	 * 		String.<jk>class</jk>);
-	 *
-	 * 	<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
-	 * 	Map <jv>map</jv> = <jv>config</jv>.get(<js>"MySection/myMapOfListsOfBeans"</js>).to(TreeMap.<jk>class</jk>, String.<jk>class</jk>,
-	 * 		List.<jk>class</jk>, MyBean.<jk>class</jk>);
-	 * </p>
-	 *
-	 * <p>
-	 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
-	 *
-	 * <p>
-	 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value
-	 * types.
-	 *
-	 * <p>
-	 * The array can be arbitrarily long to indicate arbitrarily complex data structures.
-	 *
-	 * <ul class='notes'>
-	 * 	<li>
-	 * 		Use the {@link #to(Class)} method instead if you don't need a parameterized map/collection.
-	 * </ul>
-	 *
-	 * @param type
-	 * 	The object type to create.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * @param args
-	 * 	The type arguments of the class if it's a collection or map.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 */
-	public <T> T to(Type type, Type...args) {
-		return to(config.parser, type, args);
+		return as((Type)type);
 	}
 
 	/**
@@ -229,7 +163,7 @@ public class Entry {
 	 *
 	 * <ul class='notes'>
 	 * 	<li>
-	 * 		Use the {@link #to(Class)} method instead if you don't need a parameterized map/collection.
+	 * 		Use the {@link #as(Class)} method instead if you don't need a parameterized map/collection.
 	 * </ul>
 	 *
 	 * @param type
@@ -242,11 +176,12 @@ public class Entry {
 	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
 	 */
 	public <T> Optional<T> as(Type type, Type...args) {
-		return ofNullable(to(type, args));
+		return as(config.parser, type, args);
 	}
 
+
 	/**
-	 * Same as {@link #to(Type, Type...)} but specifies the parser to use to parse the entry.
+	 * Same as {@link #as(Type, Type...)} but specifies the parser to use to parse the entry.
 	 *
 	 * @param parser
 	 * 	The parser to use to parse the entry.
@@ -257,24 +192,24 @@ public class Entry {
 	 * 	The type arguments of the class if it's a collection or map.
 	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
 	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
 	 */
 	@SuppressWarnings("unchecked")
-	public <T> T to(Parser parser, Type type, Type...args) {
-		if (isNull()) return null;
+	public <T> Optional<T> as(Parser parser, Type type, Type...args) {
+		if (isNull()) return empty();
 
 		try {
 			String v = toString();
-			if (type == String.class) return (T)toString();
-			if (type == String[].class) return (T)toStringArray();
-			if (type == byte[].class) return (T)toBytes();
-			if (type == int.class) return (T)toInteger();
-			if (type == int.class || type == Integer.class) return (T)toInteger();
-			if (type == long.class || type == Long.class) return (T)toLong();
-			if (type == OMap.class) return (T)toMap();
-			if (type == OList.class) return (T)toList();
-			if (isEmpty()) return null;
-			if (isSimpleType(type)) return (T)config.beanSession.convertToType(v, (Class<?>)type);
+			if (type == String.class) return (Optional<T>)asString();
+			if (type == String[].class) return (Optional<T>)asStringArray();
+			if (type == byte[].class) return (Optional<T>)asBytes();
+			if (type == int.class) return (Optional<T>)asInteger();
+			if (type == int.class || type == Integer.class) return (Optional<T>)asInteger();
+			if (type == long.class || type == Long.class) return (Optional<T>)asLong();
+			if (type == OMap.class) return (Optional<T>)asMap();
+			if (type == OList.class) return (Optional<T>)asList();
+			if (isEmpty()) return empty();
+			if (isSimpleType(type)) return ofNullable((T)config.beanSession.convertToType(v, (Class<?>)type));
 
 			if (parser instanceof JsonParser) {
 				char s1 = firstNonWhitespaceChar(v);
@@ -283,42 +218,13 @@ public class Entry {
 				else if (s1 != '[' && s1 != '{' && ! "null".equals(v))
 					v = '\'' + v + '\'';
 			}
-			return parser.parse(v, type, args);
+			return ofNullable(parser.parse(v, type, args));
 		} catch (ParseException e) {
 			throw new BeanRuntimeException(e, null, "Value could not be parsed.");
 		}
 	}
 
 	/**
-	 * Same as {@link #as(Type, Type...)} but specifies the parser to use to parse the entry.
-	 *
-	 * @param parser
-	 * 	The parser to use to parse the entry.
-	 * @param type
-	 * 	The object type to create.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * @param args
-	 * 	The type arguments of the class if it's a collection or map.
-	 * 	<br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
-	 * 	<br>Ignored if the main type is not a map or collection.
-	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
-	 */
-	public <T> Optional<T> as(Parser parser, Type type, Type...args) {
-		return ofNullable(to(parser, type, args));
-	}
-
-	/**
-	 * Returns this entry converted to the specified type.
-	 *
-	 * @param parser The parser to use to parse the entry value.
-	 * @param type The type to convert the value to.
-	 * @return This entry converted to the specified type, or <jk>null</jk> if the entry does not exist.
-	 */
-	public <T> T to(Parser parser, Class<T> type) {
-		return to(parser, (Type)type);
-	}
-
-	/**
 	 * Returns this entry converted to the specified type.
 	 *
 	 * @param parser The parser to use to parse the entry value.
@@ -326,7 +232,7 @@ public class Entry {
 	 * @return This entry converted to the specified type, or {@link Optional#empty()} if the entry does not exist.
 	 */
 	public <T> Optional<T> as(Parser parser, Class<T> type) {
-		return ofNullable(to(parser, type));
+		return as(parser, (Type)type);
 	}
 
 	/**
@@ -345,75 +251,29 @@ public class Entry {
 	 * @return This entry as a string, or {@link Optional#empty()} if the entry does not exist.
 	 */
 	public Optional<String> asString() {
- 		return ofNullable(toString());
+ 		return isPresent() ? of(config.varSession.resolve(value)) : empty();
 	}
 
- 	/**
+	/**
 	 * Returns this entry as a string array.
 	 *
 	 * <p>
 	 * If the value exists, splits the value on commas and returns the values as trimmed strings.
 	 *
-	 * @return This entry as a string array, or <jk>null</jk> if the entry does not exist.
+	 * @return This entry as a string array, or {@link Optional#empty()} if the entry does not exist.
 	 */
-	public String[] toStringArray() {
-		if (! isPresent()) return null;
+	public Optional<String[]> asStringArray() {
+		if (! isPresent()) return empty();
 		String v = toString();
 		char s1 = firstNonWhitespaceChar(v), s2 = lastNonWhitespaceChar(v);
 		if (s1 == '[' && s2 == ']' && config.parser instanceof JsonParser) {
 			try {
-				return config.parser.parse(v, String[].class);
+				return ofNullable(config.parser.parse(v, String[].class));
 			} catch (ParseException e) {
 				throw new BeanRuntimeException(e);
 			}
 		}
-		return split(v);
-	}
-
-	/**
-	 * Returns this entry as a string array.
-	 *
-	 * <p>
-	 * If the value exists, splits the value on commas and returns the values as trimmed strings.
-	 *
-	 * @return This entry as a string array, or {@link Optional#empty()} if the entry does not exist.
-	 */
-	public Optional<String[]> asStringArray() {
-		return ofNullable(toStringArray());
-	}
-
-	/**
-	 * Returns this entry as an integer.
-	 *
-	 * <p>
-	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga in base 2.
-	 * <br><js>"k"</js>, <js>"m"</js>, and <js>"g"</js> can be used to identify kilo, mega, and giga in base 10.
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		<code><js>"100K"</js> => 1024000</code>
-	 * 	<li>
-	 * 		<code><js>"100M"</js> => 104857600</code>
-	 * 	<li>
-	 * 		<code><js>"100k"</js> => 1000000</code>
-	 * 	<li>
-	 * 		<code><js>"100m"</js> => 100000000</code>
-	 * </ul>
-	 *
-	 * <p>
-	 * Uses {@link Integer#decode(String)} underneath, so any of the following integer formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
-	 */
-	public Integer toInteger() {
-		return isNotEmpty() ? parseIntWithSuffix(toString()) : null;
+		return of(split(v));
 	}
 
 	/**
@@ -447,20 +307,9 @@ public class Entry {
 	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
 	 */
 	public Optional<Integer> asInteger() {
-		return ofNullable(toInteger());
+		return isEmpty() ? empty() : of(parseIntWithSuffix(toString()));
 	}
 
-	/**
-	 * Returns this entry as a parsed boolean.
-	 *
-	 * <p>
-	 * Uses {@link Boolean#parseBoolean(String)} to parse value.
-	 *
-	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
-	 */
-	public Boolean toBoolean() {
-		return isNotEmpty() ? Boolean.parseBoolean(toString()) : null;
-	}
 
 	/**
 	 * Returns this entry as a parsed boolean.
@@ -471,41 +320,7 @@ public class Entry {
 	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
 	 */
 	public Optional<Boolean> asBoolean() {
-		return ofNullable(toBoolean());
-	}
-
-	/**
-	 * Returns this entry as a long.
-	 *
-	 * <p>
-	 * <js>"K"</js>, <js>"M"</js>, <js>"G"</js>, <js>"T"</js>, and <js>"P"</js> can be used to identify kilo, mega, giga, tera, and penta in base 2.
-	 * <br><js>"k"</js>, <js>"m"</js>, <js>"g"</js>, <js>"t"</js>, and <js>"p"</js> can be used to identify kilo, mega, giga, tera, and p in base 10.
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <ul class='spaced-list'>
-	 * 	<li>
-	 * 		<code><js>"100K"</js> => 1024000</code>
-	 * 	<li>
-	 * 		<code><js>"100M"</js> => 104857600</code>
-	 * 	<li>
-	 * 		<code><js>"100k"</js> => 1000000</code>
-	 * 	<li>
-	 * 		<code><js>"100m"</js> => 100000000</code>
-	 * </ul>
-	 *
-	 * <p>
-	 * Uses {@link Long#decode(String)} underneath, so any of the following integer formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
-	 */
-	public Long toLong() {
-		return isNotEmpty() ? parseLongWithSuffix(toString()) : null;
+		return isEmpty() ? empty() : of(Boolean.parseBoolean(toString()));
 	}
 
 	/**
@@ -539,26 +354,9 @@ public class Entry {
 	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
 	 */
 	public Optional<Long> asLong() {
-		return ofNullable(toLong());
+		return isEmpty() ? empty() : of(parseLongWithSuffix(toString()));
 	}
 
-	/**
-	 * Returns this entry as a double.
-	 *
-	 * <p>
-	 * Uses {@link Double#valueOf(String)} underneath, so any of the following number formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
-	 */
-	public Double toDouble() {
-		return isNotEmpty() ? Double.valueOf(toString()) : null;
-	}
 
 	/**
 	 * Returns this entry as a double.
@@ -575,26 +373,9 @@ public class Entry {
 	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
 	 */
 	public Optional<Double> asDouble() {
-		return ofNullable(toDouble());
+		return isEmpty() ? empty() : of(Double.valueOf(toString()));
 	}
 
-	/**
-	 * Returns this entry as a float.
-	 *
-	 * <p>
-	 * Uses {@link Float#valueOf(String)} underneath, so any of the following number formats are supported:
-	 * <ul>
-	 * 	<li><js>"0x..."</js>
-	 * 	<li><js>"0X..."</js>
-	 * 	<li><js>"#..."</js>
-	 * 	<li><js>"0..."</js>
-	 * </ul>
-	 *
-	 * @return The value, or <jk>null</jk> if the value does not exist or the value is empty.
-	 */
-	public Float toFloat() {
-		return isNotEmpty() ? Float.valueOf(toString()) : null;
-	}
 
 	/**
 	 * Returns this entry as a float.
@@ -611,61 +392,34 @@ public class Entry {
 	 * @return The value, or {@link Optional#empty()} if the value does not exist or the value is empty.
 	 */
 	public Optional<Float> asFloat() {
-		return ofNullable(toFloat());
+		return isEmpty() ? empty() : of(Float.valueOf(toString()));
 	}
 
+
 	/**
 	 * Returns this entry as a byte array.
 	 *
 	 * <p>
 	 * Byte arrays are stored as encoded strings, typically BASE64, but dependent on the {@link Config.Builder#binaryFormat(BinaryFormat)} setting.
 	 *
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
 	 */
-	public byte[] toBytes() {
-		if (isNull()) return null;
+	public Optional<byte[]> asBytes() {
+		if (isNull()) return empty();
 		String s = toString();
 		if (s.indexOf('\n') != -1) s = s.replaceAll("\n", "");
 		try {
 			if (config.binaryFormat == HEX)
-				return fromHex(s);
+				return of(fromHex(s));
 			if (config.binaryFormat == SPACED_HEX)
-				return fromSpacedHex(s);
-			return base64Decode(s);
+				return of(fromSpacedHex(s));
+			return of(base64Decode(s));
 		} catch (Exception e) {
 			throw new BeanRuntimeException(e, null, "Value could not be converted to a byte array.");
 		}
 	}
 
 	/**
-	 * Returns this entry as a byte array.
-	 *
-	 * <p>
-	 * Byte arrays are stored as encoded strings, typically BASE64, but dependent on the {@link Config.Builder#binaryFormat(BinaryFormat)} setting.
-	 *
-	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
-	 */
-	public Optional<byte[]> asBytes() {
-		return ofNullable(toBytes());
-	}
-
-	/**
-	 * Returns this entry as a parsed map.
-	 *
-	 * <p>
-	 * Uses the parser registered on the {@link Config} to parse the entry.
-	 *
-	 * <p>
-	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
-	 *
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 * @throws ParseException If value could not be parsed.
-	 */
-	public OMap toMap() throws ParseException {
-		return toMap(null);
-	}
-
-	/**
 	 * Returns this entry as a parsed map.
 	 *
 	 * <p>
@@ -678,7 +432,7 @@ public class Entry {
 	 * @throws ParseException If value could not be parsed.
 	 */
 	public Optional<OMap> asMap() throws ParseException {
-		return ofNullable(toMap());
+		return asMap(config.parser);
 	}
 
 	/**
@@ -687,12 +441,12 @@ public class Entry {
 	 * <p>
 	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
 	 *
-	 * @param parser The parser to use to parse the value, or <jk>null</jk> to use the parser defined on the config.
+	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
 	 * @return The value, or <jk>null</jk> if the section or key does not exist.
 	 * @throws ParseException If value could not be parsed.
 	 */
-	public OMap toMap(Parser parser) throws ParseException {
-		if (isNull()) return null;
+	public Optional<OMap> asMap(Parser parser) throws ParseException {
+		if (isNull()) return empty();
 		if (parser == null) parser = config.parser;
 		String s = toString();
 		if (parser instanceof JsonParser) {
@@ -700,37 +454,7 @@ public class Entry {
 			if (s1 != '{' && ! "null".equals(s))
 				s = '{' + s + '}';
 		}
-		return OMap.ofText(s, parser);
-	}
-
-	/**
-	 * Returns this entry as a parsed map.
-	 *
-	 * <p>
-	 * If the parser is a JSON parser, the starting/trailing <js>"{"</js>/<js>"}"</js> in the value are optional.
-	 *
-	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 * @throws ParseException If value could not be parsed.
-	 */
-	public Optional<OMap> asMap(Parser parser) throws ParseException {
-		return ofNullable(toMap(parser));
-	}
-
-	/**
-	 * Returns this entry as a parsed list.
-	 *
-	 * <p>
-	 * Uses the parser registered on the {@link Config} to parse the entry.
-	 *
-	 * <p>
-	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
-	 *
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
-	 * @throws ParseException If value could not be parsed.
-	 */
-	public OList toList() throws ParseException {
-		return toList(config.parser);
+		return of(OMap.ofText(s, parser));
 	}
 
 	/**
@@ -746,9 +470,10 @@ public class Entry {
 	 * @throws ParseException If value could not be parsed.
 	 */
 	public Optional<OList> asList() throws ParseException {
-		return ofNullable(toList());
+		return asList(config.parser);
 	}
 
+
 	/**
 	 * Returns this entry as a parsed list.
 	 *
@@ -756,11 +481,11 @@ public class Entry {
 	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
 	 *
 	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
-	 * @return The value, or <jk>null</jk> if the section or key does not exist.
+	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
 	 * @throws ParseException If value could not be parsed.
 	 */
-	public OList toList(Parser parser) throws ParseException {
-		if (isNull()) return null;
+	public Optional<OList> asList(Parser parser) throws ParseException {
+		if (isNull()) return empty();
 		if (parser == null) parser = config.parser;
 		String s = toString();
 		if (parser instanceof JsonParser) {
@@ -768,21 +493,7 @@ public class Entry {
 			if (s1 != '[' && ! "null".equals(s))
 				s = '[' + s + ']';
 		}
-		return OList.ofText(s, parser);
-	}
-
-	/**
-	 * Returns this entry as a parsed list.
-	 *
-	 * <p>
-	 * If the parser is a JSON parser, the starting/trailing <js>"["</js>/<js>"]"</js> in the value are optional.
-	 *
-	 * @param parser The parser to use to parse the value, or {@link Optional#empty()} to use the parser defined on the config.
-	 * @return The value, or {@link Optional#empty()} if the section or key does not exist.
-	 * @throws ParseException If value could not be parsed.
-	 */
-	public Optional<OList> asList(Parser parser) throws ParseException {
-		return ofNullable(toList(parser));
+		return of(OList.ofText(s, parser));
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Section.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Section.java
index aecbd05..88907d9 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Section.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Section.java
@@ -57,17 +57,6 @@ public class Section {
 	}
 
 	/**
-	 * Shortcut for calling <code>toBean(sectionName, c, <jk>false</jk>)</code>.
-	 *
-	 * @param c The bean class to create.
-	 * @return A new bean instance, or <jk>null</jk> if this section does not exist.
-	 * @throws ParseException Malformed input encountered.
-	 */
-	public <T> T toBean(Class<T> c) throws ParseException {
-		return toBean(c, false);
-	}
-
-	/**
 	 * Shortcut for calling <code>asBean(sectionName, c, <jk>false</jk>)</code>.
 	 *
 	 * @param c The bean class to create.
@@ -75,7 +64,7 @@ public class Section {
 	 * @throws ParseException Malformed input encountered.
 	 */
 	public <T> Optional<T> asBean(Class<T> c) throws ParseException {
-		return ofNullable(toBean(c));
+		return asBean(c, false);
 	}
 
 	/**
@@ -106,7 +95,7 @@ public class Section {
 	 * <h5 class='figure'>Example usage</h5>
 	 * <p class='bjava'>
 	 * 	Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-	 * 	Address <jv>address</jv> = <jv>config</jv>.getSection(<js>"MySection"</js>).toBean(Address.<jk>class</jk>);
+	 * 	Address <jv>address</jv> = <jv>config</jv>.getSection(<js>"MySection"</js>).asBean(Address.<jk>class</jk>).orElse(<jk>null</jk>);
 	 * </p>
 	 *
 	 * @param c The bean class to create.
@@ -116,9 +105,9 @@ public class Section {
 	 * @return A new bean instance, or <jk>null</jk> if this section doesn't exist.
 	 * @throws ParseException Unknown property was encountered in section.
 	 */
-	public <T> T toBean(Class<T> c, boolean ignoreUnknownProperties) throws ParseException {
+	public <T> Optional<T> asBean(Class<T> c, boolean ignoreUnknownProperties) throws ParseException {
 		assertArgNotNull("c", c);
-		if (! isPresent()) return null;
+		if (! isPresent()) return empty();
 
 		Set<String> keys = configMap.getKeys(name);
 
@@ -133,74 +122,23 @@ public class Section {
 			}
 		}
 
-		return bm.getBean();
-	}
-
-	/**
-	 * Converts this config file section to the specified bean instance.
-	 *
-	 * <p>
-	 * Key/value pairs in the config file section get copied as bean property values to the specified bean class.
-	 *
-	 * <h5 class='figure'>Example config file</h5>
-	 * <p class='bini'>
-	 * 	<cs>[MyAddress]</cs>
-	 * 	<ck>name</ck> = <cv>John Smith</cv>
-	 * 	<ck>street</ck> = <cv>123 Main Street</cv>
-	 * 	<ck>city</ck> = <cv>Anywhere</cv>
-	 * 	<ck>state</ck> = <cv>NY</cv>
-	 * 	<ck>zip</ck> = <cv>12345</cv>
-	 * </p>
-	 *
-	 * <h5 class='figure'>Example bean</h5>
-	 * <p class='bjava'>
-	 * 	<jk>public class</jk> Address {
-	 * 		<jk>public</jk> String <jf>name</jf>, <jf>street</jf>, <jf>city</jf>;
-	 * 		<jk>public</jk> StateEnum <jf>state</jf>;
-	 * 		<jk>public int</jk> <jf>zip</jf>;
-	 * 	}
-	 * </p>
-	 *
-	 * <h5 class='figure'>Example usage</h5>
-	 * <p class='bjava'>
-	 * 	Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-	 * 	Address <jv>address</jv> = <jv>config</jv>.getSection(<js>"MySection"</js>).asBean(Address.<jk>class</jk>).orElse(<jk>null</jk>);
-	 * </p>
-	 *
-	 * @param c The bean class to create.
-	 * @param ignoreUnknownProperties
-	 * 	If <jk>false</jk>, throws a {@link ParseException} if the section contains an entry that isn't a bean property
-	 * 	name.
-	 * @return A new bean instance, or <jk>null</jk> if this section doesn't exist.
-	 * @throws ParseException Unknown property was encountered in section.
-	 */
-	public <T> Optional<T> asBean(Class<T> c, boolean ignoreUnknownProperties) throws ParseException {
-		return ofNullable(toBean(c, ignoreUnknownProperties));
+		return of(bm.getBean());
 	}
 
 	/**
 	 * Returns this section as a map.
 	 *
-	 * @return A new {@link OMap}, or <jk>null</jk> if this section doesn't exist.
+	 * @return A new {@link OMap}, or {@link Optional#empty()} if this section doesn't exist.
 	 */
-	public OMap toMap() {
-		if (! isPresent()) return null;
+	public Optional<OMap> asMap() {
+		if (! isPresent()) return empty();
 
 		Set<String> keys = configMap.getKeys(name);
 
 		OMap om = new OMap();
 		for (String k : keys)
 			om.put(k, config.get(name + '/' + k).as(Object.class).orElse(null));
-		return om;
-	}
-
-	/**
-	 * Returns this section as a map.
-	 *
-	 * @return A new {@link OMap}, or {@link Optional#empty()} if this section doesn't exist.
-	 */
-	public Optional<OMap> asMap() {
-		return ofNullable(toMap());
+		return of(om);
 	}
 
 	/**
@@ -246,7 +184,7 @@ public class Section {
 	 * <p class='bjava'>
 	 * 	Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
 	 *
-	 * 	MyConfigInterface <jv>ci</jv> = <jv>config</jv>.get(<js>"MySection"</js>).toInterface(MyConfigInterface.<jk>class</jk>);
+	 * 	MyConfigInterface <jv>ci</jv> = <jv>config</jv>.get(<js>"MySection"</js>).asInterface(MyConfigInterface.<jk>class</jk>).orElse(<jk>null</jk>);
 	 *
 	 * 	<jk>int</jk> <jv>myInt</jv> = <jv>ci</jv>.getInt();
 	 *
@@ -263,7 +201,7 @@ public class Section {
 	 * @return The proxy interface.
 	 */
 	@SuppressWarnings("unchecked")
-	public <T> T toInterface(final Class<T> c) {
+	public <T> Optional<T> asInterface(final Class<T> c) {
 		assertArgNotNull("c", c);
 
 		if (! c.isInterface())
@@ -277,7 +215,7 @@ public class Section {
 				for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
 					Method rm = pd.getReadMethod(), wm = pd.getWriteMethod();
 					if (method.equals(rm))
-						return config.get(name + '/' + pd.getName()).to(rm.getGenericReturnType());
+						return config.get(name + '/' + pd.getName()).as(rm.getGenericReturnType()).orElse(null);
 					if (method.equals(wm))
 						return config.set(name + '/' + pd.getName(), args[0]);
 				}
@@ -285,70 +223,7 @@ public class Section {
 			}
 		};
 
-		return (T)Proxy.newProxyInstance(c.getClassLoader(), new Class[] { c }, h);
-	}
-
-	/**
-	 * Wraps this section inside a Java interface so that values in the section can be read and
-	 * write using getters and setters.
-	 *
-	 * <h5 class='figure'>Example config file</h5>
-	 * <p class='bini'>
-	 * 	<cs>[MySection]</cs>
-	 * 	<ck>string</ck> = <cv>foo</cv>
-	 * 	<ck>int</ck> = <cv>123</cv>
-	 * 	<ck>enum</ck> = <cv>ONE</cv>
-	 * 	<ck>bean</ck> = <cv>{foo:'bar',baz:123}</cv>
-	 * 	<ck>int3dArray</ck> = <cv>[[[123,null],null],null]</cv>
-	 * 	<ck>bean1d3dListMap</ck> = <cv>{key:[[[[{foo:'bar',baz:123}]]]]}</cv>
-	 * </p>
-	 *
-	 * <h5 class='figure'>Example interface</h5>
-	 * <p class='bjava'>
-	 * 	<jk>public interface</jk> MyConfigInterface {
-	 *
-	 * 		String getString();
-	 * 		<jk>void</jk> setString(String <jv>value</jv>);
-	 *
-	 * 		<jk>int</jk> getInt();
-	 * 		<jk>void</jk> setInt(<jk>int</jk> <jv>value</jv>);
-	 *
-	 * 		MyEnum getEnum();
-	 * 		<jk>void</jk> setEnum(MyEnum <jv>value</jv>);
-	 *
-	 * 		MyBean getBean();
-	 * 		<jk>void</jk> setBean(MyBean <jv>value</jv>);
-	 *
-	 * 		<jk>int</jk>[][][] getInt3dArray();
-	 * 		<jk>void</jk> setInt3dArray(<jk>int</jk>[][][] <jv>value</jv>);
-	 *
-	 * 		Map&lt;String,List&lt;MyBean[][][]&gt;&gt; getBean1d3dListMap();
-	 * 		<jk>void</jk> setBean1d3dListMap(Map&lt;String,List&lt;MyBean[][][]&gt;&gt; <jv>value</jv>);
-	 * 	}
-	 * </p>
-	 *
-	 * <h5 class='figure'>Example usage</h5>
-	 * <p class='bjava'>
-	 * 	Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-	 *
-	 * 	MyConfigInterface <jv>ci</jv> = <jv>config</jv>.get(<js>"MySection"</js>).asInterface(MyConfigInterface.<jk>class</jk>).orElse(<jk>null</jk>);
-	 *
-	 * 	<jk>int</jk> <jv>myInt</jv> = <jv>ci</jv>.getInt();
-	 *
-	 * 	<jv>ci</jv>.setBean(<jk>new</jk> MyBean());
-	 *
-	 * 	<jv>ci</jv>.save();
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li>Calls to setters when the configuration is read-only will cause {@link UnsupportedOperationException} to be thrown.
-	 * </ul>
-	 *
-	 * @param c The proxy interface class.
-	 * @return The proxy interface.
-	 */
-	public <T> Optional<T> asInterface(final Class<T> c) {
-		return ofNullable(toInterface(c));
+		return ofNullable((T)Proxy.newProxyInstance(c.getClassLoader(), new Class[] { c }, h));
 	}
 
 	/**
diff --git a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigTest.java b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigTest.java
index f6398f7..2165ad8 100644
--- a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigTest.java
+++ b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/ConfigTest.java
@@ -40,7 +40,7 @@ public class ConfigTest extends RestTestcase {
 
 		Config cf = Config.create().memStore().build().load(m);
 
-		assertObject(cf.getSection("Test").toMap()).asJson().is("{int1:'1',int2:'[1,2,3]',int3:'1',int4:'1',int5:'-1',boolean1:'true',boolean2:'[true,true]',testManifestEntry:'test-value'}");
+		assertObject(cf.getSection("Test").asMap().get()).asJson().is("{int1:'1',int2:'[1,2,3]',int3:'1',int4:'1',int5:'-1',boolean1:'true',boolean2:'[true,true]',testManifestEntry:'test-value'}");
 
 		assertEquals("'1'", c.get(URL + "/Test%2Fint1/" + getName(String.class)).run().getBody().asString());
 		assertEquals("'[1,2,3]'", c.get(URL + "/Test%2Fint2/" + getName(String.class)).run().getBody().asString());
diff --git a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java
index c691c69..75d79d2 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigInterfaceTest.java
@@ -31,7 +31,7 @@ public class ConfigInterfaceTest {
 
 	public ConfigInterfaceTest() throws Exception {
 		cf = Config.create().serializer(SimpleJsonSerializer.DEFAULT.copy().addBeanTypes().addRootType().build()).build();
-		proxy = cf.getSection("A").toInterface(ConfigInterface.class);
+		proxy = cf.getSection("A").asInterface(ConfigInterface.class).orElse(null);
 	}
 
 
diff --git a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java
index 2270ef5..4620fbe 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/config/ConfigTest.java
@@ -428,7 +428,7 @@ public class ConfigTest {
 		assertObject(c.get("a1").as(byte[].class)).asJson().is("[102,111,111]");
 		assertObject(c.get("a2").as(byte[].class)).asJson().is("[102,111,111]");
 		assertObject(c.get("a3").as(byte[].class)).asJson().is("[]");
-		assertNull(null, c.get("a4").to(byte[].class));
+		assertFalse(c.get("a4").as(byte[].class).isPresent());
 	}
 
 	//====================================================================================================
@@ -447,6 +447,7 @@ public class ConfigTest {
 	//====================================================================================================
 	//	public <T> T getObject(String key, Type type, Type...args) throws ParseException {
 	//====================================================================================================
+	@SuppressWarnings("unchecked")
 	@Test
 	public void getObject1() throws Exception {
 		Config c = init(
@@ -458,24 +459,24 @@ public class ConfigTest {
 			"\t}"
 			);
 
-		Map<String,Integer> a1 = c.get("a1").to(Map.class, String.class, Integer.class);
+		Map<String,Integer> a1 = (Map<String,Integer>) c.get("a1").as(Map.class, String.class, Integer.class).get();
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		List<Map<String,Integer>> a2a = c.get("a2").to(List.class, Map.class, String.class, Integer.class);
+		List<Map<String,Integer>> a2a = (List<Map<String,Integer>>) c.get("a2").as(List.class, Map.class, String.class, Integer.class).get();
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(a2a.get(0).keySet().iterator().next()).isType(String.class);
 		assertObject(a2a.get(0).values().iterator().next()).isType(Integer.class);
 
-		List<ABean> a2b = c.get("a2").to(List.class, ABean.class);
+		List<ABean> a2b = (List<ABean>) c.get("a2").as(List.class, ABean.class).get();
 		assertObject(a2b).asJson().is("[{foo:'123'}]");
 		assertObject(a2b.get(0)).isType(ABean.class);
 
-		Map<String,Integer> a3 = c.get("a3").to(Map.class, String.class, Integer.class);
+		Map<String,Integer> a3 = (Map<String,Integer>) c.get("a3").as(Map.class, String.class, Integer.class).orElse(null);
 		assertNull(a3);
 
-		Map<String,Integer> a4a = c.get("a4").to(Map.class, String.class, Integer.class);
+		Map<String,Integer> a4a = (Map<String,Integer>) c.get("a4").as(Map.class, String.class, Integer.class).get();
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
@@ -488,6 +489,7 @@ public class ConfigTest {
 	//====================================================================================================
 	//	public <T> T getObject(String key, Parser parser, Type type, Type...args) throws ParseException {
 	//====================================================================================================
+	@SuppressWarnings("unchecked")
 	@Test
 	public void getObject2() throws Exception {
 		Config c = init(
@@ -499,24 +501,24 @@ public class ConfigTest {
 			"\t)"
 			);
 
-		Map<String,Integer> a1 = c.get("a1").to(UonParser.DEFAULT, Map.class, String.class, Integer.class);
+		Map<String,Integer> a1 = (Map<String,Integer>) c.get("a1").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).get();
 		assertObject(a1).asJson().is("{foo:123}");
 		assertObject(a1.keySet().iterator().next()).isType(String.class);
 		assertObject(a1.values().iterator().next()).isType(Integer.class);
 
-		List<Map<String,Integer>> a2a = c.get("a2").to(UonParser.DEFAULT, List.class, Map.class, String.class, Integer.class);
+		List<Map<String,Integer>> a2a = (List<Map<String,Integer>>) c.get("a2").as(UonParser.DEFAULT, List.class, Map.class, String.class, Integer.class).get();
 		assertObject(a2a).asJson().is("[{foo:123}]");
 		assertObject(a2a.get(0).keySet().iterator().next()).isType(String.class);
 		assertObject(a2a.get(0).values().iterator().next()).isType(Integer.class);
 
-		List<ABean> a2b = c.get("a2").to(UonParser.DEFAULT, List.class, ABean.class);
+		List<ABean> a2b = (List<ABean>) c.get("a2").as(UonParser.DEFAULT, List.class, ABean.class).get();
 		assertObject(a2b).asJson().is("[{foo:'123'}]");
 		assertObject(a2b.get(0)).isType(ABean.class);
 
-		Map<String,Integer> a3 = c.get("a3").to(UonParser.DEFAULT, Map.class, String.class, Integer.class);
+		Map<String,Integer> a3 = (Map<String,Integer>) c.get("a3").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).orElse(null);
 		assertNull(a3);
 
-		Map<String,Integer> a4a = c.get("a4").to(UonParser.DEFAULT, Map.class, String.class, Integer.class);
+		Map<String,Integer> a4a = (Map<String,Integer>) c.get("a4").as(UonParser.DEFAULT, Map.class, String.class, Integer.class).get();
 		assertObject(a4a).asJson().is("{foo:123}");
 		assertObject(a4a.keySet().iterator().next()).isType(String.class);
 		assertObject(a4a.values().iterator().next()).isType(Integer.class);
@@ -838,24 +840,24 @@ public class ConfigTest {
 		ABean a = null;
 		BBean b = null;
 
-		a = c.getSection("").toBean(ABean.class);
+		a = c.getSection("").asBean(ABean.class).get();
 		assertObject(a).asJson().is("{foo:'qux'}");
-		a = c.getSection("").toBean(ABean.class);
+		a = c.getSection("").asBean(ABean.class).get();
 		assertObject(a).asJson().is("{foo:'qux'}");
-		a = c.getSection(null).toBean(ABean.class);
+		a = c.getSection(null).asBean(ABean.class).get();
 		assertObject(a).asJson().is("{foo:'qux'}");
-		a = c.getSection("S").toBean(ABean.class);
+		a = c.getSection("S").asBean(ABean.class).get();
 		assertObject(a).asJson().is("{foo:'baz'}");
 
-		b = c.getSection("").toBean(BBean.class);
+		b = c.getSection("").asBean(BBean.class).get();
 		assertObject(b).asJson().is("{foo:'qux'}");
-		b = c.getSection("").toBean(BBean.class);
+		b = c.getSection("").asBean(BBean.class).get();
 		assertObject(b).asJson().is("{foo:'qux'}");
-		b = c.getSection("S").toBean(BBean.class);
+		b = c.getSection("S").asBean(BBean.class).get();
 		assertObject(b).asJson().is("{foo:'baz'}");
 
-		assertThrown(()->c.getSection("T").toBean(ABean.class)).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
-		assertThrown(()->c.getSection("T").toBean(BBean.class)).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
+		assertThrown(()->c.getSection("T").asBean(ABean.class).get()).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
+		assertThrown(()->c.getSection("T").asBean(BBean.class).get()).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
 	}
 
 	//====================================================================================================
@@ -868,13 +870,13 @@ public class ConfigTest {
 		ABean a = null;
 		BBean b = null;
 
-		a = c.getSection("T").toBean(ABean.class, true);
+		a = c.getSection("T").asBean(ABean.class, true).get();
 		assertObject(a).asJson().is("{foo:'qux'}");
-		b = c.getSection("T").toBean(BBean.class, true);
+		b = c.getSection("T").asBean(BBean.class, true).get();
 		assertObject(b).asJson().is("{foo:'qux'}");
 
-		assertThrown(()->c.getSection("T").toBean(ABean.class, false)).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
-		assertThrown(()->c.getSection("T").toBean(BBean.class, false)).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
+		assertThrown(()->c.getSection("T").asBean(ABean.class, false).get()).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
+		assertThrown(()->c.getSection("T").asBean(BBean.class, false).get()).message().is("Unknown property 'bar' encountered in configuration section 'T'.");
 	}
 
 	//====================================================================================================
@@ -884,12 +886,12 @@ public class ConfigTest {
 	public void getSectionAsMap() throws Exception {
 		Config c = init("a=1", "[S]", "b=2", "[T]");
 
-		assertObject(c.getSection("").toMap()).asJson().is("{a:'1'}");
-		assertObject(c.getSection("").toMap()).asJson().is("{a:'1'}");
-		assertObject(c.getSection(null).toMap()).asJson().is("{a:'1'}");
-		assertObject(c.getSection("S").toMap()).asJson().is("{b:'2'}");
-		assertObject(c.getSection("T").toMap()).asJson().is("{}");
-		assertNull(c.getSection("U").toMap());
+		assertObject(c.getSection("").asMap().get()).asJson().is("{a:'1'}");
+		assertObject(c.getSection("").asMap().get()).asJson().is("{a:'1'}");
+		assertObject(c.getSection(null).asMap().get()).asJson().is("{a:'1'}");
+		assertObject(c.getSection("S").asMap().get()).asJson().is("{b:'2'}");
+		assertObject(c.getSection("T").asMap().get()).asJson().is("{}");
+		assertFalse(c.getSection("U").asMap().isPresent());
 	}
 
 	//====================================================================================================
@@ -900,22 +902,22 @@ public class ConfigTest {
 		Config c = init("foo=qux", "[S]", "foo=baz", "[T]", "foo=qux", "bar=qux");
 		AInterface a = null;
 
-		a = c.getSection("").toInterface(AInterface.class);
+		a = c.getSection("").asInterface(AInterface.class).get();
 		assertEquals("qux", a.getFoo());
 
-		a = c.getSection("").toInterface(AInterface.class);
+		a = c.getSection("").asInterface(AInterface.class).get();
 		assertEquals("qux", a.getFoo());
 
-		a = c.getSection(null).toInterface(AInterface.class);
+		a = c.getSection(null).asInterface(AInterface.class).get();
 		assertEquals("qux", a.getFoo());
 
-		a = c.getSection("S").toInterface(AInterface.class);
+		a = c.getSection("S").asInterface(AInterface.class).get();
 		assertEquals("baz", a.getFoo());
 
-		a = c.getSection("T").toInterface(AInterface.class);
+		a = c.getSection("T").asInterface(AInterface.class).get();
 		assertEquals("qux", a.getFoo());
 
-		assertThrown(()->c.getSection("T").toInterface(ABean.class)).message().is("Class 'org.apache.juneau.config.ConfigTest$ABean' passed to toInterface() is not an interface.");
+		assertThrown(()->c.getSection("T").asInterface(ABean.class).get()).message().is("Class 'org.apache.juneau.config.ConfigTest$ABean' passed to toInterface() is not an interface.");
 	}
 
 	public static interface AInterface {
@@ -1026,17 +1028,17 @@ public class ConfigTest {
 			"[section1]", "key1 = 2", "key2 = false", "key3 = [4,5,6]", "key4 = http://bar"
 		);
 
-		assertInteger(cf.get("key1").toInteger()).is(1);
-		assertBoolean(cf.get("key2").toBoolean()).isTrue();
-		assertInteger(cf.get("key3").to(int[].class)[2]).is(3);
+		assertInteger(cf.get("key1").asInteger().get()).is(1);
+		assertBoolean(cf.get("key2").asBoolean().get()).isTrue();
+		assertInteger(cf.get("key3").as(int[].class).get()[2]).is(3);
 		assertInteger(cf.get("xkey3").as(int[].class).orElse(new int[]{4,5,6})[2]).is(6);
 		assertInteger(cf.get("X/key3").as(int[].class).orElse(new int[]{4,5,6})[2]).is(6);
-		assertEquals(new URL("http://foo").toString(), cf.get("key4").to(URL.class).toString());
+		assertEquals(new URL("http://foo").toString(), cf.get("key4").as(URL.class).get().toString());
 
-		assertInteger(cf.get("section1/key1").toInteger()).is(2);
-		assertBoolean(cf.get("section1/key2").toBoolean()).isFalse();
-		assertInteger(cf.get("section1/key3").to(int[].class)[2]).is(6);
-		assertEquals(new URL("http://bar").toString(), cf.get("section1/key4").to(URL.class).toString());
+		assertInteger(cf.get("section1/key1").asInteger().get()).is(2);
+		assertBoolean(cf.get("section1/key2").asBoolean().get()).isFalse();
+		assertInteger(cf.get("section1/key3").as(int[].class).get()[2]).is(6);
+		assertEquals(new URL("http://bar").toString(), cf.get("section1/key4").as(URL.class).get().toString());
 
 		cf = init(
 			"# Default section",
@@ -1054,15 +1056,15 @@ public class ConfigTest {
 
 		cf.commit();
 
-		assertInteger(cf.get("key1").toInteger()).is(1);
-		assertBoolean(cf.get("key2").toBoolean()).isTrue();
-		assertInteger(cf.get("key3").to(int[].class)[2]).is(3);
-		assertEquals(new URL("http://foo").toString(), cf.get("key4").to(URL.class).toString());
+		assertInteger(cf.get("key1").asInteger().get()).is(1);
+		assertBoolean(cf.get("key2").asBoolean().get()).isTrue();
+		assertInteger(cf.get("key3").as(int[].class).get()[2]).is(3);
+		assertEquals(new URL("http://foo").toString(), cf.get("key4").as(URL.class).get().toString());
 
-		assertInteger(cf.get("section1/key1").toInteger()).is(2);
-		assertBoolean(cf.get("section1/key2").toBoolean()).isFalse();
-		assertInteger(cf.get("section1/key3").to(int[].class)[2]).is(6);
-		assertEquals(new URL("http://bar").toString(), cf.get("section1/key4").to(URL.class).toString());
+		assertInteger(cf.get("section1/key1").asInteger().get()).is(2);
+		assertBoolean(cf.get("section1/key2").asBoolean().get()).isFalse();
+		assertInteger(cf.get("section1/key3").as(int[].class).get()[2]).is(6);
+		assertEquals(new URL("http://bar").toString(), cf.get("section1/key4").as(URL.class).get().toString());
 	}
 
 	//====================================================================================================
@@ -1073,11 +1075,11 @@ public class ConfigTest {
 		Config cf = init(
 			"key1 = MINUTES"
 		);
-		assertEquals(TimeUnit.MINUTES, cf.get("key1").to(TimeUnit.class));
+		assertEquals(TimeUnit.MINUTES, cf.get("key1").as(TimeUnit.class).get());
 
 		cf.commit();
 
-		assertEquals(TimeUnit.MINUTES, cf.get("key1").to(TimeUnit.class));
+		assertEquals(TimeUnit.MINUTES, cf.get("key1").as(TimeUnit.class).get());
 	}
 
 	//====================================================================================================
@@ -1194,7 +1196,7 @@ public class ConfigTest {
 
 		cf.set("foo", "bar".getBytes("UTF-8"));
 		assertEquals("626172", cf.get("foo").getValue());
-		assertObject(cf.get("foo").toBytes()).asJson().is("[98,97,114]");
+		assertObject(cf.get("foo").asBytes().get()).asJson().is("[98,97,114]");
 	}
 
 	//====================================================================================================
@@ -1206,7 +1208,7 @@ public class ConfigTest {
 
 		cf.set("foo", "bar".getBytes("UTF-8"));
 		assertEquals("62 61 72", cf.get("foo").getValue());
-		assertObject(cf.get("foo").toBytes()).asJson().is("[98,97,114]");
+		assertObject(cf.get("foo").asBytes().get()).asJson().is("[98,97,114]");
 	}
 
 	//====================================================================================================
@@ -1238,10 +1240,10 @@ public class ConfigTest {
 			"f3 = 1 M",
 			"f4 = 1 K"
 		);
-		assertInteger(cf.get("s1/f1").toInteger()).is(1048576);
-		assertInteger(cf.get("s1/f2").toInteger()).is(1024);
-		assertInteger(cf.get("s1/f3").toInteger()).is(1048576);
-		assertInteger(cf.get("s1/f4").toInteger()).is(1024);
+		assertInteger(cf.get("s1/f1").asInteger().get()).is(1048576);
+		assertInteger(cf.get("s1/f2").asInteger().get()).is(1024);
+		assertInteger(cf.get("s1/f3").asInteger().get()).is(1048576);
+		assertInteger(cf.get("s1/f4").asInteger().get()).is(1024);
 	}
 
 	//====================================================================================================
@@ -1362,20 +1364,20 @@ public class ConfigTest {
 	@Test
 	public void testGetObjectArray() throws Exception {
 		Config cf = init("[A]", "a1=[1,2,3]");
-		assertObject(cf.get("A/a1").to(Integer[].class)).asJson().is("[1,2,3]");
+		assertObject(cf.get("A/a1").as(Integer[].class).get()).asJson().is("[1,2,3]");
 		assertObject(cf.get("A/a2").as(Integer[].class).orElse(new Integer[]{4,5,6})).asJson().is("[4,5,6]");
 		assertObject(cf.get("B/a1").as(Integer[].class).orElse(new Integer[]{7,8,9})).asJson().is("[7,8,9]");
-		assertNull(cf.get("B/a1").to(Integer[].class));
+		assertFalse(cf.get("B/a1").as(Integer[].class).isPresent());
 
 		cf = init("[A]", "a1 = [1 ,\n\t2 ,\n\t3] ");
-		assertObject(cf.get("A/a1").to(Integer[].class)).asJson().is("[1,2,3]");
+		assertObject(cf.get("A/a1").as(Integer[].class).get()).asJson().is("[1,2,3]");
 
 		// We cannot cast primitive arrays to Object[], so the following throws exceptions.
-		assertObject(cf.get("A/a1").to(int[].class)).asJson().is("[1,2,3]");
-		assertEquals("int", cf.get("A/a1").to(int[].class).getClass().getComponentType().getSimpleName());
-		assertNull(cf.get("B/a1").to(int[].class));
+		assertObject(cf.get("A/a1").as(int[].class).get()).asJson().is("[1,2,3]");
+		assertEquals("int", cf.get("A/a1").as(int[].class).get().getClass().getComponentType().getSimpleName());
+		assertFalse(cf.get("B/a1").as(int[].class).isPresent());
 		assertEquals("int", cf.get("B/a1").as(int[].class).orElse(new int[0]).getClass().getComponentType().getSimpleName());
-		assertNull(cf.get("A/a2").to(int[].class));
+		assertFalse(cf.get("A/a2").as(int[].class).isPresent());
 		assertEquals("int", cf.get("A/a2").as(int[].class).orElse(new int[0]).getClass().getComponentType().getSimpleName());
 
 		assertObject(cf.get("A/a1").as(int[].class).orElse(new int[]{4})).asJson().is("[1,2,3]");
@@ -1400,13 +1402,13 @@ public class ConfigTest {
 	@Test
 	public void testGetStringArray() throws Exception {
 		Config cf = init("[A]", "a1=1,2,3");
-		assertObject(cf.get("A/a1").toStringArray()).asJson().is("['1','2','3']");
+		assertObject(cf.get("A/a1").asStringArray().get()).asJson().is("['1','2','3']");
 		assertObject(cf.get("A/a2").asStringArray().orElse(new String[]{"4","5","6"})).asJson().is("['4','5','6']");
 		assertObject(cf.get("B/a1").asStringArray().orElse(new String[]{"7","8","9"})).asJson().is("['7','8','9']");
-		assertObject(cf.get("B/a1").toStringArray()).isNull();
+		assertObject(cf.get("B/a1").asStringArray().orElse(null)).isNull();
 
 		cf = init("[A]", "a1 = 1 ,\n\t2 ,\n\t3 ");
-		assertObject(cf.get("A/a1").toStringArray()).asJson().is("['1','2','3']");
+		assertObject(cf.get("A/a1").asStringArray().get()).asJson().is("['1','2','3']");
 
 		System.setProperty("X", "4,5,6");
 		cf = init(null, "x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,$S{X}}", "[A]", "a1=1,2,3");
@@ -1424,15 +1426,15 @@ public class ConfigTest {
 	public void testGetSectionMap() throws Exception {
 		Config cf = init("[A]", "a1=1", "", "[D]", "d1=$C{A/a1}","d2=$S{X}");
 
-		assertObject(cf.getSection("A").toMap()).asJson().is("{a1:'1'}");
-		assertNull(cf.getSection("B").toMap());
-		assertObject(cf.getSection("C").toMap()).asJson().is("null");
+		assertObject(cf.getSection("A").asMap().get()).asJson().is("{a1:'1'}");
+		assertFalse(cf.getSection("B").asMap().isPresent());
+		assertObject(cf.getSection("C").asMap().orElse(null)).asJson().is("null");
 
-		OMap m = cf.getSection("A").toMap();
+		OMap m = cf.getSection("A").asMap().get();
 		assertObject(m).asJson().is("{a1:'1'}");
 
 		System.setProperty("X", "x");
-		m = cf.getSection("D").toMap();
+		m = cf.getSection("D").asMap().get();
 		assertObject(m).asJson().is("{d1:'1',d2:'x'}");
 		System.clearProperty("X");
 	}