mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
Second cut at ConfigBeanFactory
This version predates ConfigMemorySize and java.time.Duration support.
This commit is contained in:
parent
d4a0255520
commit
f1f198595a
@ -1,80 +0,0 @@
|
||||
package com.typesafe.config;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.typesafe.config.Config;
|
||||
import com.typesafe.config.ConfigException;
|
||||
|
||||
/**
|
||||
* Sent as pull request to config project.
|
||||
* https://github.com/typesafehub/config/pull/107
|
||||
*/
|
||||
public class BeanFactory {
|
||||
|
||||
public static <T> T create(Config config, Class<T> clazz) {
|
||||
return create(config.root().unwrapped(), clazz);
|
||||
}
|
||||
|
||||
private static <T> T create(Map<String,?> config, Class<T> clazz) {
|
||||
Map<String, Object> configProps = new HashMap<String, Object>();
|
||||
for (Map.Entry<String, ?> configProp : config.entrySet()) {
|
||||
configProps.put(toCamelCase(configProp.getKey()), configProp.getValue());
|
||||
}
|
||||
|
||||
try {
|
||||
T bean = clazz.newInstance();
|
||||
for (PropertyDescriptor beanProp : Introspector.getBeanInfo(clazz).getPropertyDescriptors()) {
|
||||
if (beanProp.getReadMethod() == null || beanProp.getWriteMethod() == null) {
|
||||
continue;
|
||||
}
|
||||
Method setter = beanProp.getWriteMethod();
|
||||
Object configValue = configProps.get(beanProp.getName());
|
||||
if (configValue == null) {
|
||||
throw new ConfigException.Generic(
|
||||
"Could not find " + beanProp.getName() + " from " + clazz.getName() + " in config.");
|
||||
}
|
||||
if (configValue instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,?> child = ((Map<String,?>) configValue);
|
||||
configValue = create(child, beanProp.getPropertyType());
|
||||
}
|
||||
|
||||
setter.invoke(bean, configValue);
|
||||
}
|
||||
|
||||
return bean;
|
||||
} catch (IntrospectionException e) {
|
||||
throw new ConfigException.Generic("Could not resolve a string method name.", e);
|
||||
} catch (InstantiationException e) {
|
||||
throw new ConfigException.Generic(clazz + " needs a public no args constructor", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ConfigException.Generic(clazz + " getters and setters are not accessible", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new ConfigException.Generic("Calling bean method caused exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from hyphenated name to camel case.
|
||||
*/
|
||||
protected static String toCamelCase(String originalName) {
|
||||
String[] words = originalName.split("-+");
|
||||
StringBuilder nameBuilder = new StringBuilder(originalName.length());
|
||||
for (int i = 0; i < words.length; i++) {
|
||||
if (nameBuilder.length() == 0) {
|
||||
nameBuilder.append(words[i]);
|
||||
} else {
|
||||
nameBuilder.append(words[i].substring(0, 1).toUpperCase());
|
||||
nameBuilder.append(words[i].substring(1));
|
||||
}
|
||||
}
|
||||
return nameBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
131
config/src/main/java/com/typesafe/config/ConfigBeanFactory.java
Normal file
131
config/src/main/java/com/typesafe/config/ConfigBeanFactory.java
Normal file
@ -0,0 +1,131 @@
|
||||
package com.typesafe.config;
|
||||
|
||||
import com.typesafe.config.impl.DurationUnit;
|
||||
import com.typesafe.config.impl.MemoryUnit;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Factory for automatic creation of config classes populated with values from config.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* Config configSource = ConfigFactory.parseReader(new InputStreamReader("converters.conf"));
|
||||
* ConverterConfig config = ConfigBeanFactory.create(configSource,ConverterConfig.class);
|
||||
*
|
||||
* Supports nested configs.
|
||||
* Supports automatic types conversion
|
||||
* (https://github.com/typesafehub/config/blob/master/HOCON.md#automatic-type-conversions).
|
||||
*/
|
||||
public class ConfigBeanFactory {
|
||||
|
||||
/**
|
||||
* Creates instance of class containing configuration info from config source
|
||||
* @param config - source of config information
|
||||
* @param clazz - class to be created
|
||||
* @param <T>
|
||||
* @return - instance of config class populated with data from config source
|
||||
*/
|
||||
public static <T> T create(Config config, Class<T> clazz) {
|
||||
return createInternal(config, clazz);
|
||||
}
|
||||
|
||||
private static <T> T createInternal(Config config, Class<T> clazz) {
|
||||
Map<String, ?> configAsMap = config.root().unwrapped();
|
||||
Map<String, Object> configProps = new HashMap<String, Object>();
|
||||
Map<String,String> originalNames = new HashMap<String, String>();
|
||||
for (Map.Entry<String, ?> configProp : configAsMap.entrySet()) {
|
||||
configProps.put(toCamelCase(configProp.getKey()), configProp.getValue());
|
||||
originalNames.put(toCamelCase(configProp.getKey()),configProp.getKey());
|
||||
}
|
||||
|
||||
BeanInfo beanInfo = null;
|
||||
try {
|
||||
beanInfo = Introspector.getBeanInfo(clazz);
|
||||
} catch(IntrospectionException e) {
|
||||
throw new ConfigException.Generic("Could not get bean information for class " + clazz.getName(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
T bean = clazz.newInstance();
|
||||
for (PropertyDescriptor beanProp : beanInfo.getPropertyDescriptors()) {
|
||||
if (beanProp.getReadMethod() == null || beanProp.getWriteMethod() == null) {
|
||||
continue;
|
||||
}
|
||||
Method setter = beanProp.getWriteMethod();
|
||||
Object configValue = configProps.get(beanProp.getName());
|
||||
if (configValue == null) {
|
||||
throw new ConfigException.Generic(
|
||||
"Could not find property '" + beanProp.getName() + "' from class '" + clazz.getName() + "' in config.");
|
||||
}
|
||||
if (configValue instanceof Map) {
|
||||
configValue = createInternal(config.getConfig(originalNames.get(beanProp.getDisplayName())), beanProp.getPropertyType());
|
||||
} else {
|
||||
Class parameterClass = setter.getParameterTypes()[0];
|
||||
configValue = getValueWithAutoConversion(parameterClass, config, originalNames.get(beanProp.getDisplayName()));
|
||||
}
|
||||
setter.invoke(bean, configValue);
|
||||
|
||||
}
|
||||
return bean;
|
||||
} catch (InstantiationException e) {
|
||||
throw new ConfigException.Generic(clazz + " needs a public no args constructor", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ConfigException.Generic(clazz + " getters and setters are not accessible", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new ConfigException.Generic("Calling bean method caused exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getValueWithAutoConversion(Class parameterClass, Config config, String configPropName) {
|
||||
if (parameterClass == Boolean.class || parameterClass == boolean.class) {
|
||||
return config.getBoolean(configPropName);
|
||||
} else if (parameterClass == Byte.class || parameterClass == byte.class) {
|
||||
return Integer.valueOf(config.getInt(configPropName)).byteValue();
|
||||
} else if (parameterClass == Short.class || parameterClass == short.class) {
|
||||
return Integer.valueOf(config.getInt(configPropName)).shortValue();
|
||||
} else if (parameterClass == Integer.class || parameterClass == int.class) {
|
||||
return config.getInt(configPropName);
|
||||
} else if (parameterClass == Double.class || parameterClass == double.class) {
|
||||
return config.getDouble(configPropName);
|
||||
} else if (parameterClass == Long.class || parameterClass == long.class) {
|
||||
String rawVal = config.getString(configPropName);
|
||||
if (DurationUnit.containsDurationToken(rawVal)) {
|
||||
return config.getDuration(configPropName, TimeUnit.NANOSECONDS);
|
||||
} else if (MemoryUnit.containsMemoryToken(rawVal)) {
|
||||
return config.getBytes(configPropName);
|
||||
}
|
||||
return config.getLong(configPropName);
|
||||
} else if (parameterClass == String.class) {
|
||||
return config.getString(configPropName);
|
||||
}
|
||||
|
||||
return config.getAnyRef(configPropName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from hyphenated name to camel case.
|
||||
*/
|
||||
static String toCamelCase(String originalName) {
|
||||
String[] words = originalName.split("-+");
|
||||
StringBuilder nameBuilder = new StringBuilder(originalName.length());
|
||||
for (int i = 0; i < words.length; i++) {
|
||||
if (nameBuilder.length() == 0) {
|
||||
nameBuilder.append(words[i]);
|
||||
} else {
|
||||
nameBuilder.append(words[i].substring(0, 1).toUpperCase());
|
||||
nameBuilder.append(words[i].substring(1));
|
||||
}
|
||||
}
|
||||
return nameBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* https://github.com/typesafehub/config/blob/master/HOCON.md#duration-format
|
||||
*/
|
||||
public enum DurationUnit {
|
||||
|
||||
|
||||
NANOSECONDS(TimeUnit.NANOSECONDS, Arrays.asList("ns", "nano", "nanos", "nanosecond", "nanoseconds")),
|
||||
MICROSECONDS(TimeUnit.MICROSECONDS, Arrays.asList("us", "micro", "micros", "microsecond", "microseconds")),
|
||||
MILLISECONDS(TimeUnit.MILLISECONDS,Arrays.asList("ms", "milli", "millis", "millisecond", "milliseconds")),
|
||||
SECONDS(TimeUnit.SECONDS,Arrays.asList("s", "second", "seconds")),
|
||||
MINUTES(TimeUnit.MINUTES,Arrays.asList("m", "minute", "minutes")),
|
||||
HOURS(TimeUnit.HOURS,Arrays.asList("h", "hour", "hours")),
|
||||
DAYS(TimeUnit.DAYS,Arrays.asList("d", "day", "days"));
|
||||
|
||||
private List<String> aliases;
|
||||
private TimeUnit timeUnit;
|
||||
|
||||
DurationUnit(TimeUnit timeUnit,List<String> aliases) {
|
||||
this.timeUnit = timeUnit;
|
||||
this.aliases = aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds corresponding duration unit by its string representation.
|
||||
* @param rawVal - string duration value ('s','ns' etc.)
|
||||
* @return one of enum values or null if none applicable
|
||||
*/
|
||||
public static final DurationUnit fromString(String rawVal) {
|
||||
for (DurationUnit durationUnit : DurationUnit.values()) {
|
||||
// note that this is deliberately case-sensitive
|
||||
if(durationUnit.aliases.contains(rawVal)) {
|
||||
return durationUnit;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given string contains duration token.
|
||||
* @param rawVal - string like '10s','45nanos' etc.
|
||||
* String is case sensitive, i.e. '10S' is not treated as valid duration string
|
||||
* @return true - if string contains one of enum aliases, false otherwise
|
||||
*/
|
||||
public static boolean containsDurationToken(String rawVal) {
|
||||
String unitStr = rawVal.replaceAll("[^A-Za-z]","");
|
||||
return fromString(unitStr) != null;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return timeUnit;
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* https://github.com/typesafehub/config/blob/master/HOCON.md#size-in-bytes-format
|
||||
*/
|
||||
public enum MemoryUnit {
|
||||
BYTES("", 1024, 0),
|
||||
|
||||
KILOBYTES("kilo", 1000, 1),
|
||||
MEGABYTES("mega", 1000, 2),
|
||||
GIGABYTES("giga", 1000, 3),
|
||||
TERABYTES("tera", 1000, 4),
|
||||
PETABYTES("peta", 1000, 5),
|
||||
EXABYTES("exa", 1000, 6),
|
||||
ZETTABYTES("zetta", 1000, 7),
|
||||
YOTTABYTES("yotta", 1000, 8),
|
||||
|
||||
KIBIBYTES("kibi", 1024, 1),
|
||||
MEBIBYTES("mebi", 1024, 2),
|
||||
GIBIBYTES("gibi", 1024, 3),
|
||||
TEBIBYTES("tebi", 1024, 4),
|
||||
PEBIBYTES("pebi", 1024, 5),
|
||||
EXBIBYTES("exbi", 1024, 6),
|
||||
ZEBIBYTES("zebi", 1024, 7),
|
||||
YOBIBYTES("yobi", 1024, 8);
|
||||
|
||||
final String prefix;
|
||||
final int powerOf;
|
||||
final int power;
|
||||
final BigInteger bytes;
|
||||
|
||||
MemoryUnit(String prefix, int powerOf, int power) {
|
||||
this.prefix = prefix;
|
||||
this.powerOf = powerOf;
|
||||
this.power = power;
|
||||
this.bytes = BigInteger.valueOf(powerOf).pow(power);
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> makeUnitsMap() {
|
||||
Map<String, MemoryUnit> map = new HashMap<String, MemoryUnit>();
|
||||
for (MemoryUnit unit : MemoryUnit.values()) {
|
||||
map.put(unit.prefix + "byte", unit);
|
||||
map.put(unit.prefix + "bytes", unit);
|
||||
if (unit.prefix.length() == 0) {
|
||||
map.put("b", unit);
|
||||
map.put("B", unit);
|
||||
map.put("", unit); // no unit specified means bytes
|
||||
} else {
|
||||
String first = unit.prefix.substring(0, 1);
|
||||
String firstUpper = first.toUpperCase();
|
||||
if (unit.powerOf == 1024) {
|
||||
map.put(first, unit); // 512m
|
||||
map.put(firstUpper, unit); // 512M
|
||||
map.put(firstUpper + "i", unit); // 512Mi
|
||||
map.put(firstUpper + "iB", unit); // 512MiB
|
||||
} else if (unit.powerOf == 1000) {
|
||||
if (unit.power == 1) {
|
||||
map.put(first + "B", unit); // 512kB
|
||||
} else {
|
||||
map.put(firstUpper + "B", unit); // 512MB
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("broken MemoryUnit enum");
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> unitsMap = makeUnitsMap();
|
||||
|
||||
static MemoryUnit parseUnit(String unit) {
|
||||
return unitsMap.get(unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given string contains memory token.
|
||||
* @param rawVal - string like '10B','45bytes' etc.
|
||||
* String is case sensitive, i.e. '10KILOS' is not treated as valid memory size string
|
||||
* @return true - if string contains memory data, false otherwise
|
||||
*/
|
||||
public static boolean containsMemoryToken(String rawVal) {
|
||||
String unitStr = rawVal.replaceAll("[^A-Za-z]","");
|
||||
for (String unit : unitsMap.keySet()) {
|
||||
if(unit.equals(unitStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -547,27 +547,17 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
if (unitString.length() > 2 && !unitString.endsWith("s"))
|
||||
unitString = unitString + "s";
|
||||
|
||||
// note that this is deliberately case-sensitive
|
||||
if (unitString.equals("") || unitString.equals("ms") || unitString.equals("millis")
|
||||
|| unitString.equals("milliseconds")) {
|
||||
if(unitString.equals("")) {
|
||||
units = TimeUnit.MILLISECONDS;
|
||||
} else if (unitString.equals("us") || unitString.equals("micros") || unitString.equals("microseconds")) {
|
||||
units = TimeUnit.MICROSECONDS;
|
||||
} else if (unitString.equals("ns") || unitString.equals("nanos") || unitString.equals("nanoseconds")) {
|
||||
units = TimeUnit.NANOSECONDS;
|
||||
} else if (unitString.equals("d") || unitString.equals("days")) {
|
||||
units = TimeUnit.DAYS;
|
||||
} else if (unitString.equals("h") || unitString.equals("hours")) {
|
||||
units = TimeUnit.HOURS;
|
||||
} else if (unitString.equals("s") || unitString.equals("seconds")) {
|
||||
units = TimeUnit.SECONDS;
|
||||
} else if (unitString.equals("m") || unitString.equals("minutes")) {
|
||||
units = TimeUnit.MINUTES;
|
||||
} else {
|
||||
throw new ConfigException.BadValue(originForException,
|
||||
DurationUnit durationUnit = DurationUnit.fromString(unitString);
|
||||
units = durationUnit != null ? durationUnit.getTimeUnit() : null;
|
||||
if(units == null) {
|
||||
throw new ConfigException.BadValue(originForException,
|
||||
pathForException, "Could not parse time unit '"
|
||||
+ originalUnitString
|
||||
+ "' (try ns, us, ms, s, m, h, d)");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@ -587,77 +577,6 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
private static enum MemoryUnit {
|
||||
BYTES("", 1024, 0),
|
||||
|
||||
KILOBYTES("kilo", 1000, 1),
|
||||
MEGABYTES("mega", 1000, 2),
|
||||
GIGABYTES("giga", 1000, 3),
|
||||
TERABYTES("tera", 1000, 4),
|
||||
PETABYTES("peta", 1000, 5),
|
||||
EXABYTES("exa", 1000, 6),
|
||||
ZETTABYTES("zetta", 1000, 7),
|
||||
YOTTABYTES("yotta", 1000, 8),
|
||||
|
||||
KIBIBYTES("kibi", 1024, 1),
|
||||
MEBIBYTES("mebi", 1024, 2),
|
||||
GIBIBYTES("gibi", 1024, 3),
|
||||
TEBIBYTES("tebi", 1024, 4),
|
||||
PEBIBYTES("pebi", 1024, 5),
|
||||
EXBIBYTES("exbi", 1024, 6),
|
||||
ZEBIBYTES("zebi", 1024, 7),
|
||||
YOBIBYTES("yobi", 1024, 8);
|
||||
|
||||
final String prefix;
|
||||
final int powerOf;
|
||||
final int power;
|
||||
final BigInteger bytes;
|
||||
|
||||
MemoryUnit(String prefix, int powerOf, int power) {
|
||||
this.prefix = prefix;
|
||||
this.powerOf = powerOf;
|
||||
this.power = power;
|
||||
this.bytes = BigInteger.valueOf(powerOf).pow(power);
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> makeUnitsMap() {
|
||||
Map<String, MemoryUnit> map = new HashMap<String, MemoryUnit>();
|
||||
for (MemoryUnit unit : MemoryUnit.values()) {
|
||||
map.put(unit.prefix + "byte", unit);
|
||||
map.put(unit.prefix + "bytes", unit);
|
||||
if (unit.prefix.length() == 0) {
|
||||
map.put("b", unit);
|
||||
map.put("B", unit);
|
||||
map.put("", unit); // no unit specified means bytes
|
||||
} else {
|
||||
String first = unit.prefix.substring(0, 1);
|
||||
String firstUpper = first.toUpperCase();
|
||||
if (unit.powerOf == 1024) {
|
||||
map.put(first, unit); // 512m
|
||||
map.put(firstUpper, unit); // 512M
|
||||
map.put(firstUpper + "i", unit); // 512Mi
|
||||
map.put(firstUpper + "iB", unit); // 512MiB
|
||||
} else if (unit.powerOf == 1000) {
|
||||
if (unit.power == 1) {
|
||||
map.put(first + "B", unit); // 512kB
|
||||
} else {
|
||||
map.put(firstUpper + "B", unit); // 512MB
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("broken MemoryUnit enum");
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> unitsMap = makeUnitsMap();
|
||||
|
||||
static MemoryUnit parseUnit(String unit) {
|
||||
return unitsMap.get(unit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a size-in-bytes string. If no units are specified in the string,
|
||||
* it is assumed to be in bytes. The returned value is in bytes. The purpose
|
||||
|
80
config/src/test/java/beanconfig/ArraysConfig.java
Normal file
80
config/src/test/java/beanconfig/ArraysConfig.java
Normal file
@ -0,0 +1,80 @@
|
||||
package beanconfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ArraysConfig {
|
||||
|
||||
List<Integer> empty;
|
||||
List<Integer> ofInt;
|
||||
List<String> ofString;
|
||||
List<Double> ofDouble;
|
||||
List<Object> ofNull;
|
||||
List<Boolean> ofBoolean;
|
||||
List<List> ofArray;
|
||||
List<Object> ofObject;
|
||||
|
||||
|
||||
public List<Integer> getEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
public void setEmpty(List<Integer> empty) {
|
||||
this.empty = empty;
|
||||
}
|
||||
|
||||
public List<Integer> getOfInt() {
|
||||
return ofInt;
|
||||
}
|
||||
|
||||
public void setOfInt(List<Integer> ofInt) {
|
||||
this.ofInt = ofInt;
|
||||
}
|
||||
|
||||
public List<String> getOfString() {
|
||||
return ofString;
|
||||
}
|
||||
|
||||
public void setOfString(List<String> ofString) {
|
||||
this.ofString = ofString;
|
||||
}
|
||||
|
||||
public List<Double> getOfDouble() {
|
||||
return ofDouble;
|
||||
}
|
||||
|
||||
public void setOfDouble(List<Double> ofDouble) {
|
||||
this.ofDouble = ofDouble;
|
||||
}
|
||||
|
||||
public List<Object> getOfNull() {
|
||||
return ofNull;
|
||||
}
|
||||
|
||||
public void setOfNull(List<Object> ofNull) {
|
||||
this.ofNull = ofNull;
|
||||
}
|
||||
|
||||
public List<Boolean> getOfBoolean() {
|
||||
return ofBoolean;
|
||||
}
|
||||
|
||||
public void setOfBoolean(List<Boolean> ofBoolean) {
|
||||
this.ofBoolean = ofBoolean;
|
||||
}
|
||||
|
||||
public List<List> getOfArray() {
|
||||
return ofArray;
|
||||
}
|
||||
|
||||
public void setOfArray(List<List> ofArray) {
|
||||
this.ofArray = ofArray;
|
||||
}
|
||||
|
||||
public List<Object> getOfObject() {
|
||||
return ofObject;
|
||||
}
|
||||
|
||||
public void setOfObject(List<Object> ofObject) {
|
||||
this.ofObject = ofObject;
|
||||
}
|
||||
}
|
59
config/src/test/java/beanconfig/BooleansConfig.java
Normal file
59
config/src/test/java/beanconfig/BooleansConfig.java
Normal file
@ -0,0 +1,59 @@
|
||||
package beanconfig;
|
||||
|
||||
|
||||
public class BooleansConfig {
|
||||
Boolean trueVal;
|
||||
Boolean trueValAgain;
|
||||
Boolean falseVal;
|
||||
Boolean falseValAgain;
|
||||
Boolean on;
|
||||
Boolean off;
|
||||
|
||||
public Boolean getTrueVal() {
|
||||
return trueVal;
|
||||
}
|
||||
|
||||
public void setTrueVal(Boolean trueVal) {
|
||||
this.trueVal = trueVal;
|
||||
}
|
||||
|
||||
public Boolean getTrueValAgain() {
|
||||
return trueValAgain;
|
||||
}
|
||||
|
||||
public void setTrueValAgain(Boolean trueValAgain) {
|
||||
this.trueValAgain = trueValAgain;
|
||||
}
|
||||
|
||||
public Boolean getFalseVal() {
|
||||
return falseVal;
|
||||
}
|
||||
|
||||
public void setFalseVal(Boolean falseVal) {
|
||||
this.falseVal = falseVal;
|
||||
}
|
||||
|
||||
public Boolean getFalseValAgain() {
|
||||
return falseValAgain;
|
||||
}
|
||||
|
||||
public void setFalseValAgain(Boolean falseValAgain) {
|
||||
this.falseValAgain = falseValAgain;
|
||||
}
|
||||
|
||||
public Boolean getOn() {
|
||||
return on;
|
||||
}
|
||||
|
||||
public void setOn(Boolean on) {
|
||||
this.on = on;
|
||||
}
|
||||
|
||||
public Boolean getOff() {
|
||||
return off;
|
||||
}
|
||||
|
||||
public void setOff(Boolean off) {
|
||||
this.off = off;
|
||||
}
|
||||
}
|
32
config/src/test/java/beanconfig/BytesConfig.java
Normal file
32
config/src/test/java/beanconfig/BytesConfig.java
Normal file
@ -0,0 +1,32 @@
|
||||
package beanconfig;
|
||||
|
||||
public class BytesConfig {
|
||||
|
||||
private Long kilobyte;
|
||||
private Long kibibyte;
|
||||
private Long thousandBytes;
|
||||
|
||||
public Long getKilobyte() {
|
||||
return kilobyte;
|
||||
}
|
||||
|
||||
public void setKilobyte(Long kilobyte) {
|
||||
this.kilobyte = kilobyte;
|
||||
}
|
||||
|
||||
public Long getKibibyte() {
|
||||
return kibibyte;
|
||||
}
|
||||
|
||||
public void setKibibyte(Long kibibyte) {
|
||||
this.kibibyte = kibibyte;
|
||||
}
|
||||
|
||||
public Long getThousandBytes() {
|
||||
return thousandBytes;
|
||||
}
|
||||
|
||||
public void setThousandBytes(Long thousandBytes) {
|
||||
this.thousandBytes = thousandBytes;
|
||||
}
|
||||
}
|
33
config/src/test/java/beanconfig/DurationsConfig.java
Normal file
33
config/src/test/java/beanconfig/DurationsConfig.java
Normal file
@ -0,0 +1,33 @@
|
||||
package beanconfig;
|
||||
|
||||
|
||||
public class DurationsConfig {
|
||||
Long second;
|
||||
Long secondAsNumber;
|
||||
Long halfSecond;
|
||||
|
||||
|
||||
public Long getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public void setSecond(Long second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public Long getSecondAsNumber() {
|
||||
return secondAsNumber;
|
||||
}
|
||||
|
||||
public void setSecondAsNumber(Long secondAsNumber) {
|
||||
this.secondAsNumber = secondAsNumber;
|
||||
}
|
||||
|
||||
public Long getHalfSecond() {
|
||||
return halfSecond;
|
||||
}
|
||||
|
||||
public void setHalfSecond(Long halfSecond) {
|
||||
this.halfSecond = halfSecond;
|
||||
}
|
||||
}
|
14
config/src/test/java/beanconfig/NoFoundPropBeanConfig.java
Normal file
14
config/src/test/java/beanconfig/NoFoundPropBeanConfig.java
Normal file
@ -0,0 +1,14 @@
|
||||
package beanconfig;
|
||||
|
||||
public class NoFoundPropBeanConfig extends TestBeanConfig{
|
||||
|
||||
private String propNotListedInConfig;
|
||||
|
||||
public String getPropNotListedInConfig() {
|
||||
return propNotListedInConfig;
|
||||
}
|
||||
|
||||
public void setPropNotListedInConfig(String propNotListedInConfig) {
|
||||
this.propNotListedInConfig = propNotListedInConfig;
|
||||
}
|
||||
}
|
98
config/src/test/java/beanconfig/NumbersConfig.java
Normal file
98
config/src/test/java/beanconfig/NumbersConfig.java
Normal file
@ -0,0 +1,98 @@
|
||||
package beanconfig;
|
||||
|
||||
|
||||
public class NumbersConfig {
|
||||
|
||||
|
||||
private byte byteVal;
|
||||
private Byte byteObj;
|
||||
private short shortVal;
|
||||
private Short shortObj;
|
||||
private int intVal;
|
||||
private Integer intObj;
|
||||
private long longVal;
|
||||
private Long longObj;
|
||||
private double doubleVal;
|
||||
private Double doubleObj;
|
||||
|
||||
|
||||
public int getIntVal() {
|
||||
return intVal;
|
||||
}
|
||||
|
||||
public void setIntVal(int intVal) {
|
||||
this.intVal = intVal;
|
||||
}
|
||||
|
||||
public Integer getIntObj() {
|
||||
return intObj;
|
||||
}
|
||||
|
||||
public void setIntObj(Integer intObj) {
|
||||
this.intObj = intObj;
|
||||
}
|
||||
|
||||
public long getLongVal() {
|
||||
return longVal;
|
||||
}
|
||||
|
||||
public void setLongVal(long longVal) {
|
||||
this.longVal = longVal;
|
||||
}
|
||||
|
||||
public Long getLongObj() {
|
||||
return longObj;
|
||||
}
|
||||
|
||||
public void setLongObj(Long longObj) {
|
||||
this.longObj = longObj;
|
||||
}
|
||||
|
||||
public double getDoubleVal() {
|
||||
return doubleVal;
|
||||
}
|
||||
|
||||
public void setDoubleVal(double doubleVal) {
|
||||
this.doubleVal = doubleVal;
|
||||
}
|
||||
|
||||
public Double getDoubleObj() {
|
||||
return doubleObj;
|
||||
}
|
||||
|
||||
public void setDoubleObj(Double doubleObj) {
|
||||
this.doubleObj = doubleObj;
|
||||
}
|
||||
|
||||
public byte getByteVal() {
|
||||
return byteVal;
|
||||
}
|
||||
|
||||
public void setByteVal(byte byteVal) {
|
||||
this.byteVal = byteVal;
|
||||
}
|
||||
|
||||
public Byte getByteObj() {
|
||||
return byteObj;
|
||||
}
|
||||
|
||||
public void setByteObj(Byte byteObj) {
|
||||
this.byteObj = byteObj;
|
||||
}
|
||||
|
||||
public short getShortVal() {
|
||||
return shortVal;
|
||||
}
|
||||
|
||||
public void setShortVal(short shortVal) {
|
||||
this.shortVal = shortVal;
|
||||
}
|
||||
|
||||
public Short getShortObj() {
|
||||
return shortObj;
|
||||
}
|
||||
|
||||
public void setShortObj(Short shortObj) {
|
||||
this.shortObj = shortObj;
|
||||
}
|
||||
}
|
15
config/src/test/java/beanconfig/TestBeanConfig.java
Normal file
15
config/src/test/java/beanconfig/TestBeanConfig.java
Normal file
@ -0,0 +1,15 @@
|
||||
package beanconfig;
|
||||
|
||||
public class TestBeanConfig {
|
||||
|
||||
|
||||
private NumbersConfig numbers;
|
||||
|
||||
public NumbersConfig getNumbers() {
|
||||
return numbers;
|
||||
}
|
||||
|
||||
public void setNumbers(NumbersConfig numbers) {
|
||||
this.numbers = numbers;
|
||||
}
|
||||
}
|
62
config/src/test/resources/beanconfig/beanconfig01.conf
Normal file
62
config/src/test/resources/beanconfig/beanconfig01.conf
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"booleans" : {
|
||||
"trueVal" : true,
|
||||
"trueValAgain" : ${booleans.trueVal},
|
||||
"falseVal" : false,
|
||||
"falseValAgain" : ${booleans.falseVal},
|
||||
"on" : "on",
|
||||
"off" : "off"
|
||||
}
|
||||
|
||||
"numbers" : {
|
||||
"byteVal" : "1",
|
||||
"byteObj" : ${numbers.byteVal},
|
||||
"shortVal" : "1",
|
||||
"shortObj" : ${numbers.shortVal},
|
||||
"intVal" : "1",
|
||||
"intObj" : ${numbers.intVal},
|
||||
"longVal" : "1",
|
||||
"longObj" : ${numbers.longVal},
|
||||
"doubleVal" : "1.0",
|
||||
"doubleObj" : ${numbers.doubleVal}
|
||||
}
|
||||
//
|
||||
"strings" : {
|
||||
"abcd" : "abcd",
|
||||
"abcdAgain" : ${strings.a}${strings.b}${strings.c}${strings.d},
|
||||
"a" : "a",
|
||||
"b" : "b",
|
||||
"c" : "c",
|
||||
"d" : "d",
|
||||
"concatenated" : null bar 42 baz true 3.14 hi,
|
||||
"double" : "3.14",
|
||||
"number" : "57",
|
||||
"null" : "null",
|
||||
"true" : "true",
|
||||
"yes" : "yes",
|
||||
"false" : "false",
|
||||
"no" : "no"
|
||||
},
|
||||
|
||||
"arrays" : {
|
||||
"empty" : [],
|
||||
"ofInt" : [1, 2, 3],
|
||||
"ofString" : [ ${strings.a}, ${strings.b}, ${strings.c} ],
|
||||
"ofDouble" : [3.14, 4.14, 5.14],
|
||||
"ofNull" : [null, null, null],
|
||||
"ofBoolean" : [true, false],
|
||||
"ofArray" : [${arrays.ofString}, ${arrays.ofString}, ${arrays.ofString}],
|
||||
"ofObject" : [${numbers}, ${booleans}, ${strings}]
|
||||
},
|
||||
"bytes" : {
|
||||
"kilobyte" : "1kB",
|
||||
"kibibyte" : "1K",
|
||||
"thousandBytes" : "1000B"
|
||||
},
|
||||
"durations" : {
|
||||
"second" : 1s,
|
||||
"secondAsNumber" : 1000000000,
|
||||
"halfSecond" : 0.5s
|
||||
},
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2013 Typesafe Inc. <http://typesafe.com>
|
||||
*/
|
||||
package com.typesafe.config
|
||||
|
||||
import org.junit.Assert._
|
||||
import org.junit._
|
||||
|
||||
class BeanFactoryTest {
|
||||
|
||||
@Test
|
||||
def toCamelCase() {
|
||||
assertEquals("configProp", BeanFactory.toCamelCase("config-prop"))
|
||||
assertEquals("fooBar", BeanFactory.toCamelCase("foo-----bar"))
|
||||
assertEquals("foo", BeanFactory.toCamelCase("-foo"))
|
||||
assertEquals("bar", BeanFactory.toCamelCase("bar-"))
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (C) 2013 Typesafe Inc. <http://typesafe.com>
|
||||
*/
|
||||
package com.typesafe.config
|
||||
|
||||
import java.io.{ InputStream, InputStreamReader }
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import beanconfig._
|
||||
import org.junit.Assert._
|
||||
import org.junit._
|
||||
|
||||
class ConfigBeanFactoryTest {
|
||||
|
||||
@Test
|
||||
def toCamelCase() {
|
||||
assertEquals("configProp", ConfigBeanFactory.toCamelCase("config-prop"))
|
||||
assertEquals("fooBar", ConfigBeanFactory.toCamelCase("foo-----bar"))
|
||||
assertEquals("foo", ConfigBeanFactory.toCamelCase("-foo"))
|
||||
assertEquals("bar", ConfigBeanFactory.toCamelCase("bar-"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreate() {
|
||||
val configIs: InputStream = this.getClass().getClassLoader().getResourceAsStream("beanconfig/beanconfig01.conf")
|
||||
val config: Config = ConfigFactory.parseReader(new InputStreamReader(configIs),
|
||||
ConfigParseOptions.defaults.setSyntax(ConfigSyntax.CONF)).resolve
|
||||
val beanConfig: TestBeanConfig = ConfigBeanFactory.create(config, classOf[TestBeanConfig])
|
||||
assertNotNull(beanConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testUnknownProp() {
|
||||
val configIs: InputStream = this.getClass().getClassLoader().getResourceAsStream("beanconfig/beanconfig01.conf")
|
||||
val config: Config = ConfigFactory.parseReader(new InputStreamReader(configIs),
|
||||
ConfigParseOptions.defaults.setSyntax(ConfigSyntax.CONF)).resolve
|
||||
var expected: ConfigException.Generic = null
|
||||
var beanConfig: NoFoundPropBeanConfig = null
|
||||
try {
|
||||
beanConfig = ConfigBeanFactory.create(config, classOf[NoFoundPropBeanConfig])
|
||||
} catch {
|
||||
case cge: ConfigException.Generic => expected = cge
|
||||
case e: Exception => expected = null
|
||||
}
|
||||
assertNotNull(expected)
|
||||
assertEquals("Could not find property 'propNotListedInConfig' from class 'beanconfig.NoFoundPropBeanConfig' in config.",
|
||||
expected.getMessage)
|
||||
assertNull(beanConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateBool() {
|
||||
val beanConfig: BooleansConfig = ConfigBeanFactory.create(loadConfig().getConfig("booleans"), classOf[BooleansConfig])
|
||||
assertNotNull(beanConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateNumber() {
|
||||
val beanConfig: NumbersConfig = ConfigBeanFactory.create(loadConfig().getConfig("numbers"), classOf[NumbersConfig])
|
||||
assertNotNull(beanConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateList() {
|
||||
val beanConfig: ArraysConfig = ConfigBeanFactory.create(loadConfig().getConfig("arrays"), classOf[ArraysConfig])
|
||||
assertNotNull(beanConfig)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateDuration() {
|
||||
val beanConfig: DurationsConfig = ConfigBeanFactory.create(loadConfig().getConfig("durations"), classOf[DurationsConfig])
|
||||
assertNotNull(beanConfig)
|
||||
assertEquals(beanConfig.getHalfSecond, TimeUnit.MILLISECONDS.toNanos(500))
|
||||
assertEquals(beanConfig.getSecond, TimeUnit.SECONDS.toNanos(1))
|
||||
assertEquals(beanConfig.getSecondAsNumber, TimeUnit.SECONDS.toNanos(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateBytes() {
|
||||
val beanConfig: BytesConfig = ConfigBeanFactory.create(loadConfig().getConfig("bytes"), classOf[BytesConfig])
|
||||
assertNotNull(beanConfig)
|
||||
assertEquals(beanConfig.getKibibyte, 1024L)
|
||||
assertEquals(beanConfig.getKilobyte, 1000L)
|
||||
assertEquals(beanConfig.getThousandBytes, 1000L)
|
||||
}
|
||||
|
||||
private def loadConfig(): Config = {
|
||||
val configIs: InputStream = this.getClass().getClassLoader().getResourceAsStream("beanconfig/beanconfig01.conf")
|
||||
val config: Config = ConfigFactory.parseReader(new InputStreamReader(configIs),
|
||||
ConfigParseOptions.defaults.setSyntax(ConfigSyntax.CONF)).resolve
|
||||
config
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user