public Map<String, ConfigValue> validateAll(Map<String, String> props) { Map<String, ConfigValue> configValues = new HashMap<>(); for (String name: configKeys.keySet()) { configValues.put(name, new ConfigValue(name)); } List<String> undefinedConfigKeys = undefinedDependentConfigs(); for (String undefinedConfigKey: undefinedConfigKeys) { ConfigValue undefinedConfigValue = new ConfigValue(undefinedConfigKey); undefinedConfigValue.addErrorMessage(undefinedConfigKey + " is referred in the dependents, but not defined."); undefinedConfigValue.visible(false); configValues.put(undefinedConfigKey, undefinedConfigValue); } Map<String, Object> parsed = parseForValidate(props, configValues); return validate(parsed, configValues); }
@Test public void testValidateCannotParse() { Map<String, ConfigValue> expected = new HashMap<>(); String errorMessageB = "Invalid value non_integer for configuration a: Not a number of type INT"; ConfigValue configA = new ConfigValue("a", null, Collections.emptyList(), Arrays.asList(errorMessageB)); expected.put("a", configA); ConfigDef def = new ConfigDef().define("a", Type.INT, Importance.HIGH, "docs"); Map<String, String> props = new HashMap<>(); props.put("a", "non_integer"); List<ConfigValue> configs = def.validate(props); for (ConfigValue config: configs) { String name = config.name(); ConfigValue expectedConfig = expected.get(name); assertEquals(expectedConfig, config); } }
@Test public void testValidate() { Map<String, ConfigValue> expected = new HashMap<>(); String errorMessageB = "Missing required configuration \"b\" which has no default value."; String errorMessageC = "Missing required configuration \"c\" which has no default value."; ConfigValue configA = new ConfigValue("a", 1, Arrays.<Object>asList(1, 2, 3), Collections.<String>emptyList()); ConfigValue configB = new ConfigValue("b", null, Arrays.<Object>asList(4, 5), Arrays.asList(errorMessageB, errorMessageB)); ConfigValue configC = new ConfigValue("c", null, Arrays.<Object>asList(4, 5), Arrays.asList(errorMessageC)); ConfigValue configD = new ConfigValue("d", 10, Arrays.<Object>asList(1, 2, 3), Collections.<String>emptyList()); expected.put("a", configA); expected.put("b", configB); expected.put("c", configC); expected.put("d", configD); ConfigDef def = new ConfigDef() .define("a", Type.INT, Importance.HIGH, "docs", "group", 1, Width.SHORT, "a", Arrays.asList("b", "c"), new IntegerRecommender(false)) .define("b", Type.INT, Importance.HIGH, "docs", "group", 2, Width.SHORT, "b", new IntegerRecommender(true)) .define("c", Type.INT, Importance.HIGH, "docs", "group", 3, Width.SHORT, "c", new IntegerRecommender(true)) .define("d", Type.INT, Importance.HIGH, "docs", "group", 4, Width.SHORT, "d", Arrays.asList("b"), new IntegerRecommender(false)); Map<String, String> props = new HashMap<>(); props.put("a", "1"); props.put("d", "10"); List<ConfigValue> configs = def.validate(props); for (ConfigValue config : configs) { String name = config.name(); ConfigValue expectedConfig = expected.get(name); assertEquals(expectedConfig, config); } }
/** * Validate the supplied fields in this configuration. Extra fields not described by the supplied {@code fields} parameter * are not validated. * * @param fields the fields * @return the {@link ConfigValue} for each of the fields; never null */ default Map<String, ConfigValue> validate(Field.Set fields) { // Create a map of configuration values for each field ... Map<String, ConfigValue> configValuesByFieldName = new HashMap<>(); fields.forEach(field -> { configValuesByFieldName.put(field.name(), new ConfigValue(field.name())); }); // If any dependents don't exist ... fields.forEachMissingDependent(missingDepedent -> { ConfigValue undefinedConfigValue = new ConfigValue(missingDepedent); undefinedConfigValue.addErrorMessage(missingDepedent + " is referred in the dependents, but not defined."); undefinedConfigValue.visible(false); configValuesByFieldName.put(missingDepedent, undefinedConfigValue); }); // Now validate each top-level field ... fields.forEachTopLevelField(field -> { field.validate(this, fields::fieldWithName, configValuesByFieldName); }); return configValuesByFieldName; }
@Test public void testValidateMissingConfigKey() { Map<String, ConfigValue> expected = new HashMap<>(); String errorMessageB = "Missing required configuration \"b\" which has no default value."; String errorMessageC = "Missing required configuration \"c\" which has no default value."; String errorMessageD = "d is referred in the dependents, but not defined."; ConfigValue configA = new ConfigValue("a", 1, Arrays.<Object>asList(1, 2, 3), Collections.<String>emptyList()); ConfigValue configB = new ConfigValue("b", null, Arrays.<Object>asList(4, 5), Arrays.asList(errorMessageB)); ConfigValue configC = new ConfigValue("c", null, Arrays.<Object>asList(4, 5), Arrays.asList(errorMessageC)); ConfigValue configD = new ConfigValue("d", null, Collections.emptyList(), Arrays.asList(errorMessageD)); configD.visible(false); expected.put("a", configA); expected.put("b", configB); expected.put("c", configC); expected.put("d", configD); ConfigDef def = new ConfigDef() .define("a", Type.INT, Importance.HIGH, "docs", "group", 1, Width.SHORT, "a", Arrays.asList("b", "c", "d"), new IntegerRecommender(false)) .define("b", Type.INT, Importance.HIGH, "docs", "group", 2, Width.SHORT, "b", new IntegerRecommender(true)) .define("c", Type.INT, Importance.HIGH, "docs", "group", 3, Width.SHORT, "c", new IntegerRecommender(true)); Map<String, String> props = new HashMap<>(); props.put("a", "1"); List<ConfigValue> configs = def.validate(props); for (ConfigValue config: configs) { String name = config.name(); ConfigValue expectedConfig = expected.get(name); assertEquals(expectedConfig, config); } }
String errorMessageB = "Missing required configuration \"b\" which has no default value."; String errorMessageC = "Missing required configuration \"c\" which has no default value."; ConfigValue configA = new ConfigValue("a", 1, Collections.<Object>emptyList(), Collections.<String>emptyList()); ConfigValue configB = new ConfigValue("b", null, Collections.<Object>emptyList(), Arrays.asList(errorMessageB, errorMessageB)); ConfigValue configC = new ConfigValue("c", null, Collections.<Object>emptyList(), Arrays.asList(errorMessageC)); ConfigValue configD = new ConfigValue("d", 10, Collections.<Object>emptyList(), Collections.<String>emptyList()); expected.put("a", configA); expected.put("b", configB); configValues.put(name, new ConfigValue(name));
ConfigValue value = results.computeIfAbsent(this.name(), n -> new ConfigValue(n));
/** * Validate the supplied fields in this configuration. Extra fields not described by the supplied {@code fields} parameter * are not validated. * * @param fields the fields * @return the {@link ConfigValue} for each of the fields; never null */ default Map<String, ConfigValue> validate(Field.Set fields) { // Create a map of configuration values for each field ... Map<String, ConfigValue> configValuesByFieldName = new HashMap<>(); fields.forEach(field -> { configValuesByFieldName.put(field.name(), new ConfigValue(field.name())); }); // If any dependents don't exist ... fields.forEachMissingDependent(missingDepedent -> { ConfigValue undefinedConfigValue = new ConfigValue(missingDepedent); undefinedConfigValue.addErrorMessage(missingDepedent + " is referred in the dependents, but not defined."); undefinedConfigValue.visible(false); configValuesByFieldName.put(missingDepedent, undefinedConfigValue); }); // Now validate each top-level field ... fields.forEachTopLevelField(field -> { field.validate(this, fields::fieldWithName, configValuesByFieldName); }); return configValuesByFieldName; }
ConfigValue value = results.computeIfAbsent(this.name(), n -> new ConfigValue(n));