Skip to content

Commit

Permalink
Introduce containsNoNullElements() in Preconditions
Browse files Browse the repository at this point in the history
Prior to this commit, precondition checks for "no null elements" were
supported by the existing notNull(Object[], String) and
notEmpty(Collection, String) methods. However, this functionality was
hidden behind misleading method names and implemented in a manner that
is inconsistent with similarly named methods in the Preconditions class.

This commit introduces dedicated containsNoNullElements() variants that
serve as a collective stepping stone for converting the Preconditions
API into a set of fine grained building blocks that enable the developer
to support more complex (i.e., composite) preconditions when necessary
while simultaneously avoiding the confusion associated with the status
quo for notNull(Object[], String) and notEmpty(Collection, String).

Issue: #496
  • Loading branch information
sbrannen committed Oct 5, 2016
1 parent f46640e commit d3bb779
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,8 @@ public static void assertAll(Stream<Executable> executables) throws MultipleFail
*/
@API(Experimental)
public static void assertAll(String heading, Executable... executables) throws MultipleFailuresError {
Preconditions.notNull(executables, "executables must not be null");
Preconditions.notNull(executables, "executables array must not be null");
Preconditions.containsNoNullElements(executables, "individual executables must not be null");
assertAll(heading, Arrays.stream(executables));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,11 @@ class Namespace {
*
* <p>The order of the {@code parts} is not significant.
*
* <p>Internally the {@code parts} are compared using {@code Object.equals(Object)}.
* <p>Internally the {@code parts} are compared using {@link Object#equals(Object)}.
*/
public static Namespace create(Object... parts) {
Preconditions.notNull(parts, "There must be at least one reference object to create a namespace");
Preconditions.notNull(parts, "parts array must not be null");
Preconditions.containsNoNullElements(parts, "individual parts must not be null");
return new Namespace(parts);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3342,7 +3342,7 @@ void assertAllWithNullInExecutableArray() {
// @formatter:on
}
catch (PreconditionViolationException ex) {
assertMessageEquals(ex, "executables must not be null");
assertMessageEquals(ex, "executables array must not be null");
}
}

Expand All @@ -3352,7 +3352,7 @@ void assertAllWithNullExecutableArray() {
assertAll((Executable[]) null);
}
catch (PreconditionViolationException ex) {
assertMessageEquals(ex, "executables must not be null");
assertMessageEquals(ex, "executables array must not be null");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ public static <T> T notNull(T object, Supplier<String> messageSupplier) throws P
public static Object[] notNull(Object[] objects, String message) throws PreconditionViolationException {
notNull(objects, () -> StringUtils.isNotBlank(message) ? message : "Object array must not be null");
Arrays.stream(objects).forEach(object -> notNull(object, () -> message));

return objects;
}

Expand All @@ -103,6 +102,47 @@ public static <T extends Collection<?>> T notEmpty(T collection, String message)
return collection;
}

/**
* Assert that the supplied array contains no {@code null} elements.
*
* <p><strong>WARNING</strong>: this method does NOT check if the supplied
* array is {@code null} or <em>empty</em>.
*
* @param array the array to check
* @param message precondition violation message
* @return the supplied array as a convenience
* @throws PreconditionViolationException if the supplied array contains
* any {@code null} elements
* @see #notNull(Object, Supplier)
*/
public static <T> T[] containsNoNullElements(T[] array, String message) throws PreconditionViolationException {
if (array != null) {
Arrays.stream(array).forEach(object -> notNull(object, () -> message));
}
return array;
}

/**
* Assert that the supplied collection contains no {@code null} elements.
*
* <p><strong>WARNING</strong>: this method does NOT check if the supplied
* collection is {@code null} or <em>empty</em>.
*
* @param collection the collection to check
* @param message precondition violation message
* @return the supplied collection as a convenience
* @throws PreconditionViolationException if the supplied collection contains
* any {@code null} elements
* @see #notNull(Object, Supplier)
*/
public static <T extends Collection<?>> T containsNoNullElements(T collection, String message)
throws PreconditionViolationException {
if (collection != null) {
collection.forEach(object -> notNull(object, () -> message));
}
return collection;
}

/**
* Assert that the supplied {@link String} is not blank.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ public static Class<?> getWrapperType(Class<?> type) {
*/
public static <T> T newInstance(Class<T> clazz, Object... args) {
Preconditions.notNull(clazz, "class must not be null");
Preconditions.notNull(args, "none of the arguments may be null");
Preconditions.notNull(args, "argument array must not be null");
Preconditions.containsNoNullElements(args, "individual arguments must not be null");

try {
Class<?>[] parameterTypes = Arrays.stream(args).map(Object::getClass).toArray(Class[]::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public interface Filter<T> {
@SafeVarargs
@SuppressWarnings("varargs")
static <T> Filter<T> composeFilters(Filter<T>... filters) {
Preconditions.notNull(filters, "Filters must not be null");
Preconditions.notNull(filters, "filters array must not be null");
Preconditions.containsNoNullElements(filters, "individual filters must not be null");

if (filters.length == 0) {
return alwaysIncluded();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ private TagFilter() {
* @param tags the included tags; never {@code null} or empty
*/
public static PostDiscoveryFilter includeTags(String... tags) {
Preconditions.notNull(tags, "tags must not be null");
Preconditions.notNull(tags, "tags array must not be null");
return includeTags(asList(tags));
}

Expand All @@ -59,7 +59,8 @@ public static PostDiscoveryFilter includeTags(String... tags) {
* @param tags the included tags; never {@code null} or empty
*/
public static PostDiscoveryFilter includeTags(List<String> tags) {
Preconditions.notEmpty(tags, "tags must not be null or empty");
Preconditions.notEmpty(tags, "tags list must not be null or empty");
Preconditions.containsNoNullElements(tags, "individual tags must not be null");
return descriptor -> FilterResult.includedIf(trimmedTagsOf(descriptor).anyMatch(tags::contains));
}

Expand All @@ -72,7 +73,7 @@ public static PostDiscoveryFilter includeTags(List<String> tags) {
* @param tags the excluded tags; never {@code null} or empty
*/
public static PostDiscoveryFilter excludeTags(String... tags) {
Preconditions.notNull(tags, "tags must not be null");
Preconditions.notNull(tags, "tags array must not be null");
return excludeTags(asList(tags));
}

Expand All @@ -85,7 +86,8 @@ public static PostDiscoveryFilter excludeTags(String... tags) {
* @param tags the excluded tags; never {@code null} or empty
*/
public static PostDiscoveryFilter excludeTags(List<String> tags) {
Preconditions.notEmpty(tags, "tags must not be null or empty");
Preconditions.notEmpty(tags, "tags list must not be null or empty");
Preconditions.containsNoNullElements(tags, "individual tags must not be null");
return descriptor -> FilterResult.includedIf(trimmedTagsOf(descriptor).noneMatch(tags::contains));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ private static Iterable<TestEngine> validateUniqueIds(Iterable<TestEngine> testE

@Override
public void registerTestExecutionListeners(TestExecutionListener... listeners) {
Preconditions.notNull(listeners, "listeners must not be null");
Preconditions.notNull(listeners, "listeners array must not be null");
Preconditions.containsNoNullElements(listeners, "individual listeners must not be null");
this.listenerRegistry.registerListeners(listeners);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -138,6 +139,53 @@ void notEmptyThrowsForCollectionWithNullElements() {
assertEquals(message, exception.getMessage());
}

@Test
void containsNoNullElementsPassesForArrayThatIsNullOrEmpty() {
containsNoNullElements((Object[]) null, "array is null");
containsNoNullElements(new Object[0], "array is empty");
}

@Test
void containsNoNullElementsPassesForCollectionThatIsNullOrEmpty() {
containsNoNullElements((List<?>) null, "collection is null");
containsNoNullElements(Collections.emptyList(), "collection is empty");
}

@Test
void containsNoNullElementsPassesForArrayContainingNonNullElements() {
String[] input = new String[] { "a", "b", "c" };
String[] output = containsNoNullElements(input, "message");
assertSame(input, output);
}

@Test
void containsNoNullElementsPassesForCollectionContainingNonNullElements() {
Collection<String> input = Arrays.asList("a", "b", "c");
Collection<String> output = containsNoNullElements(input, "message");
assertSame(input, output);
}

@Test
void containsNoNullElementsThrowsForArrayContainingNullElements() {
String message = "array contains null elements";
Object[] array = { new Object(), null, new Object() };

PreconditionViolationException exception = assertThrows(PreconditionViolationException.class,
() -> containsNoNullElements(array, message));

assertEquals(message, exception.getMessage());
}

@Test
void containsNoNullElementsThrowsForCollectionContainingNullElements() {
String message = "collection contains null elements";

PreconditionViolationException exception = assertThrows(PreconditionViolationException.class,
() -> containsNoNullElements(Collections.singletonList(null), message));

assertEquals(message, exception.getMessage());
}

@Test
void notBlankPassesForNonBlankString() {
String string = "abc";
Expand Down

0 comments on commit d3bb779

Please sign in to comment.