private static void checkContainedValueTypes()

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