SearchUtils.java

1
package com.renomad.minum.utils;
2
3
import java.util.List;
4
import java.util.Objects;
5
import java.util.concurrent.Callable;
6
import java.util.function.Predicate;
7
import java.util.stream.Stream;
8
9
import static com.renomad.minum.utils.Invariants.mustBeTrue;
10
11
/**
12
 * Utilities for searching collections of data
13
 */
14
public final class SearchUtils {
15
16
    private SearchUtils() {
17
        // not meant to be instantiated
18
    }
19
20
    /**
21
     * This helper method will give you the one item in this list, or
22
     * null if there are none.  If there's more than 1, it will throw
23
     * an exception.  This is for those times when we absolutely expect
24
     * there to be just one of a thing in a database, like if we're searching
25
     * for Persons by id.
26
     * @param searchPredicate a {@link Predicate} run to search for an element in the stream.
27
     * @throws InvariantException if there are two or more results found
28
     */
29
    public static <T> T findExactlyOne(Stream<T> streamOfSomething, Predicate<? super T> searchPredicate) {
30 1 1. findExactlyOne : replaced return value with null for com/renomad/minum/utils/SearchUtils::findExactlyOne → KILLED
        return findExactlyOne(streamOfSomething, searchPredicate, () -> null);
31
    }
32
33
    /**
34
     * This is similar to {@link #findExactlyOne(Stream, Predicate)} except that you
35
     * can provide what gets returned if there are none found - so instead of
36
     * returning null, it can return something else.
37
     * <br>
38
     * The values will be pre-filtered to skip any null values.
39
     * <br>
40
     * @param alternate a {@link Callable} that will be run when no elements were found.
41
     * @param searchPredicate a {@link Predicate} run to search for an element in the stream.
42
     * @throws InvariantException if there are two or more results found
43
     */
44
    public static <T> T findExactlyOne(Stream<T> streamOfSomething, Predicate<? super T> searchPredicate, Callable<T> alternate) {
45
        List<T> listOfThings = streamOfSomething.filter(Objects::nonNull).filter(searchPredicate).toList();
46
        mustBeTrue(listOfThings.isEmpty() || listOfThings.size() == 1, "Must be zero or one of this thing, or it's a bug.  We found a size of " + listOfThings.size());
47 1 1. findExactlyOne : negated conditional → KILLED
        if (listOfThings.isEmpty()) {
48
            T returnValue;
49
            try {
50
                returnValue = alternate.call();
51
            } catch (Exception ex) {
52
                throw new UtilsException(ex);
53
            }
54 1 1. findExactlyOne : replaced return value with null for com/renomad/minum/utils/SearchUtils::findExactlyOne → KILLED
            return returnValue;
55
        } else {
56 1 1. findExactlyOne : replaced return value with null for com/renomad/minum/utils/SearchUtils::findExactlyOne → KILLED
            return listOfThings.getFirst();
57
        }
58
    }
59
}

Mutations

30

1.1
Location : findExactlyOne
Killed by : com.renomad.minum.utils.SearchUtilsTests.test_SearchUtils_NullInList(com.renomad.minum.utils.SearchUtilsTests)
replaced return value with null for com/renomad/minum/utils/SearchUtils::findExactlyOne → KILLED

47

1.1
Location : findExactlyOne
Killed by : com.renomad.minum.utils.SearchUtilsTests.test_SearchUtils_OneOrNone_SpecifyReturnValue(com.renomad.minum.utils.SearchUtilsTests)
negated conditional → KILLED

54

1.1
Location : findExactlyOne
Killed by : com.renomad.minum.utils.SearchUtilsTests.test_SearchUtils_OneOrNone_SpecifyReturnValue(com.renomad.minum.utils.SearchUtilsTests)
replaced return value with null for com/renomad/minum/utils/SearchUtils::findExactlyOne → KILLED

56

1.1
Location : findExactlyOne
Killed by : com.renomad.minum.utils.SearchUtilsTests.test_SearchUtils_NullInList(com.renomad.minum.utils.SearchUtilsTests)
replaced return value with null for com/renomad/minum/utils/SearchUtils::findExactlyOne → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0