ImplementationFinder.java

1
package fr.sii.ogham.testing.assertion.internal.helper;
2
3
import static org.apache.commons.lang3.reflect.FieldUtils.readField;
4
5
import java.util.HashSet;
6
import java.util.List;
7
import java.util.Set;
8
9
import fr.sii.ogham.core.message.Message;
10
import fr.sii.ogham.core.sender.ConditionalSender;
11
import fr.sii.ogham.core.sender.ContentTranslatorSender;
12
import fr.sii.ogham.core.sender.MessageSender;
13
import fr.sii.ogham.core.sender.MultiImplementationSender;
14
import fr.sii.ogham.core.sender.MultiImplementationSender.Implementation;
15
import fr.sii.ogham.core.service.CleanableMessagingService;
16
import fr.sii.ogham.core.service.EverySupportingMessagingService;
17
import fr.sii.ogham.core.service.MessagingService;
18
import fr.sii.ogham.core.service.WrapExceptionMessagingService;
19
import fr.sii.ogham.core.template.parser.AutoDetectTemplateParser;
20
import fr.sii.ogham.core.template.parser.TemplateParser;
21
import fr.sii.ogham.core.template.parser.AutoDetectTemplateParser.TemplateImplementation;
22
import fr.sii.ogham.core.translator.content.ContentTranslator;
23
import fr.sii.ogham.core.translator.content.EveryContentTranslator;
24
import fr.sii.ogham.core.translator.content.MultiContentTranslator;
25
import fr.sii.ogham.core.translator.content.TemplateContentTranslator;
26
import fr.sii.ogham.email.message.Email;
27
import fr.sii.ogham.email.sender.EmailSender;
28
import fr.sii.ogham.sms.message.Sms;
29
import fr.sii.ogham.sms.sender.SmsSender;
30
31
/**
32
 * Utility class to find implementations used by Ogham service.
33
 * 
34
 * @author Aurélien Baudet
35
 *
36
 */
37
public final class ImplementationFinder {
38
	private static final String DELEGATE_FIELD = "delegate";
39
40
	/**
41
	 * Find recursively a finder of the provided class
42
	 * 
43
	 * @param <T>
44
	 *            the type of the found sender
45
	 * @param service
46
	 *            the messaging service
47
	 * @param clazz
48
	 *            the class of the sender to find
49
	 * @return the found sender
50
	 */
51
	public static <T extends MessageSender> T findSender(MessagingService service, Class<T> clazz) {
52
		Set<T> found = findSenders(service, clazz);
53 1 1. findSender : negated conditional → RUN_ERROR
		if (found.isEmpty()) {
54
			throw new IllegalStateException("Failed to find MessageSender of " + clazz.getTypeName());
55
		}
56 1 1. findSender : negated conditional → RUN_ERROR
		if (found.size() == 1) {
57 1 1. findSender : replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSender → RUN_ERROR
			return found.iterator().next();
58
		}
59
		throw new IllegalStateException("Several matching MessageSender for " + clazz.getTypeName() + " found");
60
	}
61
62
	/**
63
	 * Find all senders for the given type
64
	 * 
65
	 * @param <T>
66
	 *            the type of the senders to find
67
	 * @param service
68
	 *            the messaging service
69
	 * @param clazz
70
	 *            the class of the senders to find
71
	 * @return the found senders
72
	 */
73
	@SuppressWarnings("unchecked")
74
	public static <T extends MessageSender> Set<T> findSenders(MessagingService service, Class<T> clazz) {
75
		try {
76
			Set<T> found = new HashSet<>();
77
			List<ConditionalSender> senders = (List<ConditionalSender>) readField(getRealService(service), "senders", true);
78
			for (ConditionalSender sender : senders) {
79
				found.addAll(findSenders(sender, clazz));
80
			}
81 1 1. findSenders : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSenders → RUN_ERROR
			return found;
82
		} catch (IllegalAccessException e) {
83
			throw new IllegalStateException("Failed to find senders of type " + clazz.getTypeName(), e);
84
		}
85
	}
86
87
	/**
88
	 * Find template parsers of the given type.
89
	 * 
90
	 * @param <T>
91
	 *            the type of the template parsers to find
92
	 * @param service
93
	 *            the messaging service
94
	 * @param clazz
95
	 *            the class of the template parsers to find
96
	 * @return the found parsers
97
	 */
98
	public static <T extends TemplateParser> Set<FoundParser<T>> findParsers(MessagingService service, Class<T> clazz) {
99
		try {
100
			Set<FoundParser<T>> found = new HashSet<>();
101
			Set<ContentTranslatorSender> translatorSenders = findSenders(service, ContentTranslatorSender.class);
102
			for (ContentTranslatorSender sender : translatorSenders) {
103
				Set<TemplateContentTranslator> translators = findTranslators(sender, TemplateContentTranslator.class);
104
				for (TemplateContentTranslator translator : translators) {
105
					found.addAll(findParsers(clazz, translator, (MessageSender) readField(sender, DELEGATE_FIELD, true)));
106
				}
107
			}
108 1 1. findParsers : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findParsers → RUN_ERROR
			return found;
109
		} catch (IllegalAccessException e) {
110
			throw new IllegalStateException("Failed to find parser of type " + clazz.getTypeName(), e);
111
		}
112
	}
113
114
	private static MessagingService getRealService(MessagingService service) {
115
		try {
116 1 1. getRealService : negated conditional → RUN_ERROR
			if (service instanceof WrapExceptionMessagingService) {
117 1 1. getRealService : replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getRealService → RUN_ERROR
				return getRealService((MessagingService) readField(service, DELEGATE_FIELD, true));
118
			}
119 1 1. getRealService : negated conditional → RUN_ERROR
			if (service instanceof CleanableMessagingService) {
120 1 1. getRealService : replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getRealService → RUN_ERROR
				return getRealService((MessagingService) readField(service, DELEGATE_FIELD, true));
121
			}
122 1 1. getRealService : negated conditional → RUN_ERROR
			if (service instanceof EverySupportingMessagingService) {
123 1 1. getRealService : replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getRealService → RUN_ERROR
				return service;
124
			}
125
			throw new IllegalStateException("Unknown MessagingService implementation, please add it here");
126
		} catch (IllegalAccessException e) {
127
			throw new IllegalStateException("Failed to find real MessagingService", e);
128
		}
129
	}
130
131
	@SuppressWarnings("unchecked")
132
	private static <T extends MessageSender> Set<T> findSenders(MessageSender sender, Class<T> clazz) {
133
		try {
134
			Set<T> found = new HashSet<>();
135 1 1. findSenders : negated conditional → RUN_ERROR
			if (clazz.isAssignableFrom(sender.getClass())) {
136
				found.add((T) sender);
137
			}
138
			// Any sender that delegates in the chain (FillerSender,
139
			// AttachmentResourceTranslatorSender, ContentTranslatorSender,
140
			// PhoneNumberTranslatorSender)
141
			// TODO: FallbackSender
142 1 1. findSenders : negated conditional → RUN_ERROR
			if (delegates(sender)) {
143
				MessageSender delegate = (MessageSender) readField(sender, DELEGATE_FIELD, true);
144
				found.addAll(findSenders(delegate, clazz));
145
			}
146 1 1. findSenders : negated conditional → RUN_ERROR
			if (sender instanceof MultiImplementationSender<?>) {
147
				found.addAll(findSenders((MultiImplementationSender<?>) sender, clazz));
148
			}
149 1 1. findSenders : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSenders → RUN_ERROR
			return found;
150
		} catch (IllegalAccessException e) {
151
			throw new IllegalStateException("Failed to find senders of type " + clazz.getTypeName(), e);
152
		}
153
	}
154
155
	private static boolean delegates(MessageSender sender) {
156
		try {
157
			Object value = readField(sender, DELEGATE_FIELD, true);
158 2 1. delegates : replaced boolean return with true for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::delegates → RUN_ERROR
2. delegates : replaced boolean return with false for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::delegates → RUN_ERROR
			return value instanceof MessageSender;
159
		} catch (IllegalAccessException | IllegalArgumentException e) { // NOSONAR
160 1 1. delegates : replaced boolean return with true for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::delegates → RUN_ERROR
			return false;
161
		}
162
	}
163
164
	@SuppressWarnings("unchecked")
165
	private static <T extends MessageSender> Set<T> findSenders(MultiImplementationSender<?> sender, Class<T> clazz) {
166
		Set<T> found = new HashSet<>();
167
		List<Implementation> implementations = sender.getImplementations();
168
		for (Implementation impl : implementations) {
169 1 1. findSenders : negated conditional → RUN_ERROR
			if (clazz.isAssignableFrom(impl.getSender().getClass())) {
170
				found.add((T) impl.getSender());
171
			}
172
		}
173 1 1. findSenders : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSenders → RUN_ERROR
		return found;
174
	}
175
176
	@SuppressWarnings("unchecked")
177
	private static <T extends TemplateParser> Set<FoundParser<T>> findParsers(Class<T> clazz, TemplateContentTranslator translator, MessageSender sender) throws IllegalAccessException {
178
		Set<FoundParser<T>> found = new HashSet<>();
179
		TemplateParser parser = (TemplateParser) readField(translator, "parser", true);
180 1 1. findParsers : negated conditional → RUN_ERROR
		if (clazz.isAssignableFrom(parser.getClass())) {
181
			found.add(new FoundParser<>((T) parser, getMessageType(sender)));
182
		}
183 1 1. findParsers : negated conditional → RUN_ERROR
		if (parser instanceof AutoDetectTemplateParser) {
184
			found.addAll(findParsers(clazz, (AutoDetectTemplateParser) parser, sender));
185
		}
186 1 1. findParsers : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findParsers → RUN_ERROR
		return found;
187
	}
188
189
	@SuppressWarnings("unchecked")
190
	private static <T extends TemplateParser> Set<FoundParser<T>> findParsers(Class<T> clazz, AutoDetectTemplateParser parser, MessageSender sender) throws IllegalAccessException {
191
		Set<FoundParser<T>> found = new HashSet<>();
192
		List<TemplateImplementation> implementations = (List<TemplateImplementation>) readField(parser, "implementations", true);
193
		for (TemplateImplementation impl : implementations) {
194 1 1. findParsers : negated conditional → RUN_ERROR
			if (clazz.isAssignableFrom(impl.getParser().getClass())) {
195
				found.add(new FoundParser<>((T) impl.getParser(), getMessageType(sender)));
196
			}
197
		}
198 1 1. findParsers : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findParsers → RUN_ERROR
		return found;
199
	}
200
201
	private static Class<? extends Message> getMessageType(MessageSender sender) {
202
		Set<EmailSender> emailSenders = findSenders(sender, EmailSender.class);
203 1 1. getMessageType : negated conditional → RUN_ERROR
		if (!emailSenders.isEmpty()) {
204 1 1. getMessageType : replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getMessageType → RUN_ERROR
			return Email.class;
205
		}
206
		Set<SmsSender> smsSenders = findSenders(sender, SmsSender.class);
207 1 1. getMessageType : negated conditional → RUN_ERROR
		if (!smsSenders.isEmpty()) {
208 1 1. getMessageType : replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getMessageType → RUN_ERROR
			return Sms.class;
209
		}
210
		throw new IllegalStateException("Failed to find message type");
211
	}
212
213
	private static <T extends ContentTranslator> Set<T> findTranslators(ContentTranslatorSender translatorSender, Class<T> clazz) {
214
		try {
215
			ContentTranslator translator = (ContentTranslator) readField(translatorSender, "translator", true);
216 1 1. findTranslators : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findTranslators → RUN_ERROR
			return findTranslators(translator, clazz);
217
		} catch (IllegalAccessException e) {
218
			throw new IllegalStateException("Failed to find translator of type " + clazz.getTypeName(), e);
219
		}
220
	}
221
222
	private static <T extends ContentTranslator> Set<T> findTranslators(ContentTranslator translator, Class<T> clazz) {
223
		try {
224
			Set<T> found = new HashSet<>();
225 1 1. findTranslators : negated conditional → RUN_ERROR
			if (translator instanceof EveryContentTranslator) {
226
				found.addAll(findTranslators((EveryContentTranslator) translator, clazz));
227
			}
228 1 1. findTranslators : negated conditional → RUN_ERROR
			if (translator instanceof MultiContentTranslator) {
229
				found.addAll(findTranslators((ContentTranslator) readField(translator, DELEGATE_FIELD, true), clazz));
230
			}
231 1 1. findTranslators : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findTranslators → RUN_ERROR
			return found;
232
		} catch (IllegalAccessException e) {
233
			throw new IllegalStateException("Failed to read 'delegate' of MultiContentTranslator", e);
234
		}
235
	}
236
237
	@SuppressWarnings("unchecked")
238
	private static <T extends ContentTranslator> Set<T> findTranslators(EveryContentTranslator translator, Class<T> clazz) {
239
		Set<T> found = new HashSet<>();
240
		for (ContentTranslator t : translator.getTranslators()) {
241 1 1. findTranslators : negated conditional → RUN_ERROR
			if (clazz.isAssignableFrom(t.getClass())) {
242
				found.add((T) t);
243
			}
244
		}
245 1 1. findTranslators : replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findTranslators → RUN_ERROR
		return found;
246
	}
247
248
	private ImplementationFinder() {
249
		super();
250
	}
251
}

Mutations

53

1.1
Location : findSender
Killed by :
negated conditional → RUN_ERROR

56

1.1
Location : findSender
Killed by :
negated conditional → RUN_ERROR

57

1.1
Location : findSender
Killed by :
replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSender → RUN_ERROR

81

1.1
Location : findSenders
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSenders → RUN_ERROR

108

1.1
Location : findParsers
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findParsers → RUN_ERROR

116

1.1
Location : getRealService
Killed by :
negated conditional → RUN_ERROR

117

1.1
Location : getRealService
Killed by :
replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getRealService → RUN_ERROR

119

1.1
Location : getRealService
Killed by :
negated conditional → RUN_ERROR

120

1.1
Location : getRealService
Killed by :
replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getRealService → RUN_ERROR

122

1.1
Location : getRealService
Killed by :
negated conditional → RUN_ERROR

123

1.1
Location : getRealService
Killed by :
replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getRealService → RUN_ERROR

135

1.1
Location : findSenders
Killed by :
negated conditional → RUN_ERROR

142

1.1
Location : findSenders
Killed by :
negated conditional → RUN_ERROR

146

1.1
Location : findSenders
Killed by :
negated conditional → RUN_ERROR

149

1.1
Location : findSenders
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSenders → RUN_ERROR

158

1.1
Location : delegates
Killed by :
replaced boolean return with true for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::delegates → RUN_ERROR

2.2
Location : delegates
Killed by :
replaced boolean return with false for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::delegates → RUN_ERROR

160

1.1
Location : delegates
Killed by :
replaced boolean return with true for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::delegates → RUN_ERROR

169

1.1
Location : findSenders
Killed by :
negated conditional → RUN_ERROR

173

1.1
Location : findSenders
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findSenders → RUN_ERROR

180

1.1
Location : findParsers
Killed by :
negated conditional → RUN_ERROR

183

1.1
Location : findParsers
Killed by :
negated conditional → RUN_ERROR

186

1.1
Location : findParsers
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findParsers → RUN_ERROR

194

1.1
Location : findParsers
Killed by :
negated conditional → RUN_ERROR

198

1.1
Location : findParsers
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findParsers → RUN_ERROR

203

1.1
Location : getMessageType
Killed by :
negated conditional → RUN_ERROR

204

1.1
Location : getMessageType
Killed by :
replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getMessageType → RUN_ERROR

207

1.1
Location : getMessageType
Killed by :
negated conditional → RUN_ERROR

208

1.1
Location : getMessageType
Killed by :
replaced return value with null for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::getMessageType → RUN_ERROR

216

1.1
Location : findTranslators
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findTranslators → RUN_ERROR

225

1.1
Location : findTranslators
Killed by :
negated conditional → RUN_ERROR

228

1.1
Location : findTranslators
Killed by :
negated conditional → RUN_ERROR

231

1.1
Location : findTranslators
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findTranslators → RUN_ERROR

241

1.1
Location : findTranslators
Killed by :
negated conditional → RUN_ERROR

245

1.1
Location : findTranslators
Killed by :
replaced return value with Collections.emptySet for fr/sii/ogham/testing/assertion/internal/helper/ImplementationFinder::findTranslators → RUN_ERROR

Active mutators

Tests examined


Report generated by PIT 1.13.1