1 package net.sf.atmodem4j.core.gsm;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import java.util.Arrays;
32 import net.sf.atmodem4j.core.gsm.Pdu.EncodingException;
33
34 abstract class UserData {
35
36 public abstract Pdu.Encoding getEncoding();
37
38 public abstract void setText(String text);
39
40 public abstract String getText();
41
42 public abstract int getUserDataLength(int userDataHeaderLength);
43
44 public abstract void setBytes(byte[] data);
45
46 public abstract byte[] getBytes();
47
48 public abstract void decodePduData(byte[] data, int userDataLength,
49 int userDataHeaderLength);
50
51 public abstract String encodePduData(int userDataHeaderLength);
52
53 public static String formatOctet(int octet) {
54 return String.format("%02X", (octet & 0x00FF));
55 }
56
57
58 static class Text7Bit extends UserData {
59
60 static int[] getSplitPos(String messageText) throws
61 Pdu.EncodingException {
62 int[] chunks = new int[1];
63 int chunksize = 0;
64 int septetsize = 0;
65 for (int i = 0; i < messageText.length(); i++) {
66 Entry7BitEncoding e = Entry7BitEncoding.findByChar(messageText.
67 charAt(i));
68 if (e == null) {
69 throw new Pdu.EncodingException("Cant encode char " +
70 messageText.charAt(i));
71 }
72 if (e.isEscaped()) {
73 septetsize += 2;
74 if (chunksize >= 152) {
75 chunks[chunks.length - 1] = i;
76 chunks = Arrays.copyOf(chunks, chunks.length + 1);
77 chunksize = 0;
78 }
79 chunksize += 2;
80 } else {
81 septetsize++;
82 if (chunksize >= 153) {
83 chunks[chunks.length - 1] = i;
84 chunks = Arrays.copyOf(chunks, chunks.length + 1);
85 chunksize = 0;
86 }
87 chunksize++;
88 }
89 }
90 if (septetsize <= 160) {
91 return new int[]{messageText.length()};
92 }
93 if (chunksize > 0) {
94 chunks[chunks.length - 1] = messageText.length();
95 }
96 return chunks;
97 }
98 private String text;
99
100 public Pdu.Encoding getEncoding() {
101 return Pdu.Encoding.TEXT_7BIT;
102 }
103
104 @Override
105 public String getText() {
106 return text;
107 }
108
109 @Override
110 public void decodePduData(byte[] data, int userDataLength,
111 int userDataHeaderLength) {
112 StringBuilder sb = new StringBuilder(data.length * 8 / 7);
113
114 int bitPos = (userDataHeaderLength * 8) % 7;
115 int expectedtChars = userDataLength - calcBytesToSeptets(userDataHeaderLength);
116 if (bitPos != 0) {
117 bitPos -= 7;
118 }
119 int buffer = 0;
120 int currentChar = 0;
121 boolean escaped = false;
122
123 for (int pos = 0; pos < data.length; pos++) {
124
125 if (bitPos < 0) {
126
127 buffer |= (data[pos] & 0xFF) >> -bitPos;
128 } else {
129 buffer |= (data[pos] & 0xFF) << bitPos;
130 }
131 bitPos += 8;
132
133 while (bitPos >= 7) {
134 currentChar = buffer & 0x7F;
135 buffer >>= 7;
136 bitPos -= 7;
137
138 if (escaped) {
139 escaped = false;
140 sb.append(Entry7BitEncoding.findByPdu(currentChar |
141 Entry7BitEncoding.ESC_SHORT).c);
142 } else {
143 escaped = currentChar ==
144 Entry7BitEncoding.ESC_IN_PDU_OCTET;
145 if (!escaped) {
146 sb.append(Entry7BitEncoding.findByPdu(currentChar).c);
147 }
148 }
149 if (sb.length() == expectedtChars) {
150 if (pos != data.length - 1) {
151 throw new RuntimeException(String.format("expectedtChars %d reached, but pos %d mismatch length %d", expectedtChars, pos, data.length -1));
152 }
153 break;
154 }
155 }
156 if (sb.length() == expectedtChars) {
157 if (pos != data.length - 1) {
158 throw new RuntimeException(String.format("expectedtChars %d reached, but pos %d mismatch length %d", expectedtChars, pos, data.length -1));
159 }
160 }
161 }
162 text = sb.toString();
163 }
164
165 @Override
166 public void setText(String text) {
167 this.text = text;
168 }
169
170 int calcBytesToSeptets(int lengthInBytes) {
171 return (lengthInBytes * 8) / 7 + (((lengthInBytes * 8) % 7) > 0 ? 1 : 0);
172 }
173
174 @Override
175 public int getUserDataLength(int userDataHeaderLength) {
176 try {
177 return getSeptets() + calcBytesToSeptets(userDataHeaderLength);
178 } catch (EncodingException ex) {
179 throw new RuntimeException(ex);
180 }
181 }
182
183 @Override
184 public void setBytes(byte[] data) {
185 throw new UnsupportedOperationException("Not supported yet.");
186 }
187
188 @Override
189 public byte[] getBytes() {
190 throw new UnsupportedOperationException("Not supported yet.");
191 }
192
193 private int getSeptets() throws Pdu.EncodingException {
194 int result = 0;
195 for (int i = 0; i < text.length(); i++) {
196 Entry7BitEncoding e = Entry7BitEncoding.findByChar(
197 text.charAt(i));
198 if (e == null) {
199 throw new Pdu.EncodingException("Cant encode char " +
200 text.charAt(i));
201 }
202 if (e.isEscaped()) {
203 result += 2;
204 } else {
205 result++;
206 }
207 }
208 return result;
209 }
210
211 @Override
212 public String encodePduData(int userDataHeaderLength) {
213
214 StringBuilder sb = new StringBuilder();
215 int bitPos = 7 - (userDataHeaderLength * 8) % 7;
216 if (bitPos == 7) {
217 bitPos = 0;
218 }
219 int octet = 0;
220 int currentChar;
221 for (int pos = 0; pos < text.length(); pos++) {
222
223 Entry7BitEncoding e = Entry7BitEncoding.findByChar(
224 text.charAt(pos));
225 if (e == null) {
226 throw new RuntimeException("Cant encode char " +
227 text.charAt(pos));
228 }
229 if (e.isEscaped()) {
230 currentChar = e.ESC_IN_PDU_OCTET;
231 currentChar <<= bitPos;
232 octet += currentChar;
233 bitPos += 7;
234
235 currentChar = e.pdu & 0x00FF;
236 currentChar <<= bitPos;
237 octet += currentChar;
238 bitPos += 7;
239
240 } else {
241 currentChar = e.pdu;
242 currentChar <<= bitPos;
243 octet += currentChar;
244 bitPos += 7;
245 }
246
247
248 while (bitPos > 15) {
249 sb.append(shortToOctetString((short) octet));
250 octet >>= 16;
251 bitPos -= 16;
252 }
253
254 }
255
256 if (bitPos > 8) {
257 sb.append(shortToOctetString((short) octet));
258 octet >>= 16;
259 bitPos = 0;
260 }
261
262 if (bitPos > 0) {
263 sb.append(formatOctet(octet));
264 octet >>= 8;
265 bitPos = 0;
266 }
267
268 return sb.toString();
269 }
270 }
271
272 public static String shortToOctetString(short octet) {
273 return String.format("%02X%02X", (octet & 0x00FF), ((octet >> 8) &
274 0x00FF));
275 }
276
277 static class Text16Bit extends UserData {
278
279 static Iterable<UserData> split(String messageText) {
280 throw new UnsupportedOperationException("Not yet implemented");
281 }
282 private String text;
283
284 public Pdu.Encoding getEncoding() {
285 return Pdu.Encoding.TEXT_16BIT;
286 }
287
288 @Override
289 public String getText() {
290 return text;
291 }
292
293 @Override
294 public void decodePduData(byte[] data, int userDataLength,
295 int userDataHeaderLength) {
296 throw new UnsupportedOperationException("Not supported yet.");
297 }
298
299 @Override
300 public void setText(String text) {
301 throw new UnsupportedOperationException("Not supported yet.");
302 }
303
304 @Override
305 public int getUserDataLength(int userDataHeaderLength) {
306 throw new UnsupportedOperationException("Not supported yet.");
307 }
308
309 @Override
310 public void setBytes(byte[] data) {
311 throw new UnsupportedOperationException("Not supported yet.");
312 }
313
314 @Override
315 public byte[] getBytes() {
316 throw new UnsupportedOperationException("Not supported yet.");
317 }
318
319 @Override
320 public String encodePduData(int userDataHeaderLength) {
321 throw new UnsupportedOperationException("Not supported yet.");
322 }
323 }
324
325 static class Data8Bit extends UserData {
326
327 private byte[] data;
328
329 public Pdu.Encoding getEncoding() {
330 return Pdu.Encoding.DATA_8BIT;
331 }
332
333 @Override
334 public String getText() {
335 throw new UnsupportedOperationException("Not supported yet.");
336 }
337
338 @Override
339 public void decodePduData(byte[] data, int userDataLength,
340 int userDataHeaderLength) {
341 throw new UnsupportedOperationException("Not supported yet.");
342 }
343
344 @Override
345 public void setText(String text) {
346 throw new UnsupportedOperationException("Not supported yet.");
347 }
348
349 @Override
350 public int getUserDataLength(int userDataHeaderLength) {
351 throw new UnsupportedOperationException("Not supported yet.");
352 }
353
354 @Override
355 public void setBytes(byte[] data) {
356 throw new UnsupportedOperationException("Not supported yet.");
357 }
358
359 @Override
360 public byte[] getBytes() {
361 throw new UnsupportedOperationException("Not supported yet.");
362 }
363
364 @Override
365 public String encodePduData(int userDataHeaderLength) {
366 throw new UnsupportedOperationException("Not supported yet.");
367 }
368 }
369 }