mirror of https://github.com/apache/nifi.git
add validator for lists that ensure the element validator is called for empty entries
Signed-off-by: Matthew Burgess <mattyb149@apache.org> This closes #4116
This commit is contained in:
parent
4a2a91135e
commit
d9ac9e44a7
|
@ -566,7 +566,14 @@ public class StandardValidators {
|
|||
};
|
||||
}
|
||||
|
||||
public static Validator createListValidator(boolean trimEntries, boolean excludeEmptyEntries, Validator validator) {
|
||||
public static Validator createListValidator(boolean trimEntries, boolean excludeEmptyEntries,
|
||||
Validator elementValidator){
|
||||
return createListValidator(trimEntries,excludeEmptyEntries, elementValidator, false);
|
||||
}
|
||||
|
||||
public static Validator createListValidator(boolean trimEntries, boolean excludeEmptyEntries,
|
||||
Validator validator,
|
||||
boolean ensureElementValidation) {
|
||||
return (subject, input, context) -> {
|
||||
if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) {
|
||||
return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build();
|
||||
|
@ -576,7 +583,7 @@ public class StandardValidators {
|
|||
return new ValidationResult.Builder().subject(subject).input(null).explanation("List must have at least one non-empty element").valid(false).build();
|
||||
}
|
||||
|
||||
final String[] list = input.split(",");
|
||||
final String[] list = ensureElementValidation ? input.split(",",-1) : input.split(",");
|
||||
if (list.length == 0) {
|
||||
return new ValidationResult.Builder().subject(subject).input(null).explanation("List must have at least one non-empty element").valid(false).build();
|
||||
}
|
||||
|
|
|
@ -309,6 +309,157 @@ public class TestStandardValidators {
|
|||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testListValidatorEnsuringElementValidation() {
|
||||
// use the TestMockValidator to be sure the item validator get's called when we think it should
|
||||
// note that it will reset the count after every get call.
|
||||
// note that we fail fast, so if there are 3 items, and the second fails validation, the call
|
||||
// count will be 2
|
||||
InstrumentedStandardValidator mockValidator = new InstrumentedStandardValidator(StandardValidators.NON_EMPTY_VALIDATOR, true);
|
||||
Validator val = StandardValidators.createListValidator(true, false, mockValidator, true);
|
||||
ValidationResult vr;
|
||||
|
||||
final ValidationContext validationContext = Mockito.mock(ValidationContext.class);
|
||||
|
||||
vr = val.validate("List", null, validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(0, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
// Whitespace will be trimmed
|
||||
vr = val.validate("List", " ", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
// An empty list is the same as null, "" or " "
|
||||
vr = val.validate("List", ",", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", " , ", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
// will evaluate to no entry
|
||||
vr = val.validate("List", ",,,,", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
// will evaluate to an empty element
|
||||
vr = val.validate("List", ",foo", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "1", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "1,2,3", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(3, mockValidator.getValidateCallCount());
|
||||
|
||||
// The parser will bother with whitespace after the last comma, as we ensure the inner validator is called
|
||||
vr = val.validate("List", "a,", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
|
||||
// However it will bother if there is an empty element in the list (two commas in a row, e.g.)
|
||||
vr = val.validate("List", "a,,c", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "a, ,c, ", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
|
||||
// Try without trim and use a non-blank validator instead of a non-empty one
|
||||
//
|
||||
// use the TestMockValidator to be sure the item validator get's called when we think it should
|
||||
// note that it will reset the count after every get call.
|
||||
// note that we fail fast, so if there are 3 items, and the second fails validation, the call
|
||||
// count will be 2
|
||||
mockValidator = new InstrumentedStandardValidator(StandardValidators.NON_BLANK_VALIDATOR, true);
|
||||
val = StandardValidators.createListValidator(false, true, mockValidator);
|
||||
|
||||
vr = val.validate("List", null, validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(0, mockValidator.getValidateCallCount());
|
||||
|
||||
// List Validator will ignore empty entries
|
||||
vr = val.validate("List", "", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(0, mockValidator.getValidateCallCount());
|
||||
|
||||
// Whitespace will not be trimmed, but it is still invalid because a non-blank validator is used
|
||||
vr = val.validate("List", " ", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "a,,c", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "a, ,c, ", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
|
||||
// Try without trim and use a non-empty validator
|
||||
// use the TestMockValidator to be sure the item validator get's called when we think it should
|
||||
// note that it will reset the count after every get call.
|
||||
// note that we fail fast, so if there are 3 items, and the second fails validation, the call
|
||||
// count will be 2
|
||||
mockValidator = new InstrumentedStandardValidator(StandardValidators.NON_EMPTY_VALIDATOR, true);
|
||||
val = StandardValidators.createListValidator(false, false, mockValidator);
|
||||
|
||||
vr = val.validate("List", null, validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(0, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
// Whitespace will not be trimmed
|
||||
vr = val.validate("List", " ", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "a, ,c, ", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(4, mockValidator.getValidateCallCount());
|
||||
|
||||
// Try with trim and use a boolean validator // Try without trim and use a non-empty validator
|
||||
// use the TestMockValidator to be sure the item validator get's called when we think it should
|
||||
// note that it will reset the count after every get call.
|
||||
// note that we fail fast, so if there are 3 items, and the second fails validation, the call
|
||||
// count will be 2
|
||||
mockValidator = new InstrumentedStandardValidator(StandardValidators.BOOLEAN_VALIDATOR, true);
|
||||
val = StandardValidators.createListValidator(true, true, mockValidator);
|
||||
vr = val.validate("List", "notbool", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", " notbool \n ", validationContext);
|
||||
assertFalse(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", "true", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", " true \n ", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(1, mockValidator.getValidateCallCount());
|
||||
|
||||
vr = val.validate("List", " , false, true,\n", validationContext);
|
||||
assertTrue(vr.isValid());
|
||||
assertEquals(2, mockValidator.getValidateCallCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateURLorFileValidator() {
|
||||
Validator val = StandardValidators.createURLorFileValidator();
|
||||
|
|
Loading…
Reference in New Issue