Sms.java

1
package fr.sii.ogham.sms.message;
2
3
import java.util.ArrayList;
4
import java.util.Arrays;
5
import java.util.List;
6
7
import fr.sii.ogham.core.message.Message;
8
import fr.sii.ogham.core.message.capability.HasContentFluent;
9
import fr.sii.ogham.core.message.capability.HasRecipients;
10
import fr.sii.ogham.core.message.capability.HasRecipientsFluent;
11
import fr.sii.ogham.core.message.capability.HasToFluent;
12
import fr.sii.ogham.core.message.content.Content;
13
import fr.sii.ogham.core.message.content.StringContent;
14
import fr.sii.ogham.core.message.fluent.SingleContentBuilder;
15
import fr.sii.ogham.core.util.Loggable;
16
import fr.sii.ogham.core.util.EqualsBuilder;
17
import fr.sii.ogham.core.util.HashCodeBuilder;
18
import fr.sii.ogham.core.util.StringUtils;
19
20
/**
21
 * SMS message that contains the following information:
22
 * <ul>
23
 * <li>The content of the SMS (see {@link Content} and sub classes for more
24
 * information)</li>
25
 * <li>The sender information (name and phone number). Name is optional</li>
26
 * <li>The list of recipients (name and phone number). Name is optional</li>
27
 * </ul>
28
 * 
29
 * @author Aurélien Baudet
30
 *
31
 */
32
public class Sms implements Message, HasContentFluent<Sms>, HasRecipients<Recipient>, HasRecipientsFluent<Sms, Recipient>, HasToFluent<Sms>, Loggable {
33
	/**
34
	 * The number of the sender
35
	 */
36
	private Sender from;
37
38
	/**
39
	 * The list of recipients of the SMS
40
	 */
41
	private List<Recipient> recipients;
42
43
	/**
44
	 * The content of the SMS
45
	 */
46
	private Content content;
47
48
	private final SingleContentBuilder<Sms> messageBuilder;
49
50
	public Sms() {
51
		super();
52
		recipients = new ArrayList<>();
53
		messageBuilder = new SingleContentBuilder<>(this);
54
	}
55
56
	// ----------------------- Getter/Setters -----------------------//
57
58
	/**
59
	 * Get the sender of the SMS
60
	 * 
61
	 * @return SMS sender
62
	 */
63
	public Sender getFrom() {
64 1 1. getFrom : replaced return value with null for fr/sii/ogham/sms/message/Sms::getFrom → RUN_ERROR
		return from;
65
	}
66
67
	/**
68
	 * Set the sender of the SMS
69
	 * 
70
	 * @param from
71
	 *            SMS sender to set
72
	 */
73
	public void setFrom(Sender from) {
74
		this.from = from;
75
	}
76
77
	/**
78
	 * Set the sender phone number of the SMS as string.
79
	 * 
80
	 * @param phoneNumber
81
	 *            SMS sender phone number to set
82
	 */
83
	public void setFrom(String phoneNumber) {
84 1 1. setFrom : removed call to fr/sii/ogham/sms/message/Sms::setFrom → NO_COVERAGE
		setFrom(new Sender(phoneNumber));
85
	}
86
87
	/**
88
	 * Get the recipients (to) of the SMS
89
	 * 
90
	 * @return SMS recipients
91
	 */
92
	public List<Recipient> getRecipients() {
93 1 1. getRecipients : replaced return value with Collections.emptyList for fr/sii/ogham/sms/message/Sms::getRecipients → RUN_ERROR
		return recipients;
94
	}
95
96
	/**
97
	 * Set the recipients (to) of the SMS
98
	 * 
99
	 * @param to
100
	 *            SMS recipients
101
	 */
102
	public void setRecipients(List<Recipient> to) {
103
		this.recipients = to;
104
	}
105
106
	@Override
107
	public Content getContent() {
108 1 1. getContent : negated conditional → RUN_ERROR
		if (content != null) {
109 1 1. getContent : replaced return value with null for fr/sii/ogham/sms/message/Sms::getContent → RUN_ERROR
			return content;
110
		}
111
		// NOTE: normally it can't be null but EqualsVerifier uses reflection to
112
		// set it to null
113 1 1. getContent : negated conditional → RUN_ERROR
		if (messageBuilder != null) {
114 1 1. getContent : replaced return value with null for fr/sii/ogham/sms/message/Sms::getContent → RUN_ERROR
			return messageBuilder.build();
115
		}
116
		return null;
117
	}
118
119
	@Override
120
	public void setContent(Content content) {
121
		this.content = content;
122
	}
123
124
	// ----------------------- Fluent API -----------------------//
125
126
	/**
127
	 * Set the content of the message.
128
	 * 
129
	 * <p>
130
	 * You can use this method to explicitly set a particular {@link Content}
131
	 * instance. For example:
132
	 * 
133
	 * <pre>
134
	 * {@code
135
	 * .content(new TemplateContent("path/to/template", obj));
136
	 * }
137
	 * </pre>
138
	 * 
139
	 * <p>
140
	 * If you prefer, you can instead use the fluent API to set the message of
141
	 * the SMS:
142
	 * 
143
	 * <pre>
144
	 * {@code
145
	 * .message().template("path/to/template", obj)
146
	 * }
147
	 * </pre>
148
	 * 
149
	 * @param content
150
	 *            the content of the message
151
	 * @return this instance for fluent chaining
152
	 * @see #message()
153
	 */
154
	public Sms content(Content content) {
155 1 1. content : removed call to fr/sii/ogham/sms/message/Sms::setContent → RUN_ERROR
		setContent(content);
156 1 1. content : replaced return value with null for fr/sii/ogham/sms/message/Sms::content → RUN_ERROR
		return this;
157
	}
158
159
	/**
160
	 * Set the content of the message. This is a shortcut to
161
	 * 
162
	 * <pre>
163
	 * {@code .content(new StringContent(content))}
164
	 * </pre>
165
	 * 
166
	 * <p>
167
	 * If you prefer, you can instead use the fluent API to set the message of
168
	 * the SMS:
169
	 * 
170
	 * <pre>
171
	 * {@code
172
	 * .message().string(content)
173
	 * }
174
	 * </pre>
175
	 * 
176
	 * 
177
	 * @param content
178
	 *            the content of the message
179
	 * @return this instance for fluent chaining
180
	 * @see #message()
181
	 */
182
	public Sms content(String content) {
183 1 1. content : replaced return value with null for fr/sii/ogham/sms/message/Sms::content → RUN_ERROR
		return content(new StringContent(content));
184
	}
185
186
	/**
187
	 * Set the message of the SMS.
188
	 * 
189
	 * <p>
190
	 * This method provides fluent chaining to guide developer. It has the same
191
	 * effect has using {@link #content(Content)}.
192
	 * 
193
	 * <p>
194
	 * If you also call either {@link #content(Content)},
195
	 * {@link #content(String)} or {@link #setContent(Content)} then this method
196
	 * has no effect.
197
	 * 
198
	 * @return the builder for building text part
199
	 * @since 3.0.0
200
	 */
201
	public SingleContentBuilder<Sms> message() {
202 1 1. message : replaced return value with null for fr/sii/ogham/sms/message/Sms::message → NO_COVERAGE
		return messageBuilder;
203
	}
204
205
	/**
206
	 * Set the sender.
207
	 * 
208
	 * @param from
209
	 *            the sender
210
	 * @return this instance for fluent chaining
211
	 */
212
	public Sms from(Sender from) {
213 1 1. from : removed call to fr/sii/ogham/sms/message/Sms::setFrom → RUN_ERROR
		setFrom(from);
214 1 1. from : replaced return value with null for fr/sii/ogham/sms/message/Sms::from → RUN_ERROR
		return this;
215
	}
216
217
	/**
218
	 * Set the list of recipients of the message
219
	 *
220
	 * @param recipients
221
	 *            the list of recipients of the message to set
222
	 * @return this instance for fluent chaining
223
	 */
224
	@Override
225
	public Sms recipients(List<Recipient> recipients) {
226 1 1. recipients : removed call to fr/sii/ogham/sms/message/Sms::setRecipients → NO_COVERAGE
		setRecipients(recipients);
227 1 1. recipients : replaced return value with null for fr/sii/ogham/sms/message/Sms::recipients → NO_COVERAGE
		return this;
228
	}
229
230
	/**
231
	 * Add a recipient for the message
232
	 *
233
	 * @param recipients
234
	 *            one or several recipient to add
235
	 * @return this instance for fluent chaining
236
	 */
237
	@Override
238
	public Sms recipient(Recipient... recipients) {
239
		this.recipients.addAll(Arrays.asList(recipients));
240 1 1. recipient : replaced return value with null for fr/sii/ogham/sms/message/Sms::recipient → RUN_ERROR
		return this;
241
	}
242
243
	/**
244
	 * Set the sender using the phone number as string.
245
	 * 
246
	 * @param phoneNumber
247
	 *            the sender number
248
	 * @return this instance for fluent chaining
249
	 */
250
	public Sms from(String phoneNumber) {
251 1 1. from : replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE
		return from(null, phoneNumber);
252
	}
253
254
	/**
255
	 * Set the sender using the phone number.
256
	 * 
257
	 * @param phoneNumber
258
	 *            the sender number
259
	 * @return this instance for fluent chaining
260
	 */
261
	public Sms from(PhoneNumber phoneNumber) {
262 1 1. from : replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE
		return from(null, phoneNumber);
263
	}
264
265
	/**
266
	 * Set the sender using the phone number as string.
267
	 * 
268
	 * @param name
269
	 *            the name of the sender
270
	 * @param phoneNumber
271
	 *            the sender number
272
	 * @return this instance for fluent chaining
273
	 */
274
	public Sms from(String name, String phoneNumber) {
275 1 1. from : replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE
		return from(name, new PhoneNumber(phoneNumber));
276
	}
277
278
	/**
279
	 * Set the sender using the phone number.
280
	 * 
281
	 * @param name
282
	 *            the name of the sender
283
	 * @param phoneNumber
284
	 *            the sender number
285
	 * @return this instance for fluent chaining
286
	 */
287
	public Sms from(String name, PhoneNumber phoneNumber) {
288 1 1. from : replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE
		return from(new Sender(name, phoneNumber));
289
	}
290
291
	/**
292
	 * Add a recipient specifying the phone number.
293
	 * 
294
	 * @param numbers
295
	 *            one or several recipient numbers
296
	 * @return this instance for fluent chaining
297
	 */
298
	public Sms to(PhoneNumber... numbers) {
299
		for (PhoneNumber number : numbers) {
300
			to((String) null, number);
301
		}
302 1 1. to : replaced return value with null for fr/sii/ogham/sms/message/Sms::to → NO_COVERAGE
		return this;
303
	}
304
305
	/**
306
	 * Add a recipient specifying the phone number as string.
307
	 * 
308
	 * @param numbers
309
	 *            one or several recipient numbers
310
	 * @return this instance for fluent chaining
311
	 */
312
	public Sms to(String... numbers) {
313
		for (String num : numbers) {
314
			to(new Recipient(num));
315
		}
316 1 1. to : replaced return value with null for fr/sii/ogham/sms/message/Sms::to → NO_COVERAGE
		return this;
317
	}
318
319
	/**
320
	 * Add a recipient specifying the name and the phone number.
321
	 * 
322
	 * @param name
323
	 *            the name of the recipient
324
	 * @param number
325
	 *            the number of the recipient
326
	 * @return this instance for fluent chaining
327
	 */
328
	public Sms to(String name, PhoneNumber number) {
329
		to(new Recipient(name, number));
330 1 1. to : replaced return value with null for fr/sii/ogham/sms/message/Sms::to → NO_COVERAGE
		return this;
331
	}
332
333
	/**
334
	 * Add a recipient.
335
	 * 
336
	 * @param recipients
337
	 *            one or several recipients to add
338
	 * @return this instance for fluent chaining
339
	 */
340
	public Sms to(Recipient... recipients) {
341
		recipient(recipients);
342 1 1. to : replaced return value with null for fr/sii/ogham/sms/message/Sms::to → RUN_ERROR
		return this;
343
	}
344
345
	// ----------------------- Utilities -----------------------//
346
347
	/**
348
	 * Converts a list of phone numbers to a list of recipients.
349
	 * 
350
	 * @param to
351
	 *            the list of phone numbers
352
	 * @return the list of recipients
353
	 */
354
	public static Recipient[] toRecipient(PhoneNumber[] to) {
355
		Recipient[] addresses = new Recipient[to.length];
356
		int i = 0;
357
		for (PhoneNumber t : to) {
358
			addresses[i] = new Recipient(t);
359 1 1. toRecipient : Changed increment from 1 to -1 → NO_COVERAGE
			i++;
360
		}
361 1 1. toRecipient : replaced return value with null for fr/sii/ogham/sms/message/Sms::toRecipient → NO_COVERAGE
		return addresses;
362
	}
363
364
	/**
365
	 * Converts a list of string to a list of recipients.
366
	 * 
367
	 * @param to
368
	 *            the list of phone numbers as string
369
	 * @return the list of recipients
370
	 */
371
	public static Recipient[] toRecipient(String[] to) {
372
		Recipient[] addresses = new Recipient[to.length];
373
		int i = 0;
374
		for (String t : to) {
375
			addresses[i] = new Recipient(t);
376 1 1. toRecipient : Changed increment from 1 to -1 → NO_COVERAGE
			i++;
377
		}
378 1 1. toRecipient : replaced return value with null for fr/sii/ogham/sms/message/Sms::toRecipient → NO_COVERAGE
		return addresses;
379
	}
380
381
	@Override
382
	public String toString() {
383 1 1. toString : replaced return value with "" for fr/sii/ogham/sms/message/Sms::toString → RUN_ERROR
		return toString(false);
384
	}
385
386
	@Override
387
	public String toLogString() {
388 1 1. toLogString : replaced return value with "" for fr/sii/ogham/sms/message/Sms::toLogString → NO_COVERAGE
		return toString(true);
389
	}
390
391
	@Override
392
	public int hashCode() {
393 1 1. hashCode : replaced int return with 0 for fr/sii/ogham/sms/message/Sms::hashCode → RUN_ERROR
		return new HashCodeBuilder().append(from, recipients, getContent()).hashCode();
394
	}
395
396
	@Override
397
	public boolean equals(Object obj) {
398 2 1. equals : replaced boolean return with false for fr/sii/ogham/sms/message/Sms::equals → RUN_ERROR
2. equals : replaced boolean return with true for fr/sii/ogham/sms/message/Sms::equals → RUN_ERROR
		return new EqualsBuilder(this, obj).appendFields("from", "recipients", "content").isEqual();
399
	}
400
401
	private String toString(boolean includeContent) {
402
		StringBuilder builder = new StringBuilder();
403
		builder.append("Sms message\r\nFrom: ").append(from);
404
		builder.append("\r\nTo: ").append(StringUtils.join(recipients, ", "));
405 1 1. toString : negated conditional → RUN_ERROR
		builder.append("\r\n----------------------------------\r\n").append(includeContent ? getContent() : "<Content skipped>");
406
		builder.append("\r\n==================================\r\n");
407 1 1. toString : replaced return value with "" for fr/sii/ogham/sms/message/Sms::toString → RUN_ERROR
		return builder.toString();
408
	}
409
}

Mutations

64

1.1
Location : getFrom
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::getFrom → RUN_ERROR

84

1.1
Location : setFrom
Killed by :
removed call to fr/sii/ogham/sms/message/Sms::setFrom → NO_COVERAGE

93

1.1
Location : getRecipients
Killed by :
replaced return value with Collections.emptyList for fr/sii/ogham/sms/message/Sms::getRecipients → RUN_ERROR

108

1.1
Location : getContent
Killed by :
negated conditional → RUN_ERROR

109

1.1
Location : getContent
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::getContent → RUN_ERROR

113

1.1
Location : getContent
Killed by :
negated conditional → RUN_ERROR

114

1.1
Location : getContent
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::getContent → RUN_ERROR

155

1.1
Location : content
Killed by :
removed call to fr/sii/ogham/sms/message/Sms::setContent → RUN_ERROR

156

1.1
Location : content
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::content → RUN_ERROR

183

1.1
Location : content
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::content → RUN_ERROR

202

1.1
Location : message
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::message → NO_COVERAGE

213

1.1
Location : from
Killed by :
removed call to fr/sii/ogham/sms/message/Sms::setFrom → RUN_ERROR

214

1.1
Location : from
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::from → RUN_ERROR

226

1.1
Location : recipients
Killed by :
removed call to fr/sii/ogham/sms/message/Sms::setRecipients → NO_COVERAGE

227

1.1
Location : recipients
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::recipients → NO_COVERAGE

240

1.1
Location : recipient
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::recipient → RUN_ERROR

251

1.1
Location : from
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE

262

1.1
Location : from
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE

275

1.1
Location : from
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE

288

1.1
Location : from
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::from → NO_COVERAGE

302

1.1
Location : to
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::to → NO_COVERAGE

316

1.1
Location : to
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::to → NO_COVERAGE

330

1.1
Location : to
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::to → NO_COVERAGE

342

1.1
Location : to
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::to → RUN_ERROR

359

1.1
Location : toRecipient
Killed by :
Changed increment from 1 to -1 → NO_COVERAGE

361

1.1
Location : toRecipient
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::toRecipient → NO_COVERAGE

376

1.1
Location : toRecipient
Killed by :
Changed increment from 1 to -1 → NO_COVERAGE

378

1.1
Location : toRecipient
Killed by :
replaced return value with null for fr/sii/ogham/sms/message/Sms::toRecipient → NO_COVERAGE

383

1.1
Location : toString
Killed by :
replaced return value with "" for fr/sii/ogham/sms/message/Sms::toString → RUN_ERROR

388

1.1
Location : toLogString
Killed by :
replaced return value with "" for fr/sii/ogham/sms/message/Sms::toLogString → NO_COVERAGE

393

1.1
Location : hashCode
Killed by :
replaced int return with 0 for fr/sii/ogham/sms/message/Sms::hashCode → RUN_ERROR

398

1.1
Location : equals
Killed by :
replaced boolean return with false for fr/sii/ogham/sms/message/Sms::equals → RUN_ERROR

2.2
Location : equals
Killed by :
replaced boolean return with true for fr/sii/ogham/sms/message/Sms::equals → RUN_ERROR

405

1.1
Location : toString
Killed by :
negated conditional → RUN_ERROR

407

1.1
Location : toString
Killed by :
replaced return value with "" for fr/sii/ogham/sms/message/Sms::toString → RUN_ERROR

Active mutators

Tests examined


Report generated by PIT 1.13.1