Invokers.java

1
package pro.verron.officestamper.core;
2
3
import org.springframework.core.convert.TypeDescriptor;
4
import org.springframework.expression.EvaluationContext;
5
import org.springframework.expression.MethodExecutor;
6
import org.springframework.expression.MethodResolver;
7
import org.springframework.lang.NonNull;
8
9
import java.util.ArrayDeque;
10
import java.util.ArrayList;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Map.Entry;
14
import java.util.stream.Stream;
15
16
import static java.util.Arrays.stream;
17
import static java.util.Collections.emptyMap;
18
import static java.util.stream.Collectors.groupingBy;
19
import static java.util.stream.Collectors.toMap;
20
21
/**
22
 * Resolves methods that are used as expression functions or comment processors.
23
 *
24
 * @author Joseph Verron
25
 * @version ${version}
26
 * @since 1.6.2
27
 */
28
public class Invokers
29
        implements MethodResolver {
30
    private final Map<String, Map<Args, MethodExecutor>> map;
31
32
    public Invokers(Stream<Invoker> invokerStream) {
33
        map = invokerStream.collect(groupingBy(
34
                Invoker::name,
35
                toMap(Invoker::args, Invoker::executor)
36
        ));
37
    }
38
39
    static Stream<Invoker> streamInvokers(Map<Class<?>, ?> interfaces2implementations) {
40 1 1. streamInvokers : replaced return value with Stream.empty for pro/verron/officestamper/core/Invokers::streamInvokers → KILLED
        return interfaces2implementations
41
                .entrySet()
42
                .stream()
43
                .flatMap(Invokers::streamInvokers);
44
    }
45
46
    private static Stream<Invoker> streamInvokers(Entry<Class<?>, ?> interface2implementation) {
47 1 1. streamInvokers : replaced return value with Stream.empty for pro/verron/officestamper/core/Invokers::streamInvokers → KILLED
        return streamInvokers(interface2implementation.getKey(), interface2implementation.getValue());
48
    }
49
50
    private static Stream<Invoker> streamInvokers(Class<?> key, Object obj) {
51 1 1. streamInvokers : replaced return value with Stream.empty for pro/verron/officestamper/core/Invokers::streamInvokers → KILLED
        return stream(key.getDeclaredMethods())
52 1 1. lambda$streamInvokers$0 : replaced return value with null for pro/verron/officestamper/core/Invokers::lambda$streamInvokers$0 → KILLED
                .map(method -> new Invoker(obj, method));
53
    }
54
55
    /** {@inheritDoc} */
56
    @Override
57
    public MethodExecutor resolve(
58
            @NonNull EvaluationContext context,
59
            @NonNull Object targetObject,
60
            @NonNull String name,
61
            @NonNull List<TypeDescriptor> argumentTypes
62
    ) {
63
        List<Class<?>> argumentClasses = new ArrayList<>();
64 1 1. resolve : removed call to java/util/List::forEach → KILLED
        argumentTypes.forEach(at -> argumentClasses.add(at.getType()));
65 1 1. resolve : replaced return value with null for pro/verron/officestamper/core/Invokers::resolve → KILLED
        return map.getOrDefault(name, emptyMap())
66
                  .entrySet()
67
                  .stream()
68 2 1. lambda$resolve$2 : replaced boolean return with true for pro/verron/officestamper/core/Invokers::lambda$resolve$2 → KILLED
2. lambda$resolve$2 : replaced boolean return with false for pro/verron/officestamper/core/Invokers::lambda$resolve$2 → KILLED
                  .filter(entry -> entry.getKey()
69
                                            .validate(argumentClasses))
70
                  .map(Entry::getValue)
71
                  .findFirst()
72
                  .orElse(null);
73
    }
74
75
    public record Args(List<Class<?>> sourceTypes) {
76
        public boolean validate(List<Class<?>> searchedTypes) {
77 1 1. validate : negated conditional → KILLED
            if (searchedTypes.size() != sourceTypes.size())
78 1 1. validate : replaced boolean return with true for pro/verron/officestamper/core/Invokers$Args::validate → KILLED
                return false;
79
80
            var sourceTypesQ = new ArrayDeque<>(sourceTypes);
81
            var searchedTypesQ = new ArrayDeque<>(searchedTypes);
82
            var valid = true;
83 2 1. validate : negated conditional → SURVIVED
2. validate : negated conditional → KILLED
            while (!sourceTypesQ.isEmpty() && valid) {
84
                Class<?> parameterType = sourceTypesQ.remove();
85
                Class<?> searchedType = searchedTypesQ.remove();
86
                valid = parameterType.isAssignableFrom(searchedType);
87
            }
88 2 1. validate : replaced boolean return with true for pro/verron/officestamper/core/Invokers$Args::validate → SURVIVED
2. validate : replaced boolean return with false for pro/verron/officestamper/core/Invokers$Args::validate → KILLED
            return valid;
89
        }
90
    }
91
}

Mutations

40

1.1
Location : streamInvokers
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
replaced return value with Stream.empty for pro/verron/officestamper/core/Invokers::streamInvokers → KILLED

47

1.1
Location : streamInvokers
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
replaced return value with Stream.empty for pro/verron/officestamper/core/Invokers::streamInvokers → KILLED

51

1.1
Location : streamInvokers
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
replaced return value with Stream.empty for pro/verron/officestamper/core/Invokers::streamInvokers → KILLED

52

1.1
Location : lambda$streamInvokers$0
Killed by : pro.verron.officestamper.test.DefaultTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DefaultTests]/[test-template:features(java.lang.String, pro.verron.officestamper.api.OfficeStamperConfiguration, java.lang.Object, java.io.InputStream, java.lang.String)]/[test-template-invocation:#34]
replaced return value with null for pro/verron/officestamper/core/Invokers::lambda$streamInvokers$0 → KILLED

64

1.1
Location : resolve
Killed by : pro.verron.officestamper.test.DefaultTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DefaultTests]/[test-template:features(java.lang.String, pro.verron.officestamper.api.OfficeStamperConfiguration, java.lang.Object, java.io.InputStream, java.lang.String)]/[test-template-invocation:#21]
removed call to java/util/List::forEach → KILLED

65

1.1
Location : resolve
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
replaced return value with null for pro/verron/officestamper/core/Invokers::resolve → KILLED

68

1.1
Location : lambda$resolve$2
Killed by : pro.verron.officestamper.test.DateFormatTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DateFormatTests]/[method:features()]
replaced boolean return with true for pro/verron/officestamper/core/Invokers::lambda$resolve$2 → KILLED

2.2
Location : lambda$resolve$2
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
replaced boolean return with false for pro/verron/officestamper/core/Invokers::lambda$resolve$2 → KILLED

77

1.1
Location : validate
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
negated conditional → KILLED

78

1.1
Location : validate
Killed by : pro.verron.officestamper.test.DateFormatTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.DateFormatTests]/[method:features()]
replaced boolean return with true for pro/verron/officestamper/core/Invokers$Args::validate → KILLED

83

1.1
Location : validate
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
negated conditional → KILLED

2.2
Location : validate
Killed by : none
negated conditional → SURVIVED
Covering tests

88

1.1
Location : validate
Killed by : none
replaced boolean return with true for pro/verron/officestamper/core/Invokers$Args::validate → SURVIVED
Covering tests

2.2
Location : validate
Killed by : pro.verron.officestamper.test.RegressionTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.RegressionTests]/[method:test64()]
replaced boolean return with false for pro/verron/officestamper/core/Invokers$Args::validate → KILLED

Active mutators

Tests examined


Report generated by PIT 1.17.0