1 | package fr.sii.ogham.sms.sender.impl.cloudhopper.preparator; | |
2 | ||
3 | import static com.cloudhopper.smpp.SmppConstants.ESM_CLASS_UDHI_MASK; | |
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 com.cloudhopper.smpp.pdu.SubmitSm; | |
12 | import com.cloudhopper.smpp.type.Address; | |
13 | ||
14 | import fr.sii.ogham.core.exception.InvalidMessageException; | |
15 | import fr.sii.ogham.sms.encoder.Encoded; | |
16 | import fr.sii.ogham.sms.exception.message.PhoneNumberTranslatorException; | |
17 | import fr.sii.ogham.sms.exception.message.SplitMessageException; | |
18 | import fr.sii.ogham.sms.message.Contact; | |
19 | import fr.sii.ogham.sms.message.PhoneNumber; | |
20 | import fr.sii.ogham.sms.message.Recipient; | |
21 | import fr.sii.ogham.sms.message.Sms; | |
22 | import fr.sii.ogham.sms.message.addressing.AddressedPhoneNumber; | |
23 | import fr.sii.ogham.sms.message.addressing.translator.PhoneNumberTranslator; | |
24 | import fr.sii.ogham.sms.sender.impl.cloudhopper.exception.DataCodingException; | |
25 | import fr.sii.ogham.sms.sender.impl.cloudhopper.exception.MessagePreparationException; | |
26 | import fr.sii.ogham.sms.splitter.EncodedSegment; | |
27 | import fr.sii.ogham.sms.splitter.MessageSplitter; | |
28 | import fr.sii.ogham.sms.splitter.Segment; | |
29 | ||
30 | /** | |
31 | * Base preparator that creates {@link SubmitSm}s. | |
32 | * | |
33 | * <p> | |
34 | * The message content is not set. It lets implementations implement | |
35 | * {@code fill(SubmitSm, Segment)} method to set the content. | |
36 | * | |
37 | * <p> | |
38 | * This preparator detects which charset should be used to encode message string | |
39 | * and splits it if needed. It also converts {@link PhoneNumber} to | |
40 | * {@link AddressedPhoneNumber}. | |
41 | * | |
42 | * @author Aurélien Baudet | |
43 | * | |
44 | */ | |
45 | public abstract class BaseMessagePreparator implements MessagePreparator { | |
46 | private static final Logger LOG = LoggerFactory.getLogger(BaseMessagePreparator.class); | |
47 | ||
48 | /** | |
49 | * Split message if needed into several parts | |
50 | */ | |
51 | private final MessageSplitter messageSplitter; | |
52 | ||
53 | /** | |
54 | * Determines the data coding to use according to encoding | |
55 | */ | |
56 | private final DataCodingProvider dataCodingProvider; | |
57 | ||
58 | /** | |
59 | * This phone number translator will handle the fallback addressing policy | |
60 | * (TON / NPI). | |
61 | */ | |
62 | private final PhoneNumberTranslator phoneNumberTranslator; | |
63 | ||
64 | /** | |
65 | * The preparator can split messages and provide data coding information. | |
66 | * | |
67 | * <p> | |
68 | * The phone number won't be translated meaning that if phone number is not | |
69 | * already converted to {@link AddressedPhoneNumber} then an | |
70 | * {@link IllegalStateException} is thrown. | |
71 | * | |
72 | * @param messageSplitter | |
73 | * Split message in several parts if needed | |
74 | * @param dataCodingProvider | |
75 | * Determines the data coding to use according to encoding | |
76 | */ | |
77 | public BaseMessagePreparator(MessageSplitter messageSplitter, DataCodingProvider dataCodingProvider) { | |
78 | this(messageSplitter, dataCodingProvider, null); | |
79 | } | |
80 | ||
81 | /** | |
82 | * Initializes the preparator with message splitter, data coding provider | |
83 | * and phone number translator. | |
84 | * | |
85 | * @param messageSplitter | |
86 | * Split message in several parts if needed | |
87 | * @param dataCodingProvider | |
88 | * Determines the data coding to use according to encoding | |
89 | * @param phoneNumberTranslator | |
90 | * Fallback phone translator to handle addressing policy | |
91 | */ | |
92 | public BaseMessagePreparator(MessageSplitter messageSplitter, DataCodingProvider dataCodingProvider, PhoneNumberTranslator phoneNumberTranslator) { | |
93 | super(); | |
94 | this.messageSplitter = messageSplitter; | |
95 | this.dataCodingProvider = dataCodingProvider; | |
96 | this.phoneNumberTranslator = phoneNumberTranslator; | |
97 | } | |
98 | ||
99 | @Override | |
100 | public List<SubmitSm> prepareMessages(Sms message) throws MessagePreparationException { | |
101 | try { | |
102 |
4
1. prepareMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::prepareMessages → NO_COVERAGE 2. prepareMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::prepareMessages → TIMED_OUT 3. prepareMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::prepareMessages → KILLED 4. prepareMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::prepareMessages → KILLED |
return createMessages(message); |
103 | } catch (PhoneNumberTranslatorException | DataCodingException | InvalidMessageException e) { | |
104 | throw new MessagePreparationException("Failed to prepare messages", message, e); | |
105 | } catch (SplitMessageException e) { | |
106 | throw new MessagePreparationException("Failed to split SMPP message before sending it", message, e); | |
107 | } | |
108 | } | |
109 | ||
110 | /** | |
111 | * Fill the {@link SubmitSm} with the message content. | |
112 | * | |
113 | * @param originalMessage | |
114 | * the SMS that is about to be sent | |
115 | * @param submit | |
116 | * the submit to fill | |
117 | * @param part | |
118 | * the message content | |
119 | * @throws MessagePreparationException | |
120 | * when message couldn't be prepared correctly | |
121 | */ | |
122 | protected abstract void fill(Sms originalMessage, SubmitSm submit, Segment part) throws MessagePreparationException; | |
123 | ||
124 | private List<SubmitSm> createMessages(Sms message) throws PhoneNumberTranslatorException, SplitMessageException, DataCodingException, MessagePreparationException, InvalidMessageException { | |
125 | List<SubmitSm> messages = new ArrayList<>(); | |
126 | for (Recipient recipient : message.getRecipients()) { | |
127 | messages.addAll(createMessages(message, recipient)); | |
128 | } | |
129 |
4
1. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → NO_COVERAGE 2. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → TIMED_OUT 3. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → KILLED 4. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → KILLED |
return messages; |
130 | } | |
131 | ||
132 | private List<SubmitSm> createMessages(Sms message, Recipient recipient) throws PhoneNumberTranslatorException, SplitMessageException, DataCodingException, MessagePreparationException, InvalidMessageException { | |
133 | List<SubmitSm> messages = new ArrayList<>(); | |
134 | ||
135 | List<Segment> parts = messageSplitter.split(message.getContent().toString()); | |
136 |
8
1. createMessages : changed conditional boundary → NO_COVERAGE 2. createMessages : negated conditional → NO_COVERAGE 3. createMessages : changed conditional boundary → TIMED_OUT 4. createMessages : negated conditional → TIMED_OUT 5. createMessages : changed conditional boundary → KILLED 6. createMessages : changed conditional boundary → KILLED 7. createMessages : negated conditional → KILLED 8. createMessages : negated conditional → KILLED |
if (parts.size() <= 1) { |
137 |
4
1. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addSubmit → NO_COVERAGE 2. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addSubmit → TIMED_OUT 3. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addSubmit → KILLED 4. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addSubmit → KILLED |
addSubmit(message, recipient, messages, parts.get(0)); |
138 |
4
1. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → NO_COVERAGE 2. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → TIMED_OUT 3. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → KILLED 4. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → KILLED |
return messages; |
139 | } | |
140 | ||
141 | LOG.debug("Content split into {} parts", parts.size()); | |
142 | for (Segment part : parts) { | |
143 |
3
1. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addEsmClassSubmit → NO_COVERAGE 2. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addEsmClassSubmit → KILLED 3. createMessages : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::addEsmClassSubmit → KILLED |
addEsmClassSubmit(message, recipient, messages, part); |
144 | } | |
145 |
3
1. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → NO_COVERAGE 2. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → KILLED 3. createMessages : replaced return value with Collections.emptyList for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessages → KILLED |
return messages; |
146 | } | |
147 | ||
148 | private void addEsmClassSubmit(Sms message, Recipient recipient, List<SubmitSm> messages, Segment part) throws PhoneNumberTranslatorException, DataCodingException, MessagePreparationException, InvalidMessageException { | |
149 | SubmitSm submit = createMessage(message, recipient, part); | |
150 |
3
1. addEsmClassSubmit : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setEsmClass → NO_COVERAGE 2. addEsmClassSubmit : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setEsmClass → KILLED 3. addEsmClassSubmit : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setEsmClass → KILLED |
submit.setEsmClass(ESM_CLASS_UDHI_MASK); |
151 | messages.add(submit); | |
152 | } | |
153 | ||
154 | private void addSubmit(Sms message, Recipient recipient, List<SubmitSm> messages, Segment part) throws PhoneNumberTranslatorException, DataCodingException, MessagePreparationException, InvalidMessageException { | |
155 | SubmitSm submit = createMessage(message, recipient, part); | |
156 | messages.add(submit); | |
157 | } | |
158 | ||
159 | private SubmitSm createMessage(Sms message, Recipient recipient, Segment part) throws PhoneNumberTranslatorException, DataCodingException, MessagePreparationException, InvalidMessageException { | |
160 | SubmitSm submit = new SubmitSm(); | |
161 |
4
1. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setSourceAddress → NO_COVERAGE 2. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setSourceAddress → TIMED_OUT 3. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setSourceAddress → KILLED 4. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setSourceAddress → KILLED |
submit.setSourceAddress(toAddress("sender", message, message.getFrom())); |
162 |
4
1. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDestAddress → NO_COVERAGE 2. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDestAddress → TIMED_OUT 3. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDestAddress → KILLED 4. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDestAddress → KILLED |
submit.setDestAddress(toAddress("recipient", message, recipient)); |
163 | ||
164 |
4
1. createMessage : negated conditional → NO_COVERAGE 2. createMessage : negated conditional → TIMED_OUT 3. createMessage : negated conditional → KILLED 4. createMessage : negated conditional → KILLED |
if (part instanceof EncodedSegment) { |
165 | Encoded encoded = ((EncodedSegment) part).getEncoded(); | |
166 |
4
1. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDataCoding → NO_COVERAGE 2. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDataCoding → TIMED_OUT 3. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDataCoding → KILLED 4. createMessage : removed call to com/cloudhopper/smpp/pdu/SubmitSm::setDataCoding → KILLED |
submit.setDataCoding(dataCodingProvider.provide(encoded).getByteValue()); |
167 | } | |
168 | ||
169 |
4
1. createMessage : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::fill → NO_COVERAGE 2. createMessage : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::fill → TIMED_OUT 3. createMessage : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::fill → KILLED 4. createMessage : removed call to fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::fill → KILLED |
fill(message, submit, part); |
170 | ||
171 |
4
1. createMessage : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessage → NO_COVERAGE 2. createMessage : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessage → TIMED_OUT 3. createMessage : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessage → KILLED 4. createMessage : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::createMessage → KILLED |
return submit; |
172 | } | |
173 | ||
174 | private Address toAddress(String field, Sms msg, Contact contact) throws PhoneNumberTranslatorException, InvalidMessageException { | |
175 |
4
1. toAddress : negated conditional → NO_COVERAGE 2. toAddress : negated conditional → TIMED_OUT 3. toAddress : negated conditional → KILLED 4. toAddress : negated conditional → KILLED |
if (contact == null) { |
176 | throw new InvalidMessageException(field+" is not set", msg, "Missing "+field+" phone number"); | |
177 | } | |
178 | PhoneNumber phoneNumber = contact.getPhoneNumber(); | |
179 |
4
1. toAddress : negated conditional → NO_COVERAGE 2. toAddress : negated conditional → TIMED_OUT 3. toAddress : negated conditional → KILLED 4. toAddress : negated conditional → KILLED |
if (phoneNumber == null) { |
180 | throw new InvalidMessageException(field+" phone number is not set", msg, "Missing "+field+" phone number"); | |
181 | } | |
182 |
4
1. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → NO_COVERAGE 2. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → TIMED_OUT 3. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → KILLED 4. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → KILLED |
return toAddress(phoneNumber); |
183 | } | |
184 | | |
185 | /** | |
186 | * Transforms a {@link PhoneNumber} in a {@link Address} type. | |
187 | * | |
188 | * @param phoneNumber | |
189 | * The given phone number | |
190 | * @return corresponding address with number, TON and NPI | |
191 | * @throws PhoneNumberTranslatorException | |
192 | * If an error occurs during fallback phone number translation | |
193 | */ | |
194 | private Address toAddress(PhoneNumber phoneNumber) throws PhoneNumberTranslatorException { | |
195 | AddressedPhoneNumber addressedPhoneNumber; | |
196 | ||
197 |
4
1. toAddress : negated conditional → NO_COVERAGE 2. toAddress : negated conditional → TIMED_OUT 3. toAddress : negated conditional → KILLED 4. toAddress : negated conditional → KILLED |
if (phoneNumber instanceof AddressedPhoneNumber) { |
198 | addressedPhoneNumber = (AddressedPhoneNumber) phoneNumber; | |
199 |
2
1. toAddress : negated conditional → NO_COVERAGE 2. toAddress : negated conditional → KILLED |
} else if (phoneNumberTranslator != null) { |
200 | LOG.warn("Fallback addressing policy used for PhoneNumber '{}'. You might decorate your sender with a PhoneNumberTranslatorSender.", phoneNumber); | |
201 | addressedPhoneNumber = phoneNumberTranslator.translate(phoneNumber); | |
202 | } else { | |
203 | throw new IllegalStateException("Must provide addressing policy with the phone number or with a fallback phone number translator."); | |
204 | } | |
205 | LOG.debug("Addressing policy applied on {} ", addressedPhoneNumber); | |
206 |
4
1. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → NO_COVERAGE 2. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → TIMED_OUT 3. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → KILLED 4. toAddress : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/BaseMessagePreparator::toAddress → KILLED |
return new Address(addressedPhoneNumber.getTon().value(), addressedPhoneNumber.getNpi().value(), addressedPhoneNumber.getNumber()); |
207 | } | |
208 | ||
209 | } | |
Mutations | ||
102 |
1.1 2.2 3.3 4.4 |
|
129 |
1.1 2.2 3.3 4.4 |
|
136 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
137 |
1.1 2.2 3.3 4.4 |
|
138 |
1.1 2.2 3.3 4.4 |
|
143 |
1.1 2.2 3.3 |
|
145 |
1.1 2.2 3.3 |
|
150 |
1.1 2.2 3.3 |
|
161 |
1.1 2.2 3.3 4.4 |
|
162 |
1.1 2.2 3.3 4.4 |
|
164 |
1.1 2.2 3.3 4.4 |
|
166 |
1.1 2.2 3.3 4.4 |
|
169 |
1.1 2.2 3.3 4.4 |
|
171 |
1.1 2.2 3.3 4.4 |
|
175 |
1.1 2.2 3.3 4.4 |
|
179 |
1.1 2.2 3.3 4.4 |
|
182 |
1.1 2.2 3.3 4.4 |
|
197 |
1.1 2.2 3.3 4.4 |
|
199 |
1.1 2.2 |
|
206 |
1.1 2.2 3.3 4.4 |