String stype = (String) typeValue.unwrapped();
try {
Class<T> normalType = (Class<T>) pluginMap.getClass(stype);
ConfigObject aliasDefaults = pluginMap.aliasDefaults(stype);
ConfigObject fieldValues = configObject.withoutKey(classField).withFallback(aliasDefaults);
CodableClassInfo normalInfo = getOrCreateClassInfo(normalType);
return createAndPopulate(normalInfo, normalType, fieldValues);
} catch (ClassNotFoundException e) {
String helpMessage = Plugins.classNameSuggestions(pluginRegistry, pluginMap, stype);
throw new ConfigException.UnresolvedSubstitution(configObject.origin(), helpMessage, e);
}
}
/* if no chance of instantiating current type, try to get a new type from various special syntax/ settings */
if ((type == null) || Modifier.isAbstract(type.getModifiers()) || Modifier.isInterface(type.getModifiers())) {
T maybeSingleKey = hydrateSingleKeyObject(pluginMap, configObject);
if (maybeSingleKey != null) {
return maybeSingleKey;
}
/* inlined types syntax ie "{ type-value: some-value, some-field: some-other-value, ...}".
* Opt-in is on a per alias basis, and the target type must be unambiguous amongst aliases
* that have opted in. The recognized alias label is then replaced with the _primary field. */
String matched = null;
for (String alias : pluginMap.inlinedAliases()) {
if (configObject.get(alias) != null) {
if (matched != null) {
String message = String.format(
"no type specified, more than one key, and both %s and %s match for inlined types.",
matched, alias);
throw new ConfigException.Parse(configObject.origin(), message);
}
matched = alias;
}
}
if (matched != null) {
Class<T> inlinedType = (Class<T>) pluginMap.getClassIfConfigured(matched);
assert inlinedType != null : "matched is always a key from the pluginMap's inlinedAliases set";
CodableClassInfo inlinedInfo = getOrCreateClassInfo(inlinedType);
ConfigObject aliasDefaults = pluginMap.aliasDefaults(matched);
ConfigValue configValue = configObject.get(matched);
String primaryField = (String) aliasDefaults.get("_primary").unwrapped();
ConfigObject fieldValues = configObject.withoutKey(matched).toConfig()
.withValue(primaryField, configValue).root()
.withFallback(aliasDefaults);
return createAndPopulate(inlinedInfo, inlinedType, fieldValues);
}
/* lastly, check for a _default type. */
Class<T> defaultType = (Class<T>) pluginMap.defaultSugar();
if (defaultType != null) {
CodableClassInfo defaultInfo = getOrCreateClassInfo(defaultType);
ConfigObject aliasDefaults = pluginMap.aliasDefaults("_default");
ConfigObject fieldValues = configObject.withFallback(aliasDefaults);
return createAndPopulate(defaultInfo, defaultType, fieldValues);
}