| 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 |