in scripts/src/main/java/com/gu/typesafe/config/impl/ConfigBeanImpl.java [37:129]
public static <T> T createInternal(com.gu.typesafe.config.Config config, Class<T> clazz) {
if (((com.gu.typesafe.config.impl.SimpleConfig)config).root().resolveStatus() != ResolveStatus.RESOLVED)
throw new com.gu.typesafe.config.ConfigException.NotResolved(
"need to Config#resolve() a config before using it to initialize a bean, see the API docs for Config#resolve()");
Map<String, com.gu.typesafe.config.impl.AbstractConfigValue> configProps = new HashMap<String, com.gu.typesafe.config.impl.AbstractConfigValue>();
Map<String, String> originalNames = new HashMap<String, String>();
for (Map.Entry<String, com.gu.typesafe.config.ConfigValue> configProp : config.root().entrySet()) {
String originalName = configProp.getKey();
String camelName = ConfigImplUtil.toCamelCase(originalName);
// if a setting is in there both as some hyphen name and the camel name,
// the camel one wins
if (originalNames.containsKey(camelName) && !originalName.equals(camelName)) {
// if we aren't a camel name to start with, we lose.
// if we are or we are the first matching key, we win.
} else {
configProps.put(camelName, (com.gu.typesafe.config.impl.AbstractConfigValue) configProp.getValue());
originalNames.put(camelName, originalName);
}
}
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(clazz);
} catch (IntrospectionException e) {
throw new com.gu.typesafe.config.ConfigException.BadBean("Could not get bean information for class " + clazz.getName(), e);
}
try {
List<PropertyDescriptor> beanProps = new ArrayList<PropertyDescriptor>();
for (PropertyDescriptor beanProp : beanInfo.getPropertyDescriptors()) {
if (beanProp.getReadMethod() == null || beanProp.getWriteMethod() == null) {
continue;
}
beanProps.add(beanProp);
}
// Try to throw all validation issues at once (this does not comprehensively
// find every issue, but it should find common ones).
List<com.gu.typesafe.config.ConfigException.ValidationProblem> problems = new ArrayList<com.gu.typesafe.config.ConfigException.ValidationProblem>();
for (PropertyDescriptor beanProp : beanProps) {
Method setter = beanProp.getWriteMethod();
Class<?> parameterClass = setter.getParameterTypes()[0];
com.gu.typesafe.config.ConfigValueType expectedType = getValueTypeOrNull(parameterClass);
if (expectedType != null) {
String name = originalNames.get(beanProp.getName());
if (name == null)
name = beanProp.getName();
Path path = Path.newKey(name);
com.gu.typesafe.config.impl.AbstractConfigValue configValue = configProps.get(beanProp.getName());
if (configValue != null) {
com.gu.typesafe.config.impl.SimpleConfig.checkValid(path, expectedType, configValue, problems);
} else {
if (!isOptionalProperty(clazz, beanProp)) {
com.gu.typesafe.config.impl.SimpleConfig.addMissing(problems, expectedType, path, config.origin());
}
}
}
}
if (!problems.isEmpty()) {
throw new com.gu.typesafe.config.ConfigException.ValidationFailed(problems);
}
// Fill in the bean instance
T bean = clazz.newInstance();
for (PropertyDescriptor beanProp : beanProps) {
Method setter = beanProp.getWriteMethod();
Type parameterType = setter.getGenericParameterTypes()[0];
Class<?> parameterClass = setter.getParameterTypes()[0];
String configPropName = originalNames.get(beanProp.getName());
// Is the property key missing in the config?
if (configPropName == null) {
// If so, continue if the field is marked as @{link Optional}
if (isOptionalProperty(clazz, beanProp)) {
continue;
}
// Otherwise, raise a {@link Missing} exception right here
throw new com.gu.typesafe.config.ConfigException.Missing(beanProp.getName());
}
Object unwrapped = getValue(clazz, parameterType, parameterClass, config, configPropName);
setter.invoke(bean, unwrapped);
}
return bean;
} catch (InstantiationException e) {
throw new com.gu.typesafe.config.ConfigException.BadBean(clazz.getName() + " needs a public no-args constructor to be used as a bean", e);
} catch (IllegalAccessException e) {
throw new com.gu.typesafe.config.ConfigException.BadBean(clazz.getName() + " getters and setters are not accessible, they must be for use as a bean", e);
} catch (InvocationTargetException e) {
throw new com.gu.typesafe.config.ConfigException.BadBean("Calling bean method on " + clazz.getName() + " caused an exception", e);
}
}