private ApiError validateAlterConfig(ConfigResource configResource,
                                         List<ApiMessageAndVersion> recordsExplicitlyAltered,
                                         List<ApiMessageAndVersion> recordsImplicitlyDeleted,
                                         boolean newlyCreatedResource) {
        Map<String, String> allConfigs = new HashMap<>();
        Map<String, String> alteredConfigsForAlterConfigPolicyCheck = new HashMap<>();
        TimelineHashMap<String, String> existingConfigs = configData.get(configResource);
        if (existingConfigs != null) allConfigs.putAll(existingConfigs);
        for (ApiMessageAndVersion newRecord : recordsExplicitlyAltered) {
            ConfigRecord configRecord = (ConfigRecord) newRecord.message();
            if (configRecord.value() == null) {
                allConfigs.remove(configRecord.name());
            } else {
                allConfigs.put(configRecord.name(), configRecord.value());
            }
            alteredConfigsForAlterConfigPolicyCheck.put(configRecord.name(), configRecord.value());
        }
        for (ApiMessageAndVersion recordImplicitlyDeleted : recordsImplicitlyDeleted) {
            ConfigRecord configRecord = (ConfigRecord) recordImplicitlyDeleted.message();
            allConfigs.remove(configRecord.name());
            // As per KAFKA-14195, do not include implicit deletions caused by using the legacy AlterConfigs API
            // in the list passed to the policy in order to maintain backwards compatibility
        }
        try {
            validator.validate(configResource, allConfigs);
            if (!newlyCreatedResource) {
                existenceChecker.accept(configResource);
            }
            if (alterConfigPolicy.isPresent()) {
                alterConfigPolicy.get().validate(new RequestMetadata(configResource, alteredConfigsForAlterConfigPolicyCheck));
            }
        } catch (ConfigException e) {
            return new ApiError(INVALID_CONFIG, e.getMessage());
        } catch (Throwable e) {
            // return the corresponding API error, but emit the stack trace first if it is an unknown server error
            ApiError apiError = ApiError.fromThrowable(e);
            if (apiError.error() == Errors.UNKNOWN_SERVER_ERROR) {
                log.error("Unknown server error validating Alter Configs", e);
            }
            return apiError;
        }
        return ApiError.NONE;
    }
Determine the result of applying a batch of incremental configuration changes.  Note
that this method does not change the contents of memory.  It just generates a
result, that you can replay later if you wish using replay().

Note that there can only be one result per ConfigResource.  So if you try to modify
several keys and one modification fails, the whole ConfigKey fails and nothing gets
changed.

@param configChanges     Maps each resource to a map from config keys to
                         operation data.
@return                  The result.
metadata/src/main/java/org/apache/kafka/controller/ConfigurationControlManager.java