@Nonnull Config config) throws IllegalAccessException {
Config fieldDefaults = classInfo.getFieldDefaults();
Collection<String> unusedKeys = new HashSet<>(config.root().keySet());
ConfigValue fieldAliasesValue = config.root().get("_rename");
ConfigObject fieldAliases;
if ((fieldAliasesValue != null) && (fieldAliasesValue.valueType() != ConfigValueType.NULL)) {
fieldAliases = (ConfigObject) fieldAliasesValue;
} else {
fieldAliases = ConfigFactory.empty().root();
}
ConfigValue primaryFieldNameValue = config.root().get("_primary");
String primaryFieldName = null;
boolean usedPrimaryField = false;
if ((primaryFieldNameValue != null) && (primaryFieldNameValue.valueType() != ConfigValueType.NULL)) {
primaryFieldName = (String) primaryFieldNameValue.unwrapped();
}
for (CodableFieldInfo field : classInfo.values()) {
if (field.isWriteOnly()) {
continue;
}
String fieldName = field.getName();
if (fieldAliases.containsKey(fieldName)) {
String aliasName = (String) fieldAliases.get(fieldName).unwrapped();
unusedKeys.remove(aliasName);
if (config.root().containsKey(fieldName)
&& (config.root().get(fieldName).valueType() == ConfigValueType.NULL)) {
// complain about values for renamed fields unless null or used elsewhere
unusedKeys.remove(fieldName);
}
} else {
unusedKeys.remove(fieldName);
}
}
if (!unusedKeys.isEmpty()) {
for (Iterator<String> unusedKeyIterator = unusedKeys.iterator();
unusedKeyIterator.hasNext(); ) {
String unusedKey = unusedKeyIterator.next();
if (unusedKey.charAt(0) == '_') {
unusedKeyIterator.remove();
}
}
}
if (unusedKeys.size() > 1) {
throw new ConfigException.BadPath(config.origin(), "unrecognized key(s) " + unusedKeys.toString());
}
for (CodableFieldInfo field : classInfo.values()) {
if (field.isWriteOnly()) {
continue;
}
String fieldName = field.getName();
String resolvedName;
Config resolvedConfig;
if (fieldAliases.containsKey(fieldName)) {
String aliasName = (String) fieldAliases.get(fieldName).unwrapped();
if (config.hasPath(aliasName)) {
ConfigValue aliasValue = config.getValue(aliasName); // alias targets are paths
resolvedConfig = config.root().withValue(fieldName, aliasValue).toConfig();
} else {
resolvedConfig = config.root().withoutKey(fieldName).toConfig();
}
resolvedName = aliasName;
} else {
resolvedName = fieldName;
resolvedConfig = config;
}
Object value = null;
if (resolvedName.equals(primaryFieldName)) {
if (unusedKeys.size() == 1) {
String onlyUnusedKey = unusedKeys.iterator().next();
ConfigObject onlyObject = resolvedConfig.root().withOnlyKey(onlyUnusedKey);
if (resolvedConfig.hasPath(primaryFieldName)) {
onlyObject = onlyObject.withFallback(
resolvedConfig.getValue(primaryFieldName).atKey(onlyUnusedKey));
}
CodableClassInfo primaryInfo = getOrCreateClassInfo(
field.getTypeOrComponentType());
PluginMap primaryMap = primaryInfo.getPluginMap();