Implementations.java

1
package io.github.gipo999.smispi;
2
3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.HashMap;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Optional;
9
import java.util.ServiceLoader;
10
import org.slf4j.Logger;
11
12
/** Utility class for loading implementations of services. */
13
public final class Implementations {
14
15
  /** The logger for this class. */
16
  private static final Logger LOGGER = SmiSpi.LOGGER;
17
18
  /** The cache for implementations. */
19
  private static final Map<String, List<PrioritizedService>> CACHE = new HashMap<>();
20
21
  /** The cache for implementations with parameters. */
22
  private static final Map<String, Map<String, List<PrioritizedService>>> PARAMS_CACHE =
23
      new HashMap<>();
24
25
  /** Prevents instantiation of this utility class. */
26
  private Implementations() {}
27
28
  /**
29
   * Returns the implementations of a service.
30
   *
31
   * @param clazz the class of the service
32
   * @param <T> the type of the service
33
   * @return the implementations of the service
34
   */
35
  public static <T extends PrioritizedService> List<T> of(Class<T> clazz) {
36 1 1. of : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED
    return of(clazz, null);
37
  }
38
39
  /**
40
   * Returns the implementations of a service.
41
   *
42
   * @param clazz the class of the service
43
   * @param filter the filter for the implementations
44
   * @param <T> the type of the service
45
   * @return the implementations of the service
46
   */
47
  public static <T extends PrioritizedService> List<T> of(
48
      Class<T> clazz, ImplementationsFilter filter) {
49 1 1. of : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED
    return of(clazz, filter, null);
50
  }
51
52
  /**
53
   * Returns the implementations of a service.
54
   *
55
   * @param clazz the class of the service
56
   * @param filter the filter for the implementations
57
   * @param params the parameters for the implementations
58
   * @param <T> the type of the service
59
   * @return the implementations of the service
60
   */
61
  @SuppressWarnings("unchecked")
62
  public static <T extends PrioritizedService> List<T> of(
63
      Class<T> clazz, ImplementationsFilter filter, ImplementationParams params) {
64
65
    Map<String, List<PrioritizedService>> cacheObject;
66
67
    String cacheKey;
68
69
    String className = getClassName(clazz);
70
71 1 1. of : negated conditional → KILLED
    if (params == null) {
72
      cacheObject = CACHE;
73
74
      cacheKey = className;
75
76
    } else {
77
78
      cacheKey = params.getCacheKey();
79
80 1 1. lambda$of$0 : replaced return value with Collections.emptyMap for io/github/gipo999/smispi/Implementations::lambda$of$0 → SURVIVED
      cacheObject = PARAMS_CACHE.computeIfAbsent(className, k -> new HashMap<>());
81
    }
82
83 1 1. of : negated conditional → KILLED
    if (cacheObject.containsKey(cacheKey)) {
84
85 1 1. of : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED
      return (List<T>) cacheObject.get(cacheKey);
86
    }
87
88
    List<T> selected = ofNew(clazz, filter, params);
89
90 1 1. of : negated conditional → KILLED
    if (!selected.isEmpty()) {
91
      cacheObject.put(cacheKey, (List<PrioritizedService>) selected);
92
    }
93
94 1 1. of : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED
    return selected;
95
  }
96
97
  /**
98
   * Returns the class name of a service.
99
   *
100
   * @param clazz the class of the service
101
   * @param <T> the type of the service
102
   * @return the class name of the service
103
   */
104
  static <T extends NamedService> String getClassName(Class<T> clazz) {
105
106 1 1. getClassName : replaced return value with "" for io/github/gipo999/smispi/Implementations::getClassName → KILLED
    return clazz.getCanonicalName();
107
  }
108
109
  /**
110
   * Returns the implementations of a service.
111
   *
112
   * @param clazz the class of the service
113
   * @param <T> the type of the service
114
   * @return the implementations of the service
115
   */
116
  public static <T extends PrioritizedService> List<T> ofNew(Class<T> clazz) {
117
118 1 1. ofNew : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::ofNew → KILLED
    return ofNew(clazz, null);
119
  }
120
121
  /**
122
   * Returns the implementations of a service.
123
   *
124
   * @param clazz the class of the service
125
   * @param filter the filter for the implementations
126
   * @param <T> the type of the service
127
   * @return the implementations of the service
128
   */
129
  public static <T extends PrioritizedService> List<T> ofNew(
130
      Class<T> clazz, ImplementationsFilter filter) {
131
132 1 1. ofNew : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::ofNew → KILLED
    return ofNew(clazz, filter, null);
133
  }
134
135
  /**
136
   * Returns the implementations of a service.
137
   *
138
   * @param clazz the class of the service
139
   * @param filter the filter for the implementations
140
   * @param params the parameters for the implementations
141
   * @param <T> the type of the service
142
   * @return the implementations of the service
143
   */
144
  public static <T extends PrioritizedService> List<T> ofNew(
145
      Class<T> clazz, ImplementationsFilter filter, ImplementationParams params) {
146
147
    List<T> list = loadList(clazz);
148
149
    List<T> selected;
150
151 2 1. ofNew : negated conditional → KILLED
2. ofNew : negated conditional → KILLED
    if (list.isEmpty() || filter == null) {
152
153
      selected = list;
154
155
    } else {
156
157
      selected =
158
          Collections.unmodifiableList(filter.filter(clazz, list, Optional.ofNullable(params)));
159
    }
160
161
    if (LOGGER.isDebugEnabled()) {
162
163 1 1. ofNew : negated conditional → NO_COVERAGE
      if (selected.isEmpty()) {
164
165
        LOGGER.warn("No implementation selected for : {}", getClassName(clazz));
166
167
      } else {
168
169
        LOGGER.debug("Filtered implementations are :");
170
171
        for (T impl : selected) {
172
173
          LOGGER.debug(
174
              "\t#{} {} : {}",
175
              impl.getPriority(),
176
              impl.getServiceImplementationName(),
177
              impl.getClass().getName());
178
        }
179
      }
180
    }
181
182 1 1. ofNew : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::ofNew → KILLED
    return selected;
183
  }
184
185
  /**
186
   * Loads the implementations of a service.
187
   *
188
   * @param clazz the class of the service
189
   * @param <T> the type of the service
190
   * @return the implementations of the service
191
   */
192
  private static <T extends PrioritizedService> List<T> loadList(Class<T> clazz) {
193
194
    if (LOGGER.isDebugEnabled()) {
195
      LOGGER.debug("Loading implementations for class <{}> :", getClassName(clazz));
196
    }
197
198
    final List<T> implementations = new ArrayList<>();
199
200
    final ServiceLoader<? extends T> implementationsLoader = ServiceLoader.load(clazz);
201
202
    for (T impl : implementationsLoader) {
203
      implementations.add(impl);
204
    }
205
206 1 1. loadList : removed call to java/util/Collections::sort → KILLED
    Collections.sort(implementations);
207
208
    if (LOGGER.isDebugEnabled()) {
209
210 1 1. loadList : negated conditional → NO_COVERAGE
      if (implementations.isEmpty()) {
211
212
        LOGGER.debug("\tNo implementations found.");
213
214
      } else {
215
216
        for (T impl : implementationsLoader) {
217
218
          LOGGER.debug(
219
              "\t#{} {} : {}",
220
              impl.getPriority(),
221
              impl.getServiceImplementationName(),
222
              impl.getClass().getName());
223
        }
224
      }
225
    }
226
227 1 1. loadList : replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::loadList → KILLED
    return Collections.unmodifiableList(implementations);
228
  }
229
}

Mutations

36

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testCustomOnlyWithCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED

49

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testCustomOnlyWithCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED

71

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testNoPresenceWithCache()]
negated conditional → KILLED

80

1.1
Location : lambda$of$0
Killed by : none
replaced return value with Collections.emptyMap for io/github/gipo999/smispi/Implementations::lambda$of$0 → SURVIVED

83

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testNoPresenceWithCache()]
negated conditional → KILLED

85

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testCustomOnlyWithCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED

90

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testEmptySelectorWithCache()]
negated conditional → KILLED

94

1.1
Location : of
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testEmptySelectorWithCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::of → KILLED

106

1.1
Location : getClassName
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testStandardOnlyWithCache()]
replaced return value with "" for io/github/gipo999/smispi/Implementations::getClassName → KILLED

118

1.1
Location : ofNew
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testStandardOnlyNoCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::ofNew → KILLED

132

1.1
Location : ofNew
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testStandardOnlyNoCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::ofNew → KILLED

151

1.1
Location : ofNew
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testEmptySelectorNoCache()]
negated conditional → KILLED

2.2
Location : ofNew
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testEmptySelectorNoCache()]
negated conditional → KILLED

163

1.1
Location : ofNew
Killed by : none
negated conditional → NO_COVERAGE

182

1.1
Location : ofNew
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testStandardOnlyNoCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::ofNew → KILLED

206

1.1
Location : loadList
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testEmptySelectorWithCache()]
removed call to java/util/Collections::sort → KILLED

210

1.1
Location : loadList
Killed by : none
negated conditional → NO_COVERAGE

227

1.1
Location : loadList
Killed by : io.github.gipo999.smispi.ImplementationsTest.[engine:junit-jupiter]/[class:io.github.gipo999.smispi.ImplementationsTest]/[method:testStandardOnlyNoCache()]
replaced return value with Collections.emptyList for io/github/gipo999/smispi/Implementations::loadList → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.2