Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions src/main/java/io/skelp/verifier/type/StringVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,136 @@ public StringVerifier match(final Pattern pattern) {
return this;
}

/**
* <p>
* Verifies that the value matches <b>all</b> of the regular expressions provided.
* </p>
* <p>
* {@literal null} references are handled gracefully without exceptions.
* </p>
* <pre>
* Verifier.verify(*).matchAll() =&gt; PASS
* Verifier.verify(*).matchAll((CharSequence[]) null) =&gt; PASS
* Verifier.verify(*).matchAll(*, null) =&gt; FAIL
* Verifier.verify((String) null).matchAll(*) =&gt; FAIL
* Verifier.verify("foo").matchAll(".*", "fo{2}") =&gt; PASS
* Verifier.verify("foo").matchAll(".*", "fiz{2}") =&gt; FAIL
* </pre>
*
* @param regexes
* the regular expressions to be matched against of the value (may be {@literal null} or contain {@literal
* null} references)
* @return A reference to this {@link StringVerifier} for chaining purposes.
* @throws VerifierException
* If the verification fails while not negated or passes while negated.
* @see #matchAll(Pattern...)
*/
public StringVerifier matchAll(final CharSequence... regexes) {
final String value = verification().getValue();
final boolean result = value != null && matchAll(regexes, input -> input != null && value.matches(input.toString()));

verification().report(result, MessageKeys.MATCH_ALL, (Object) regexes);

return this;
}

/**
* <p>
* Verifies that the value matches <b>all</b> of the regular expression {@code patterns} provided.
* </p>
* <p>
* {@literal null} references are handled gracefully without exceptions.
* </p>
* <pre>
* Verifier.verify(*).matchAll() =&gt; PASS
* Verifier.verify(*).matchAll((Pattern[]) null) =&gt; PASS
* Verifier.verify(*).matchAll(*, null) =&gt; FAIL
* Verifier.verify((String) null).matchAll(*) =&gt; FAIL
* Verifier.verify("foo").matchAll(Pattern.compile(".*"), Pattern.compile("fo{2}")) =&gt; PASS
* Verifier.verify("foo").matchAll(Pattern.compile(".*"), Pattern.compile("fiz{2}")) =&gt; FAIL
* </pre>
*
* @param patterns
* the regular expression {@code Patterns} to be matched against of the value (may be {@literal null} or
* contain {@literal null} references)
* @return A reference to this {@link StringVerifier} for chaining purposes.
* @throws VerifierException
* If the verification fails while not negated or passes while negated.
* @see #matchAll(CharSequence...)
*/
public StringVerifier matchAll(final Pattern... patterns) {
final String value = verification().getValue();
final boolean result = value != null && matchAll(patterns, input -> input != null && input.matcher(value).matches());

verification().report(result, MessageKeys.MATCH_ALL, (Object) patterns);

return this;
}

/**
* <p>
* Verifies that the value matches <b>any</b> of the regular expressions provided.
* </p>
* <p>
* {@literal null} references are handled gracefully without exceptions.
* </p>
* <pre>
* Verifier.verify(*).matchAny() =&gt; FAIL
* Verifier.verify(*).matchAny((CharSequence[]) null) =&gt; FAIL
* Verifier.verify((String) null).matchAny(*) =&gt; FAIL
* Verifier.verify("foo").matchAny("fo{2}", "fiz{2}") =&gt; PASS
* Verifier.verify("foo").matchAny("fiz{2}", "buz{2}") =&gt; FAIL
* </pre>
*
* @param regexes
* the regular expressions to be matched against of the value (may be {@literal null} or contain {@literal
* null} references)
* @return A reference to this {@link StringVerifier} for chaining purposes.
* @throws VerifierException
* If the verification fails while not negated or passes while negated.
* @see #matchAny(Pattern...)
*/
public StringVerifier matchAny(final CharSequence... regexes) {
final String value = verification().getValue();
final boolean result = value != null && matchAny(regexes, input -> input != null && value.matches(input.toString()));

verification().report(result, MessageKeys.MATCH_ANY, (Object) regexes);

return this;
}

/**
* <p>
* Verifies that the value matches <b>any</b> of the regular expression {@code patterns} provided.
* </p>
* <p>
* {@literal null} references are handled gracefully without exceptions.
* </p>
* <pre>
* Verifier.verify(*).matchAny() =&gt; FAIL
* Verifier.verify(*).matchAny((Pattern[]) null) =&gt; FAIL
* Verifier.verify((String) null).matchAny(*) =&gt; FAIL
* Verifier.verify("foo").matchAny(Pattern.compile("fo{2}"), Pattern.compile("fiz{2}")) =&gt; PASS
* Verifier.verify("foo").matchAny(Pattern.compile("fiz{2}"), Pattern.compile("buz{2}")) =&gt; FAIL
* </pre>
*
* @param patterns
* the regular expression {@code Patterns} to be matched against of the value (may be {@literal null} or
* contain {@literal null} references)
* @return A reference to this {@link StringVerifier} for chaining purposes.
* @throws VerifierException
* If the verification fails while not negated or passes while negated.
* @see #matchAny(CharSequence...)
*/
public StringVerifier matchAny(final Pattern... patterns) {
final String value = verification().getValue();
final boolean result = value != null && matchAny(patterns, input -> input != null && input.matcher(value).matches());

verification().report(result, MessageKeys.MATCH_ANY, (Object) patterns);

return this;
}

/**
* <p>
* Verifies that the value contains only digits.
Expand Down Expand Up @@ -1096,6 +1226,8 @@ enum MessageKeys implements MessageKey {
EQUAL_TO_IGNORE_CASE("io.skelp.verifier.type.StringVerifier.equalToIgnoreCase"),
LOWER_CASE("io.skelp.verifier.type.StringVerifier.lowerCase"),
MATCH("io.skelp.verifier.type.StringVerifier.match"),
MATCH_ALL("io.skelp.verifier.type.StringVerifier.matchAll"),
MATCH_ANY("io.skelp.verifier.type.StringVerifier.matchAny"),
NUMERIC("io.skelp.verifier.type.StringVerifier.numeric"),
NUMERIC_SPACE("io.skelp.verifier.type.StringVerifier.numericSpace"),
SIZE_OF("io.skelp.verifier.type.StringVerifier.sizeOf"),
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/Verifier.properties
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ io.skelp.verifier.type.StringVerifier.equalToAnyIgnoreCase=be equal to any {0} (
io.skelp.verifier.type.StringVerifier.equalToIgnoreCase=be equal to ''{0}'' (ignore case)
io.skelp.verifier.type.StringVerifier.lowerCase=be all lower case
io.skelp.verifier.type.StringVerifier.match=match ''{0}''
io.skelp.verifier.type.StringVerifier.matchAll=match all {0}
io.skelp.verifier.type.StringVerifier.matchAny=match any {0}
io.skelp.verifier.type.StringVerifier.numeric=contain only digits
io.skelp.verifier.type.StringVerifier.numericSpace=contain only digits or space
io.skelp.verifier.type.StringVerifier.sizeOf=have a size of ''{0,number,integer}''
Expand Down
208 changes: 206 additions & 2 deletions src/test/java/io/skelp/verifier/type/StringVerifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,7 @@ public void testMatchWhenValueIsEmptyAndNotMatch() {
}

@Test
public void testMatchWhenValueIsEmptyAndNotMatchAndOtherIsCharSequence() {
public void testMatchWhenValueIsEmptyAndNotMatchAndRegexIsCharSequence() {
testMatchHelper(EMPTY, new StringWrapper("fo{2}"), false);
}

Expand All @@ -1511,7 +1511,7 @@ public void testMatchWhenValueIsMatch() {
}

@Test
public void testMatchWhenValueIsMatchAndOtherIsCharSequence() {
public void testMatchWhenValueIsMatchAndRegexIsCharSequence() {
testMatchHelper("foo", new StringWrapper("fo{2}"), true);
}

Expand All @@ -1535,6 +1535,122 @@ private void testMatchHelper(String value, CharSequence regex, boolean expected)
assertSame("Passes regex for message formatting", regex, getArgsCaptor().getValue());
}

@Test
public void testMatchAllWhenNoRegularExpressions() {
testMatchAllHelper("foo", createEmptyArray(CharSequence.class), true);
}

@Test
public void testMatchAllWhenRegularExpressionIsNull() {
testMatchAllHelper("foo", createArray((CharSequence) null), false);
}

@Test
public void testMatchAllWhenRegularExpressionsIsNull() {
testMatchAllHelper("foo", null, true);
}

@Test
public void testMatchAllWhenValueMatchesAllRegularExpressions() {
testMatchAllHelper("foo", createArray("fo{2}", ".*"), true);
}

@Test
public void testMatchAllWhenValueMatchesAllRegularExpressionsWhenNotCharSequences() {
testMatchAllHelper("foo", createArray(new StringWrapper("fo{2}"), new StringWrapper(".*")), true);
}

@Test
public void testMatchAllWhenValueMatchesSomeRegularExpressions() {
testMatchAllHelper("foo", createArray("fo{2}", "fiz{2}"), false);
}

@Test
public void testMatchAllWhenValueMatchesSomeRegularExpressionsWhenNotCharSequences() {
testMatchAllHelper("foo", createArray(new StringWrapper("fo{2}"), new StringWrapper("fiz{2}")), false);
}

@Test
public void testMatchAllWhenValueDoesNotMatchAnyRegularExpression() {
testMatchAllHelper("foo", createArray("fiz{2}", "buz{2}"), false);
}

@Test
public void testMatchAllWhenValueDoesNotMatchAnyRegularExpressionWhenNotCharSequences() {
testMatchAllHelper("foo", createArray(new StringWrapper("fiz{2}"), new StringWrapper("buz{2}")), false);
}

@Test
public void testMatchAllWhenValueIsNull() {
testMatchAllHelper(null, createArray(".*"), false);
}

private void testMatchAllHelper(String value, CharSequence[] regexes, boolean expected) {
setValue(value);

assertSame("Chains reference", getCustomVerifier(), getCustomVerifier().matchAll(regexes));

verify(getMockVerification()).report(expected, StringVerifier.MessageKeys.MATCH_ALL, (Object) regexes);
}

@Test
public void testMatchAnyWhenNoRegularExpressions() {
testMatchAnyHelper("foo", createEmptyArray(CharSequence.class), false);
}

@Test
public void testMatchAnyWhenRegularExpressionIsNull() {
testMatchAnyHelper("foo", createArray((CharSequence) null), false);
}

@Test
public void testMatchAnyWhenRegularExpressionsIsNull() {
testMatchAnyHelper("foo", null, false);
}

@Test
public void testMatchAnyWhenValueMatchesAllRegularExpressions() {
testMatchAnyHelper("foo", createArray("fo{2}", ".*"), true);
}

@Test
public void testMatchAnyWhenValueMatchesAllRegularExpressionsWhenNotCharSequences() {
testMatchAnyHelper("foo", createArray(new StringWrapper("fo{2}"), new StringWrapper(".*")), true);
}

@Test
public void testMatchAnyWhenValueMatchesSomeRegularExpressions() {
testMatchAnyHelper("foo", createArray("fo{2}", "fiz{2}"), true);
}

@Test
public void testMatchAnyWhenValueMatchesSomeRegularExpressionsWhenNotCharSequences() {
testMatchAnyHelper("foo", createArray(new StringWrapper("fo{2}"), new StringWrapper("fiz{2}")), true);
}

@Test
public void testMatchAnyWhenValueDoesNotMatchAnyRegularExpression() {
testMatchAnyHelper("foo", createArray("fiz{2}", "buz{2}"), false);
}

@Test
public void testMatchAnyWhenValueDoesNotMatchAnyRegularExpressionWhenNotCharSequences() {
testMatchAnyHelper("foo", createArray(new StringWrapper("fiz{2}"), new StringWrapper("buz{2}")), false);
}

@Test
public void testMatchAnyWhenValueIsNull() {
testMatchAnyHelper(null, createArray(".*"), false);
}

private void testMatchAnyHelper(String value, CharSequence[] regexes, boolean expected) {
setValue(value);

assertSame("Chains reference", getCustomVerifier(), getCustomVerifier().matchAny(regexes));

verify(getMockVerification()).report(expected, StringVerifier.MessageKeys.MATCH_ANY, (Object) regexes);
}

@Test
public void testMatchWithPatternWhenPatternIsNull() {
testMatchWithPatternHelper("foo", null, false);
Expand Down Expand Up @@ -1575,6 +1691,92 @@ private void testMatchWithPatternHelper(String value, Pattern pattern, boolean e
assertSame("Passes pattern for message formatting", pattern, getArgsCaptor().getValue());
}

@Test
public void testMatchAllWithPatternsWhenNoPatterns() {
testMatchAllWithPatternsHelper("foo", createEmptyArray(Pattern.class), true);
}

@Test
public void testMatchAllWithPatternsWhenPatternIsNull() {
testMatchAllWithPatternsHelper("foo", createArray((Pattern) null), false);
}

@Test
public void testMatchAllWithPatternsWhenPatternsIsNull() {
testMatchAllWithPatternsHelper("foo", null, true);
}

@Test
public void testMatchAllWithPatternsWhenValueMatchesAllPatterns() {
testMatchAllWithPatternsHelper("foo", createArray(Pattern.compile("fo{2}"), Pattern.compile(".*")), true);
}

@Test
public void testMatchAllWithPatternsWhenValueMatchesSomePatterns() {
testMatchAllWithPatternsHelper("foo", createArray(Pattern.compile("fo{2}"), Pattern.compile("fiz{2}")), false);
}

@Test
public void testMatchAllWithPatternsWhenValueDoesNotMatchAnyPattern() {
testMatchAllWithPatternsHelper("foo", createArray(Pattern.compile("fiz{2}"), Pattern.compile("buz{2}")), false);
}

@Test
public void testMatchAllWithPatternsWhenValueIsNull() {
testMatchAllWithPatternsHelper(null, createArray(Pattern.compile(".*")), false);
}

private void testMatchAllWithPatternsHelper(String value, Pattern[] patterns, boolean expected) {
setValue(value);

assertSame("Chains reference", getCustomVerifier(), getCustomVerifier().matchAll(patterns));

verify(getMockVerification()).report(expected, StringVerifier.MessageKeys.MATCH_ALL, (Object) patterns);
}

@Test
public void testMatchAnyWithPatternsWhenNoPatterns() {
testMatchAnyWithPatternsHelper("foo", createEmptyArray(Pattern.class), false);
}

@Test
public void testMatchAnyWithPatternsWhenPatternIsNull() {
testMatchAnyWithPatternsHelper("foo", createArray((Pattern) null), false);
}

@Test
public void testMatchAnyWithPatternsWhenPatternsIsNull() {
testMatchAnyWithPatternsHelper("foo", null, false);
}

@Test
public void testMatchAnyWithPatternsWhenValueMatchesAllPatterns() {
testMatchAnyWithPatternsHelper("foo", createArray(Pattern.compile("fo{2}"), Pattern.compile(".*")), true);
}

@Test
public void testMatchAnyWithPatternsWhenValueMatchesSomePatterns() {
testMatchAnyWithPatternsHelper("foo", createArray(Pattern.compile("fo{2}"), Pattern.compile("fiz{2}")), true);
}

@Test
public void testMatchAnyWithPatternsWhenValueDoesNotMatchAnyPattern() {
testMatchAnyWithPatternsHelper("foo", createArray(Pattern.compile("fiz{2}"), Pattern.compile("buz{2}")), false);
}

@Test
public void testMatchAnyWithPatternsWhenValueIsNull() {
testMatchAnyWithPatternsHelper(null, createArray(Pattern.compile(".*")), false);
}

private void testMatchAnyWithPatternsHelper(String value, Pattern[] patterns, boolean expected) {
setValue(value);

assertSame("Chains reference", getCustomVerifier(), getCustomVerifier().matchAny(patterns));

verify(getMockVerification()).report(expected, StringVerifier.MessageKeys.MATCH_ANY, (Object) patterns);
}

@Test
public void testNumericWhenValueIsEmpty() {
testNumericHelper(EMPTY, true);
Expand Down Expand Up @@ -2112,6 +2314,8 @@ protected Map<String, String> getMessageKeys() {
messageKeys.put("EQUAL_TO_IGNORE_CASE", "io.skelp.verifier.type.StringVerifier.equalToIgnoreCase");
messageKeys.put("LOWER_CASE", "io.skelp.verifier.type.StringVerifier.lowerCase");
messageKeys.put("MATCH", "io.skelp.verifier.type.StringVerifier.match");
messageKeys.put("MATCH_ALL", "io.skelp.verifier.type.StringVerifier.matchAll");
messageKeys.put("MATCH_ANY", "io.skelp.verifier.type.StringVerifier.matchAny");
messageKeys.put("NUMERIC", "io.skelp.verifier.type.StringVerifier.numeric");
messageKeys.put("NUMERIC_SPACE", "io.skelp.verifier.type.StringVerifier.numericSpace");
messageKeys.put("SIZE_OF", "io.skelp.verifier.type.StringVerifier.sizeOf");
Expand Down