SenderImplementationBuilderHelper.java

1
package fr.sii.ogham.core.builder.sender;
2
3
import static fr.sii.ogham.core.util.BuilderUtils.instantiateBuilder;
4
5
import java.util.ArrayList;
6
import java.util.List;
7
8
import org.slf4j.Logger;
9
import org.slf4j.LoggerFactory;
10
11
import fr.sii.ogham.core.builder.ActivableAtRuntime;
12
import fr.sii.ogham.core.builder.Builder;
13
import fr.sii.ogham.core.builder.condition.RequiredClass;
14
import fr.sii.ogham.core.builder.condition.RequiredClasses;
15
import fr.sii.ogham.core.builder.condition.RequiredProperties;
16
import fr.sii.ogham.core.builder.condition.RequiredProperty;
17
import fr.sii.ogham.core.builder.context.BuildContext;
18
import fr.sii.ogham.core.builder.env.EnvironmentBuilder;
19
import fr.sii.ogham.core.builder.priority.ImplementationPriorityProvider;
20
import fr.sii.ogham.core.builder.priority.PriorityProvider;
21
import fr.sii.ogham.core.condition.Condition;
22
import fr.sii.ogham.core.condition.fluent.MessageConditions;
23
import fr.sii.ogham.core.condition.provider.ImplementationConditionProvider;
24
import fr.sii.ogham.core.message.Message;
25
import fr.sii.ogham.core.sender.MessageSender;
26
import fr.sii.ogham.core.sender.MultiImplementationSender;
27
28
/**
29
 * Helps to configure a {@link MultiImplementationSender}.
30
 * 
31
 * <p>
32
 * It registers and uses {@link Builder}s to instantiate and configure a
33
 * {@link MessageSender} implementation.
34
 * </p>
35
 * 
36
 * <p>
37
 * It also let you provide your own direct {@link MessageSender} implementation.
38
 * </p>
39
 * 
40
 * @author Aurélien Baudet
41
 *
42
 * @param <P>
43
 *            the type of the parent builder {@link MessageSender}
44
 *            {@link Builder}
45
 */
46
public class SenderImplementationBuilderHelper<P> {
47
	private static final Logger LOG = LoggerFactory.getLogger(SenderImplementationBuilderHelper.class);
48
49
	private final P parent;
50
	private final BuildContext buildContext;
51
	private final List<Builder<? extends MessageSender>> senderBuilders;
52
	private final List<MessageSender> customSenders;
53
	private final PriorityProvider<MessageSender> priorityProvider;
54
55
	/**
56
	 * Initializes the builder with a parent builder. The parent builder is used
57
	 * when calling and() method of any registered {@link Message}
58
	 * {@link Builder}. The {@link EnvironmentBuilder} is used to evaluate
59
	 * properties at build time (when
60
	 * {@link #addSenders(MultiImplementationSender)} is called).
61
	 * 
62
	 * @param parent
63
	 *            the parent builder
64
	 * @param buildContext
65
	 *            for registering instances and property evaluation
66
	 */
67
	public SenderImplementationBuilderHelper(P parent, BuildContext buildContext) {
68
		super();
69
		this.parent = parent;
70
		this.buildContext = buildContext;
71
		senderBuilders = new ArrayList<>();
72
		customSenders = new ArrayList<>();
73
		priorityProvider = new ImplementationPriorityProvider<>(buildContext);
74
	}
75
76
	/**
77
	 * Returns true if at least either one custom sender or a sender builder was
78
	 * previously registered.
79
	 * 
80
	 * @return true if at least one custom sender or one sender builder
81
	 */
82
	public boolean hasRegisteredSenders() {
83 3 1. hasRegisteredSenders : replaced boolean return with true for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::hasRegisteredSenders → NO_COVERAGE
2. hasRegisteredSenders : negated conditional → NO_COVERAGE
3. hasRegisteredSenders : negated conditional → NO_COVERAGE
		return !customSenders.isEmpty() || !senderBuilders.isEmpty();
84
	}
85
86
	/**
87
	 * Registers a custom message sender implementation.
88
	 * 
89
	 * <p>
90
	 * If your custom implementation is annotated by one or several of:
91
	 * <ul>
92
	 * <li>{@link RequiredClass}</li>
93
	 * <li>{@link RequiredProperty}</li>
94
	 * <li>{@link RequiredClasses}</li>
95
	 * <li>{@link RequiredProperties}</li>
96
	 * </ul>
97
	 * Then if condition evaluation returns true, your implementation will be
98
	 * used. If you provide several annotations, your implementation will be
99
	 * used only if all conditions are met (and operator).
100
	 * 
101
	 * <p>
102
	 * If your custom implementation implements {@link ActivableAtRuntime}, and
103
	 * the provided condition evaluation returns true, then your implementation
104
	 * will be used.
105
	 * 
106
	 * See {@link MessageConditions} to build your condition.
107
	 * </p>
108
	 * 
109
	 * <p>
110
	 * If neither annotations nor implementation of {@link ActivableAtRuntime}
111
	 * is used, then your custom implementation will be always used. All other
112
	 * implementations (even standard ones) will never be used.
113
	 * </p>
114
	 * 
115
	 * @param sender
116
	 *            the sender to register
117
	 */
118
	public void customSender(MessageSender sender) {
119
		customSenders.add(sender);
120
	}
121
122
	/**
123
	 * Registers and configures sender through a dedicated builder.
124
	 * 
125
	 * For example:
126
	 * 
127
	 * <pre>
128
	 * .register(JavaMailBuilder.class)
129
	 *     .host("localhost");
130
	 * </pre>
131
	 * 
132
	 * <p>
133
	 * If your custom builder is annotated by one or several of:
134
	 * <ul>
135
	 * <li>{@link RequiredClass}</li>
136
	 * <li>{@link RequiredProperty}</li>
137
	 * <li>{@link RequiredClasses}</li>
138
	 * <li>{@link RequiredProperties}</li>
139
	 * </ul>
140
	 * Then if condition evaluation returns true, your built implementation will
141
	 * be used. If you provide several annotations, your built implementation
142
	 * will be used only if all conditions are met (and operator).
143
	 * 
144
	 * <p>
145
	 * If your custom builder implements {@link ActivableAtRuntime}, and the
146
	 * provided condition evaluation returns true, then your built
147
	 * implementation will be used.
148
	 * 
149
	 * See {@link MessageConditions} to build your condition.
150
	 * </p>
151
	 * 
152
	 * <p>
153
	 * If neither annotations nor implementation of {@link ActivableAtRuntime}
154
	 * is used, then your built implementation will be always used. All other
155
	 * implementations (even standard ones) will never be used.
156
	 * </p>
157
	 * 
158
	 * <p>
159
	 * In order to be able to keep chaining, you builder instance may provide a
160
	 * constructor with one argument with the type of the parent builder
161
	 * ({@code &lt;P&gt;}). If you don't care about chaining, just provide a
162
	 * default constructor.
163
	 * </p>
164
	 * 
165
	 * <p>
166
	 * Your builder may return {@code null} when calling
167
	 * {@link Builder#build()}. In this case it means that your implementation
168
	 * can't be used due to current environment. Your implementation is then not
169
	 * registered.
170
	 * </p>
171
	 * 
172
	 * @param builderClass
173
	 *            the builder class to instantiate
174
	 * @param <B>
175
	 *            the type of the builder
176
	 * @return the builder to configure the implementation
177
	 * 
178
	 */
179
	@SuppressWarnings("unchecked")
180
	public <B extends Builder<? extends MessageSender>> B register(Class<B> builderClass) {
181
		// if builder already registered => provide same instance
182
		for (Builder<? extends MessageSender> builder : senderBuilders) {
183 6 1. register : negated conditional → NO_COVERAGE
2. register : negated conditional → KILLED
3. register : negated conditional → KILLED
4. register : negated conditional → KILLED
5. register : negated conditional → KILLED
6. register : negated conditional → KILLED
			if (builderClass.isAssignableFrom(builder.getClass())) {
184 5 1. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → NO_COVERAGE
2. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
3. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
4. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
5. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
				return (B) builder;
185
			}
186
		}
187
		B builder = instantiateBuilder(builderClass, parent, buildContext);
188
		senderBuilders.add(builder);
189 8 1. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → NO_COVERAGE
2. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → TIMED_OUT
3. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
4. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
5. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
6. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
7. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
8. register : replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED
		return builder;
190
	}
191
192
	/**
193
	 * Add registered custom senders or built senders base on registered sender
194
	 * builders to the provided {@link MultiImplementationSender}.
195
	 * 
196
	 * <p>
197
	 * A {@link MultiImplementationSender} is able to evaluate a
198
	 * {@link Condition} when a message is being sent to determine which
199
	 * implementation can and should handle the message and really send it.
200
	 * </p>
201
	 * 
202
	 * <p>
203
	 * If a custom implementation was registered and is annotated by one or
204
	 * several of:
205
	 * <ul>
206
	 * <li>{@link RequiredClass}</li>
207
	 * <li>{@link RequiredProperty}</li>
208
	 * <li>{@link RequiredClasses}</li>
209
	 * <li>{@link RequiredProperties}</li>
210
	 * </ul>
211
	 * Then if condition evaluation returns true, the custom implementation will
212
	 * be used. If you provide several annotations, the custom implementation
213
	 * will be used only if all conditions are met (and operator).
214
	 * 
215
	 * <p>
216
	 * If a custom implementation was registered and implements
217
	 * {@link ActivableAtRuntime}, and the provided condition evaluation returns
218
	 * true, then the custom implementation will be used.
219
	 * 
220
	 * See {@link MessageConditions} to build your condition.
221
	 * </p>
222
	 * 
223
	 * <p>
224
	 * If neither annotations nor implementation of {@link ActivableAtRuntime}
225
	 * is used, then the custom implementation will be always used. All other
226
	 * implementations (even standard ones) will never be used.
227
	 * </p>
228
	 * 
229
	 * @param mainSender
230
	 *            the sender that manages several implementations
231
	 */
232
	public void addSenders(MultiImplementationSender<?> mainSender) {
233
		ImplementationConditionProvider implementationSelection = new ImplementationConditionProvider(buildContext.getPropertyResolver());
234
		for (MessageSender customSender : customSenders) {
235
			LOG.debug("Custom implementation {} registered into {}", customSender, mainSender);
236
			mainSender.addImplementation(implementationSelection.provide(customSender), buildContext.register(customSender), priorityProvider.provide(customSender));
237
		}
238
		for (Builder<? extends MessageSender> builder : senderBuilders) {
239
			MessageSender sender = builder.build();
240 8 1. addSenders : negated conditional → NO_COVERAGE
2. addSenders : negated conditional → KILLED
3. addSenders : negated conditional → KILLED
4. addSenders : negated conditional → KILLED
5. addSenders : negated conditional → KILLED
6. addSenders : negated conditional → KILLED
7. addSenders : negated conditional → KILLED
8. addSenders : negated conditional → KILLED
			if (sender != null) {
241
				LOG.debug("Implementation {} registered into {}", sender, mainSender);
242
				mainSender.addImplementation(implementationSelection.provide(builder), sender, priorityProvider.provide(sender));
243
			}
244
		}
245
	}
246
247
}

Mutations

83

1.1
Location : hasRegisteredSenders
Killed by : none
replaced boolean return with true for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::hasRegisteredSenders → NO_COVERAGE

2.2
Location : hasRegisteredSenders
Killed by : none
negated conditional → NO_COVERAGE

3.3
Location : hasRegisteredSenders
Killed by : none
negated conditional → NO_COVERAGE

183

1.1
Location : register
Killed by : oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests.oghamAloneShouldUseOghamProperties(oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests)
negated conditional → KILLED

2.2
Location : register
Killed by : oghamcore.it.core.builder.SenderPrioritySpec
negated conditional → KILLED

3.3
Location : register
Killed by : oghamall.it.html.translator.JsoupInlineCssTranslatorTest.notHtml(oghamall.it.html.translator.JsoupInlineCssTranslatorTest)
negated conditional → KILLED

4.4
Location : register
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
negated conditional → KILLED

5.5
Location : register
Killed by : oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests.oghamPropertiesWithSpringPropsShouldUseOghamPropertiesPrecedence(oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests)
negated conditional → KILLED

6.6
Location : register
Killed by : none
negated conditional → NO_COVERAGE

184

1.1
Location : register
Killed by : oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests.oghamPropertiesWithSpringPropsShouldUseOghamPropertiesPrecedence(oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

2.2
Location : register
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

3.3
Location : register
Killed by : oghamall.it.configuration.JavaMailConfigurationTest.asDeveloperIDefineHostInMyOwnCode(oghamall.it.configuration.JavaMailConfigurationTest)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

4.4
Location : register
Killed by : oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests.oghamAloneShouldUseOghamProperties(oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

5.5
Location : register
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → NO_COVERAGE

189

1.1
Location : register
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → NO_COVERAGE

2.2
Location : register
Killed by : none
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → TIMED_OUT

3.3
Location : register
Killed by : oghamcore.it.core.builder.CustomSenderBuilderTest.asDeveloperIRegisterACustomBuilderWithoutFluentChaining(oghamcore.it.core.builder.CustomSenderBuilderTest)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

4.4
Location : register
Killed by : oghamall.it.configuration.EmptyBuilderTest.emailSenderManuallyRegisteredButUnconfiguredTemplateParsersCantHandleMultiTemplateContent(oghamall.it.configuration.EmptyBuilderTest)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

5.5
Location : register
Killed by : oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests.oghamAloneShouldUseOghamProperties(oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

6.6
Location : register
Killed by : oghamcloudhopper.it.AutoRetryExtensionTest.smsNotRetriedDueToCloudhopperError(oghamcloudhopper.it.AutoRetryExtensionTest)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

7.7
Location : register
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

8.8
Location : register
Killed by : oghamjavamail.it.builder.JavaMailCustomConfigurationTest.noHostDefinedShouldFail(oghamjavamail.it.builder.JavaMailCustomConfigurationTest)
replaced return value with null for fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::register → KILLED

240

1.1
Location : addSenders
Killed by : oghamcloudhopper.it.AutoRetryExtensionTest.smsNotRetriedDueToCloudhopperError(oghamcloudhopper.it.AutoRetryExtensionTest)
negated conditional → KILLED

2.2
Location : addSenders
Killed by : oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests.oghamAloneShouldUseOghamProperties(oghamspringbootv1autoconfigure.it.OghamSpringBoot1JavaMailAutoConfigurationTests)
negated conditional → KILLED

3.3
Location : addSenders
Killed by : oghamall.it.configuration.EmptyBuilderTest.emailSenderManuallyRegisteredButUnconfiguredTemplateParsersCantHandleMultiTemplateContent(oghamall.it.configuration.EmptyBuilderTest)
negated conditional → KILLED

4.4
Location : addSenders
Killed by : oghamsmsglobal.it.SmsglobalServiceProviderConfigurerSpec
negated conditional → KILLED

5.5
Location : addSenders
Killed by : oghamcore.it.core.builder.SenderPrioritySpec
negated conditional → KILLED

6.6
Location : addSenders
Killed by : oghamjavamail.it.builder.JavaMailCustomConfigurationTest.oghamPropertyShouldOverride(oghamjavamail.it.builder.JavaMailCustomConfigurationTest)
negated conditional → KILLED

7.7
Location : addSenders
Killed by : none
negated conditional → NO_COVERAGE

8.8
Location : addSenders
Killed by : oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests.oghamPropertiesWithSpringPropsShouldUseOghamPropertiesPrecedence(oghamspringbootv2autoconfigure.it.OghamSpringBoot2JavaMailAutoConfigurationTests)
negated conditional → KILLED

Active mutators

Tests examined


Report generated by PIT OGHAM