| 1 | package fr.sii.ogham.sms.sender.impl.cloudhopper.preparator; | |
| 2 | ||
| 3 | import static com.cloudhopper.commons.charset.CharsetUtil.NAME_GSM; | |
| 4 | import static com.cloudhopper.commons.charset.CharsetUtil.NAME_GSM7; | |
| 5 | import static com.cloudhopper.commons.charset.CharsetUtil.NAME_GSM8; | |
| 6 | import static com.cloudhopper.commons.charset.CharsetUtil.NAME_ISO_8859_1; | |
| 7 | import static com.cloudhopper.commons.charset.CharsetUtil.NAME_PACKED_GSM; | |
| 8 | import static com.cloudhopper.commons.charset.CharsetUtil.NAME_UCS_2; | |
| 9 | import static com.cloudhopper.commons.gsm.DataCoding.CHAR_ENC_8BIT; | |
| 10 | import static com.cloudhopper.commons.gsm.DataCoding.CHAR_ENC_DEFAULT; | |
| 11 | import static com.cloudhopper.commons.gsm.DataCoding.CHAR_ENC_LATIN1; | |
| 12 | import static com.cloudhopper.commons.gsm.DataCoding.CHAR_ENC_UCS2; | |
| 13 | ||
| 14 | import java.util.Collections; | |
| 15 | import java.util.HashMap; | |
| 16 | import java.util.Map; | |
| 17 | ||
| 18 | import com.cloudhopper.commons.charset.Charset; | |
| 19 | import com.cloudhopper.commons.charset.CharsetUtil; | |
| 20 | import com.cloudhopper.commons.gsm.DataCoding; | |
| 21 | ||
| 22 | import fr.sii.ogham.sms.encoder.Encoded; | |
| 23 | import fr.sii.ogham.sms.sender.impl.cloudhopper.encoder.NamedCharset; | |
| 24 | import fr.sii.ogham.sms.sender.impl.cloudhopper.exception.DataCodingException; | |
| 25 | import fr.sii.ogham.sms.sender.impl.cloudhopper.exception.UnsupportedCharsetException; | |
| 26 | ||
| 27 | /** | |
| 28 |  * Provide a Data Coding Scheme according to charset used to encode the message. | |
| 29 |  * The resulting encoding is <b>Character Encoding Group</b>: | |
| 30 |  *  | |
| 31 |  * Bit 7 6 5 4 3 2 1 0<br> | |
| 32 |  * <br> | |
| 33 |  * Bits 7..4 contain the "Coding Group Bits" which control what values are | |
| 34 |  * contained in bits 3..0 OR even 5..0<br> | |
| 35 |  * <br> | |
| 36 |  * <b>0000: Character Encoding Group</b> | |
| 37 |  * <ul> | |
| 38 |  * <li>Bits 0,1,2,3 Represent 16 Language Encodings</li> | |
| 39 |  * </ul> | |
| 40 |  *  | |
| 41 |  *  | |
| 42 |  * @author Aurélien Baudet | |
| 43 |  * | |
| 44 |  */ | |
| 45 | public class CharsetMapToCharacterEncodingGroupDataCodingProvider implements DataCodingProvider { | |
| 46 | 	private final boolean failIfUnknown; | |
| 47 | 	private final Map<String, Byte> alphabetIndexedByCharsetName; | |
| 48 | ||
| 49 | 	/** | |
| 50 | 	 * Provides {@link DataCoding} based on the charset used to encode the | |
| 51 | 	 * message. | |
| 52 | 	 *  | |
| 53 | 	 * <p> | |
| 54 | 	 * The default map is used (charset name {@literal ->} alphabet): | |
| 55 | 	 * <ul> | |
| 56 | 	 * <li>{@link CharsetUtil#NAME_GSM7} {@literal ->} | |
| 57 | 	 * {@link DataCoding#CHAR_ENC_DEFAULT}</li> | |
| 58 | 	 * <li>{@link CharsetUtil#NAME_PACKED_GSM} {@literal ->} | |
| 59 | 	 * {@link DataCoding#CHAR_ENC_DEFAULT}</li> | |
| 60 | 	 * <li>{@link CharsetUtil#NAME_GSM} {@literal ->} | |
| 61 | 	 * {@link DataCoding#CHAR_ENC_8BIT}</li> | |
| 62 | 	 * <li>{@link CharsetUtil#NAME_GSM8} {@literal ->} | |
| 63 | 	 * {@link DataCoding#CHAR_ENC_8BIT}</li> | |
| 64 | 	 * <li>{@link CharsetUtil#NAME_ISO_8859_1} {@literal ->} | |
| 65 | 	 * {@link DataCoding#CHAR_ENC_LATIN1}</li> | |
| 66 | 	 * <li>{@link CharsetUtil#NAME_UCS_2} {@literal ->} | |
| 67 | 	 * {@link DataCoding#CHAR_ENC_UCS2}</li> | |
| 68 | 	 * </ul> | |
| 69 | 	 *  | |
| 70 | 	 * @param failIfUnknown | |
| 71 | 	 *            if true it throws {@link UnsupportedCharsetException}, if | |
| 72 | 	 *            false is returns null to let other | |
| 73 | 	 *            {@link DataCodingProvider}(s) being executed. | |
| 74 | 	 */ | |
| 75 | 	public CharsetMapToCharacterEncodingGroupDataCodingProvider(boolean failIfUnknown) { | |
| 76 | 		super(); | |
| 77 | 		this.failIfUnknown = failIfUnknown; | |
| 78 | 		this.alphabetIndexedByCharsetName = defaultMap(); | |
| 79 | 	} | |
| 80 | ||
| 81 | 	@Override | |
| 82 | 	public DataCoding provide(Encoded encoded) throws DataCodingException { | |
| 83 | 		NamedCharset charset = NamedCharset.from(encoded.getCharsetName()); | |
| 84 | 		Byte encoding = alphabetIndexedByCharsetName.get(charset.getCharsetName()); | |
| 85 | 4
1. provide : negated conditional → NO_COVERAGE 2. provide : negated conditional → TIMED_OUT 3. provide : negated conditional → KILLED 4. provide : negated conditional → KILLED | 		if (encoding == null) { | 
| 86 | 2
1. provide : negated conditional → NO_COVERAGE 2. provide : negated conditional → KILLED | 			if (failIfUnknown) { | 
| 87 | 				throw new UnsupportedCharsetException(encoded.getCharsetName() + " charset not supported for Character Encoding Group Data Coding Scheme", encoded); | |
| 88 | 			} | |
| 89 | 			return null; | |
| 90 | 		} | |
| 91 | 4
1. provide : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::provide → NO_COVERAGE 2. provide : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::provide → TIMED_OUT 3. provide : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::provide → KILLED 4. provide : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::provide → KILLED | 		return DataCoding.createCharacterEncodingGroup(encoding); | 
| 92 | 	} | |
| 93 | ||
| 94 | 	/** | |
| 95 | 	 * Default mapping used to determine {@link DataCoding} encoding value from | |
| 96 | 	 * {@link Charset}: | |
| 97 | 	 * <ul> | |
| 98 | 	 * <li>{@link CharsetUtil#NAME_GSM7} {@literal ->} | |
| 99 | 	 * {@link DataCoding#CHAR_ENC_DEFAULT}</li> | |
| 100 | 	 * <li>{@link CharsetUtil#NAME_PACKED_GSM} {@literal ->} | |
| 101 | 	 * {@link DataCoding#CHAR_ENC_DEFAULT}</li> | |
| 102 | 	 * <li>{@link CharsetUtil#NAME_GSM} {@literal ->} | |
| 103 | 	 * {@link DataCoding#CHAR_ENC_8BIT}</li> | |
| 104 | 	 * <li>{@link CharsetUtil#NAME_GSM8} {@literal ->} | |
| 105 | 	 * {@link DataCoding#CHAR_ENC_8BIT}</li> | |
| 106 | 	 * <li>{@link CharsetUtil#NAME_ISO_8859_1} {@literal ->} | |
| 107 | 	 * {@link DataCoding#CHAR_ENC_LATIN1}</li> | |
| 108 | 	 * <li>{@link CharsetUtil#NAME_UCS_2} {@literal ->} | |
| 109 | 	 * {@link DataCoding#CHAR_ENC_UCS2}</li> | |
| 110 | 	 * </ul> | |
| 111 | 	 *  | |
| 112 | 	 *  | |
| 113 | 	 * @return the mapping | |
| 114 | 	 */ | |
| 115 | 	public static Map<String, Byte> defaultMap() { | |
| 116 | 		Map<String, Byte> map = new HashMap<>(); | |
| 117 | 		// @formatter:off | |
| 118 | 		map.put(NAME_GSM, 			CHAR_ENC_8BIT); | |
| 119 | 		map.put(NAME_GSM8, 			CHAR_ENC_8BIT); | |
| 120 | 		// SMPP v3.3 defines 0 for GSM 7-bit packed. | |
| 121 | 		// Since SMPP v3.4, meaning of DCS=0 is ambiguous... | |
| 122 | 		// But it is the only possible value for GSM 7-bit packed  | |
| 123 | 		map.put(NAME_GSM7, 			CHAR_ENC_DEFAULT); | |
| 124 | 		map.put(NAME_PACKED_GSM, 	CHAR_ENC_DEFAULT); | |
| 125 | 		map.put(NAME_ISO_8859_1, 	CHAR_ENC_LATIN1); | |
| 126 | 		map.put(NAME_UCS_2, 		CHAR_ENC_UCS2); | |
| 127 | 		// TODO: if other charset are used => which data coding values to use ? Where to find the information ??? | |
| 128 | //		map.put(CharsetUtil.NAME_AIRWIDE_GSM, DataCoding.); | |
| 129 | //		map.put(CharsetUtil.NAME_AIRWIDE_IA5, DataCoding.); | |
| 130 | //		map.put(CharsetUtil.NAME_ISO_8859_15, DataCoding.); | |
| 131 | //		map.put(CharsetUtil.NAME_MODIFIED_UTF8, DataCoding.); | |
| 132 | //		map.put(CharsetUtil.NAME_TMOBILENL_GSM, DataCoding.); | |
| 133 | //		map.put(CharsetUtil.NAME_UTF_8, DataCoding.); | |
| 134 | //		map.put(CharsetUtil.NAME_VFD2_GSM, DataCoding.); | |
| 135 | //		map.put(CharsetUtil.NAME_VFTR_GSM, DataCoding.); | |
| 136 | ||
| 137 | 		 | |
| 138 | //		map.put(CharsetUtil.NAME_GSM, 		DataCoding.CHAR_ENC_8BIT); | |
| 139 | //		map.put(CharsetUtil.NAME_GSM8, 		DataCoding.CHAR_ENC_8BIT); | |
| 140 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_8BITA); | |
| 141 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_CYRLLIC); | |
| 142 | //		map.put(CharsetUtil.NAME_GSM7, 		DataCoding.CHAR_ENC_DEFAULT); | |
| 143 | //		map.put(CharsetUtil.NAME_PACKED_GSM, 		DataCoding.CHAR_ENC_DEFAULT); | |
| 144 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_EXKANJI); | |
| 145 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_HEBREW); | |
| 146 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_IA5); | |
| 147 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_JIS); | |
| 148 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_KSC5601); | |
| 149 | //		map.put(CharsetUtil.NAME_ISO_8859_1, 		DataCoding.CHAR_ENC_LATIN1); | |
| 150 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_MUSIC); | |
| 151 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_PICTO); | |
| 152 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_RSRVD); | |
| 153 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_RSRVD2); | |
| 154 | //		map.put(CharsetUtil., 		DataCoding.CHAR_ENC_RSRVD3); | |
| 155 | //		map.put(CharsetUtil.NAME_UCS_2, 		DataCoding.CHAR_ENC_UCS2); | |
| 156 | 		// @formatter:on | |
| 157 | 4
1. defaultMap : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::defaultMap → SURVIVED 2. defaultMap : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::defaultMap → TIMED_OUT 3. defaultMap : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::defaultMap → KILLED 4. defaultMap : replaced return value with null for fr/sii/ogham/sms/sender/impl/cloudhopper/preparator/CharsetMapToCharacterEncodingGroupDataCodingProvider::defaultMap → KILLED | 		return Collections.unmodifiableMap(map); | 
| 158 | 	} | |
| 159 | ||
| 160 | } | |
| Mutations | ||
| 85 | 1.1 2.2 3.3 4.4 | |
| 86 | 1.1 2.2 | |
| 91 | 1.1 2.2 3.3 4.4 | |
| 157 | 1.1 2.2 3.3 4.4 |