in freemarker-docgen-core/src/main/java/org/freemarker/docgen/core/SettingUtils.java [135:212]
private static void checkContainedValueTypes(
SettingName settingName, Object containerValue,
List<Object> checkedContainedSettingNameTail, ContainedValueType... containedValueTypes) {
if (checkedContainedSettingNameTail.size() == containedValueTypes.length || containerValue == null) {
return;
}
Class<? extends Object> containerClass = containerValue.getClass();
ContainedValueType containedValueType = containedValueTypes[checkedContainedSettingNameTail.size()];
checkContainerClassIsValidContainedValueType(containerClass, containedValueType);
if (containedValueType instanceof ListItemType) {
int listElementIndex = 0;
for (Object listElement : ((List<?>) containerValue)) {
if (listElement == null) {
if (!containedValueType.allowNullValue) {
throw newNullSettingValueException(
settingName.subKey(checkedContainedSettingNameTail).subKey(listElementIndex));
}
} else if (!containedValueType.valueType.isInstance(listElement)) {
throw newBadSettingValueTypeException(
settingName.subKey(checkedContainedSettingNameTail).subKey(listElementIndex),
containedValueType.valueType, listElement);
}
checkedContainedSettingNameTail.add(listElementIndex);
try {
checkContainedValueTypes(
settingName, listElement, checkedContainedSettingNameTail,
containedValueTypes);
} finally {
checkedContainedSettingNameTail.remove(checkedContainedSettingNameTail.size() - 1);
}
listElementIndex++;
}
} else if (containedValueType instanceof MapEntryType) {
MapEntryType mapEntryType = (MapEntryType) containedValueType;
for (Map.Entry<?, ?> mapEntry : ((Map<?, ?>) containerValue).entrySet()) {
Object entryKey = mapEntry.getKey();
if (entryKey == null) {
throw newCfgFileException(
settingName, "Null keys aren't allowed in this setting value.");
}
Class<?> keyType = mapEntryType.keyType;
if (!keyType.isInstance(entryKey)) {
throw newCfgFileException(
settingName.subKey(checkedContainedSettingNameTail), // Don't add the key.
"Expected key type " + CJSONInterpreter.cjsonTypeNameForClass(keyType)
+ ", but key was of type " + CJSONInterpreter.cjsonTypeNameOfValue(entryKey));
}
Object entryValue = mapEntry.getValue();
if (entryValue == null) {
if (!containedValueType.allowNullValue) {
throw newNullSettingValueException(
settingName.subKey(checkedContainedSettingNameTail).subKey(entryKey));
}
} else if (!containedValueType.valueType.isInstance(entryValue)) {
throw newBadSettingValueTypeException(
settingName.subKey(checkedContainedSettingNameTail).subKey(entryKey),
containedValueType.valueType, entryValue);
}
checkedContainedSettingNameTail.add(entryKey);
try {
checkContainedValueTypes(
settingName, entryValue, checkedContainedSettingNameTail,
containedValueTypes);
} finally {
checkedContainedSettingNameTail.remove(checkedContainedSettingNameTail.size() - 1);
}
}
if (mapEntryType.validateKeys) {
checkMapKeys(settingName, (Map) containerValue, mapEntryType.requiredKeys, mapEntryType.optionalKeys);
}
} else {
throw new AssertionError();
}
}