public static T createInternal()

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