mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
Add Support for Enums in Config Beans.
This commit is contained in:
parent
23c5306038
commit
0791e41a03
@ -597,6 +597,22 @@ public interface Config extends ConfigMergeable {
|
||||
*/
|
||||
String getString(String path);
|
||||
|
||||
/**
|
||||
* @param enumClass
|
||||
* an enum class
|
||||
* @param <T>
|
||||
* a generic denoting a specific type of enum
|
||||
* @param path
|
||||
* path expression
|
||||
* @return the {@code Enum} value at the requested path
|
||||
* of the requested enum class
|
||||
* @throws ConfigException.Missing
|
||||
* if value is absent or null
|
||||
* @throws ConfigException.WrongType
|
||||
* if value is not convertible to an Enum
|
||||
*/
|
||||
public <T extends Enum<T>> T getEnum(Class<T> enumClass, String path);
|
||||
|
||||
/**
|
||||
* @param path
|
||||
* path expression
|
||||
@ -882,6 +898,25 @@ public interface Config extends ConfigMergeable {
|
||||
*/
|
||||
List<String> getStringList(String path);
|
||||
|
||||
/**
|
||||
* Gets a list value with {@code Enum} elements. Throws if the
|
||||
* path is unset or null or not a list or contains values not
|
||||
* convertible to {@code Enum}.
|
||||
*
|
||||
* @param enumClass
|
||||
* the enum class
|
||||
* @param <T>
|
||||
* a generic denoting a specific type of enum
|
||||
* @param path
|
||||
* the path to the list value.
|
||||
* @return the list at the path
|
||||
* @throws ConfigException.Missing
|
||||
* if value is absent or null
|
||||
* @throws ConfigException.WrongType
|
||||
* if value is not convertible to a list of {@code Enum}
|
||||
*/
|
||||
<T extends Enum<T>> List<T> getEnumList(Class<T> enumClass, String path);
|
||||
|
||||
/**
|
||||
* Gets a list value with object elements. Throws if the
|
||||
* path is unset or null or not a list or contains values not
|
||||
|
@ -175,6 +175,10 @@ public class ConfigBeanImpl {
|
||||
return config.getValue(configPropName);
|
||||
} else if (parameterClass == ConfigList.class) {
|
||||
return config.getList(configPropName);
|
||||
} else if (parameterClass.isEnum()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Enum enumValue = config.getEnum((Class<Enum>) parameterClass, configPropName);
|
||||
return enumValue;
|
||||
} else if (hasAtLeastOneBeanProperty(parameterClass)) {
|
||||
return createInternal(config.getConfig(configPropName), parameterClass);
|
||||
} else {
|
||||
@ -207,6 +211,10 @@ public class ConfigBeanImpl {
|
||||
return config.getObjectList(configPropName);
|
||||
} else if (elementType == ConfigValue.class) {
|
||||
return config.getList(configPropName);
|
||||
} else if (((Class<?>) elementType).isEnum()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Enum> enumValues = config.getEnumList((Class<Enum>) elementType, configPropName);
|
||||
return enumValues;
|
||||
} else if (hasAtLeastOneBeanProperty((Class<?>) elementType)) {
|
||||
List<Object> beanList = new ArrayList<Object>();
|
||||
List<? extends Config> configList = config.getConfigList(configPropName);
|
||||
|
@ -247,6 +247,12 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
return (String) v.unwrapped();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Enum<T>> T getEnum(Class<T> enumClass, String path) {
|
||||
ConfigValue v = find(path, ConfigValueType.STRING);
|
||||
return getEnumValue(path, enumClass, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigList getList(String path) {
|
||||
AbstractConfigValue v = find(path, ConfigValueType.LIST);
|
||||
@ -381,6 +387,35 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
return getHomogeneousUnwrappedList(path, ConfigValueType.STRING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Enum<T>> List<T> getEnumList(Class<T> enumClass, String path) {
|
||||
List<ConfigString> enumNames = getHomogeneousWrappedList(path, ConfigValueType.STRING);
|
||||
List<T> enumList = new ArrayList<T>();
|
||||
for (ConfigString enumName : enumNames) {
|
||||
enumList.add(getEnumValue(path, enumClass, enumName));
|
||||
}
|
||||
return enumList;
|
||||
}
|
||||
|
||||
private <T extends Enum<T>> T getEnumValue(String path, Class<T> enumClass, ConfigValue enumConfigValue) {
|
||||
String enumName = (String) enumConfigValue.unwrapped();
|
||||
try {
|
||||
return Enum.valueOf(enumClass, enumName);
|
||||
} catch (IllegalArgumentException e) {
|
||||
List<String> enumNames = new ArrayList<String>();
|
||||
Enum[] enumConstants = enumClass.getEnumConstants();
|
||||
if (enumConstants != null) {
|
||||
for (Enum enumConstant : enumConstants) {
|
||||
enumNames.add(enumConstant.name());
|
||||
}
|
||||
}
|
||||
throw new ConfigException.BadValue(
|
||||
enumConfigValue.origin(), path,
|
||||
String.format("The enum class %s has no constant of the name '%s' (should be one of %s.)",
|
||||
enumClass.getSimpleName(), enumName, enumNames));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends ConfigValue> List<T> getHomogeneousWrappedList(
|
||||
String path, ConfigValueType expected) {
|
||||
|
65
config/src/test/java/beanconfig/EnumsConfig.java
Normal file
65
config/src/test/java/beanconfig/EnumsConfig.java
Normal file
@ -0,0 +1,65 @@
|
||||
package beanconfig;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EnumsConfig {
|
||||
public enum Problem {
|
||||
P1, P2, P3;
|
||||
};
|
||||
public enum Solution {
|
||||
S1, S2, S3;
|
||||
}
|
||||
Problem problem;
|
||||
List<Solution> solutions;
|
||||
|
||||
public Problem getProblem() {
|
||||
return problem;
|
||||
}
|
||||
|
||||
public void setProblem(Problem problem) {
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
public List<Solution> getSolutions() {
|
||||
return solutions;
|
||||
}
|
||||
|
||||
public void setSolutions(List<Solution> solutions) {
|
||||
this.solutions = solutions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof EnumsConfig)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumsConfig that = (EnumsConfig) o;
|
||||
|
||||
if (getProblem() != that.getProblem()) {
|
||||
return false;
|
||||
}
|
||||
return getSolutions() == that.getSolutions();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = getProblem() != null ? getProblem().hashCode() : 0;
|
||||
result = 31 * result + (getSolutions() != null ? getSolutions().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("EnumsConfig{");
|
||||
sb.append("problem=").append(problem);
|
||||
sb.append(", solution=").append(solutions);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -93,6 +93,10 @@
|
||||
"list" : [1,2,3],
|
||||
"unwrappedMap" : ${validation}
|
||||
},
|
||||
"enums" : {
|
||||
"problem" : "P1",
|
||||
"solutions" : ["S1", "S3"]
|
||||
},
|
||||
"objects" : {
|
||||
"valueObject": {
|
||||
"mandatoryValue": "notNull"
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
package com.typesafe.config.impl
|
||||
|
||||
import beanconfig.EnumsConfig.{ Solution, Problem }
|
||||
import com.typesafe.config._
|
||||
|
||||
import java.io.{ InputStream, InputStreamReader }
|
||||
@ -13,6 +14,7 @@ import org.junit.Assert._
|
||||
import org.junit._
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
class ConfigBeanFactoryTest extends TestUtils {
|
||||
|
||||
@ -70,6 +72,14 @@ class ConfigBeanFactoryTest extends TestUtils {
|
||||
assertEquals("yes", beanConfig.getYes)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateEnum() {
|
||||
val beanConfig: EnumsConfig = ConfigBeanFactory.create(loadConfig().getConfig("enums"), classOf[EnumsConfig])
|
||||
assertNotNull(beanConfig)
|
||||
assertEquals(Problem.P1, beanConfig.getProblem)
|
||||
assertEquals(ArrayBuffer(Solution.S1, Solution.S3), beanConfig.getSolutions.asScala)
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateNumber() {
|
||||
val beanConfig: NumbersConfig = ConfigBeanFactory.create(loadConfig().getConfig("numbers"), classOf[NumbersConfig])
|
||||
@ -190,6 +200,16 @@ class ConfigBeanFactoryTest extends TestUtils {
|
||||
assertTrue("error about the right property", e.getMessage.contains("notBean"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def testNotAnEnumField() {
|
||||
val e = intercept[ConfigException.BadValue] {
|
||||
ConfigBeanFactory.create(parseConfig("{problem=P1,solutions=[S4]}"), classOf[EnumsConfig])
|
||||
}
|
||||
assertTrue("invalid value error", e.getMessage.contains("Invalid value"))
|
||||
assertTrue("error about the right property", e.getMessage.contains("solutions"))
|
||||
assertTrue("error enumerates the enum constants", e.getMessage.contains("should be one of [S1, S2, S3]"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def testUnsupportedListElement() {
|
||||
val e = intercept[ConfigException.BadBean] {
|
||||
|
Loading…
Reference in New Issue
Block a user