1/*
2 * Copyright (C) 2007 Esmertec AG.
3 * Copyright (C) 2007 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package android.support.v7.mms.pdu;
19
20import java.util.ArrayList;
21import java.util.HashMap;
22
23public class PduHeaders {
24    /**
25     * All pdu header fields.
26     */
27    public static final int BCC                             = 0x81;
28    public static final int CC                              = 0x82;
29    public static final int CONTENT_LOCATION                = 0x83;
30    public static final int CONTENT_TYPE                    = 0x84;
31    public static final int DATE                            = 0x85;
32    public static final int DELIVERY_REPORT                 = 0x86;
33    public static final int DELIVERY_TIME                   = 0x87;
34    public static final int EXPIRY                          = 0x88;
35    public static final int FROM                            = 0x89;
36    public static final int MESSAGE_CLASS                   = 0x8A;
37    public static final int MESSAGE_ID                      = 0x8B;
38    public static final int MESSAGE_TYPE                    = 0x8C;
39    public static final int MMS_VERSION                     = 0x8D;
40    public static final int MESSAGE_SIZE                    = 0x8E;
41    public static final int PRIORITY                        = 0x8F;
42
43    public static final int READ_REPLY                      = 0x90;
44    public static final int READ_REPORT                     = 0x90;
45    public static final int REPORT_ALLOWED                  = 0x91;
46    public static final int RESPONSE_STATUS                 = 0x92;
47    public static final int RESPONSE_TEXT                   = 0x93;
48    public static final int SENDER_VISIBILITY               = 0x94;
49    public static final int STATUS                          = 0x95;
50    public static final int SUBJECT                         = 0x96;
51    public static final int TO                              = 0x97;
52    public static final int TRANSACTION_ID                  = 0x98;
53    public static final int RETRIEVE_STATUS                 = 0x99;
54    public static final int RETRIEVE_TEXT                   = 0x9A;
55    public static final int READ_STATUS                     = 0x9B;
56    public static final int REPLY_CHARGING                  = 0x9C;
57    public static final int REPLY_CHARGING_DEADLINE         = 0x9D;
58    public static final int REPLY_CHARGING_ID               = 0x9E;
59    public static final int REPLY_CHARGING_SIZE             = 0x9F;
60
61    public static final int PREVIOUSLY_SENT_BY              = 0xA0;
62    public static final int PREVIOUSLY_SENT_DATE            = 0xA1;
63    public static final int STORE                           = 0xA2;
64    public static final int MM_STATE                        = 0xA3;
65    public static final int MM_FLAGS                        = 0xA4;
66    public static final int STORE_STATUS                    = 0xA5;
67    public static final int STORE_STATUS_TEXT               = 0xA6;
68    public static final int STORED                          = 0xA7;
69    public static final int ATTRIBUTES                      = 0xA8;
70    public static final int TOTALS                          = 0xA9;
71    public static final int MBOX_TOTALS                     = 0xAA;
72    public static final int QUOTAS                          = 0xAB;
73    public static final int MBOX_QUOTAS                     = 0xAC;
74    public static final int MESSAGE_COUNT                   = 0xAD;
75    public static final int CONTENT                         = 0xAE;
76    public static final int START                           = 0xAF;
77
78    public static final int ADDITIONAL_HEADERS              = 0xB0;
79    public static final int DISTRIBUTION_INDICATOR          = 0xB1;
80    public static final int ELEMENT_DESCRIPTOR              = 0xB2;
81    public static final int LIMIT                           = 0xB3;
82    public static final int RECOMMENDED_RETRIEVAL_MODE      = 0xB4;
83    public static final int RECOMMENDED_RETRIEVAL_MODE_TEXT = 0xB5;
84    public static final int STATUS_TEXT                     = 0xB6;
85    public static final int APPLIC_ID                       = 0xB7;
86    public static final int REPLY_APPLIC_ID                 = 0xB8;
87    public static final int AUX_APPLIC_ID                   = 0xB9;
88    public static final int CONTENT_CLASS                   = 0xBA;
89    public static final int DRM_CONTENT                     = 0xBB;
90    public static final int ADAPTATION_ALLOWED              = 0xBC;
91    public static final int REPLACE_ID                      = 0xBD;
92    public static final int CANCEL_ID                       = 0xBE;
93    public static final int CANCEL_STATUS                   = 0xBF;
94
95    /**
96     * X-Mms-Message-Type field types.
97     */
98    public static final int MESSAGE_TYPE_SEND_REQ           = 0x80;
99    public static final int MESSAGE_TYPE_SEND_CONF          = 0x81;
100    public static final int MESSAGE_TYPE_NOTIFICATION_IND   = 0x82;
101    public static final int MESSAGE_TYPE_NOTIFYRESP_IND     = 0x83;
102    public static final int MESSAGE_TYPE_RETRIEVE_CONF      = 0x84;
103    public static final int MESSAGE_TYPE_ACKNOWLEDGE_IND    = 0x85;
104    public static final int MESSAGE_TYPE_DELIVERY_IND       = 0x86;
105    public static final int MESSAGE_TYPE_READ_REC_IND       = 0x87;
106    public static final int MESSAGE_TYPE_READ_ORIG_IND      = 0x88;
107    public static final int MESSAGE_TYPE_FORWARD_REQ        = 0x89;
108    public static final int MESSAGE_TYPE_FORWARD_CONF       = 0x8A;
109    public static final int MESSAGE_TYPE_MBOX_STORE_REQ     = 0x8B;
110    public static final int MESSAGE_TYPE_MBOX_STORE_CONF    = 0x8C;
111    public static final int MESSAGE_TYPE_MBOX_VIEW_REQ      = 0x8D;
112    public static final int MESSAGE_TYPE_MBOX_VIEW_CONF     = 0x8E;
113    public static final int MESSAGE_TYPE_MBOX_UPLOAD_REQ    = 0x8F;
114    public static final int MESSAGE_TYPE_MBOX_UPLOAD_CONF   = 0x90;
115    public static final int MESSAGE_TYPE_MBOX_DELETE_REQ    = 0x91;
116    public static final int MESSAGE_TYPE_MBOX_DELETE_CONF   = 0x92;
117    public static final int MESSAGE_TYPE_MBOX_DESCR         = 0x93;
118    public static final int MESSAGE_TYPE_DELETE_REQ         = 0x94;
119    public static final int MESSAGE_TYPE_DELETE_CONF        = 0x95;
120    public static final int MESSAGE_TYPE_CANCEL_REQ         = 0x96;
121    public static final int MESSAGE_TYPE_CANCEL_CONF        = 0x97;
122
123    /**
124     *  X-Mms-Delivery-Report |
125     *  X-Mms-Read-Report |
126     *  X-Mms-Report-Allowed |
127     *  X-Mms-Sender-Visibility |
128     *  X-Mms-Store |
129     *  X-Mms-Stored |
130     *  X-Mms-Totals |
131     *  X-Mms-Quotas |
132     *  X-Mms-Distribution-Indicator |
133     *  X-Mms-DRM-Content |
134     *  X-Mms-Adaptation-Allowed |
135     *  field types.
136     */
137    public static final int VALUE_YES                       = 0x80;
138    public static final int VALUE_NO                        = 0x81;
139
140    /**
141     *  Delivery-Time |
142     *  Expiry and Reply-Charging-Deadline |
143     *  field type components.
144     */
145    public static final int VALUE_ABSOLUTE_TOKEN            = 0x80;
146    public static final int VALUE_RELATIVE_TOKEN            = 0x81;
147
148    /**
149     * X-Mms-MMS-Version field types.
150     */
151    public static final int MMS_VERSION_1_3                 = ((1 << 4) | 3);
152    public static final int MMS_VERSION_1_2                 = ((1 << 4) | 2);
153    public static final int MMS_VERSION_1_1                 = ((1 << 4) | 1);
154    public static final int MMS_VERSION_1_0                 = ((1 << 4) | 0);
155
156    // Current version is 1.2.
157    public static final int CURRENT_MMS_VERSION             = MMS_VERSION_1_2;
158
159    /**
160     *  From field type components.
161     */
162    public static final int FROM_ADDRESS_PRESENT_TOKEN      = 0x80;
163    public static final int FROM_INSERT_ADDRESS_TOKEN       = 0x81;
164
165    public static final String FROM_ADDRESS_PRESENT_TOKEN_STR = "address-present-token";
166    public static final String FROM_INSERT_ADDRESS_TOKEN_STR = "insert-address-token";
167
168    /**
169     *  X-Mms-Status Field.
170     */
171    public static final int STATUS_EXPIRED                  = 0x80;
172    public static final int STATUS_RETRIEVED                = 0x81;
173    public static final int STATUS_REJECTED                 = 0x82;
174    public static final int STATUS_DEFERRED                 = 0x83;
175    public static final int STATUS_UNRECOGNIZED             = 0x84;
176    public static final int STATUS_INDETERMINATE            = 0x85;
177    public static final int STATUS_FORWARDED                = 0x86;
178    public static final int STATUS_UNREACHABLE              = 0x87;
179
180    /**
181     *  MM-Flags field type components.
182     */
183    public static final int MM_FLAGS_ADD_TOKEN              = 0x80;
184    public static final int MM_FLAGS_REMOVE_TOKEN           = 0x81;
185    public static final int MM_FLAGS_FILTER_TOKEN           = 0x82;
186
187    /**
188     *  X-Mms-Message-Class field types.
189     */
190    public static final int MESSAGE_CLASS_PERSONAL          = 0x80;
191    public static final int MESSAGE_CLASS_ADVERTISEMENT     = 0x81;
192    public static final int MESSAGE_CLASS_INFORMATIONAL     = 0x82;
193    public static final int MESSAGE_CLASS_AUTO              = 0x83;
194
195    public static final String MESSAGE_CLASS_PERSONAL_STR = "personal";
196    public static final String MESSAGE_CLASS_ADVERTISEMENT_STR = "advertisement";
197    public static final String MESSAGE_CLASS_INFORMATIONAL_STR = "informational";
198    public static final String MESSAGE_CLASS_AUTO_STR = "auto";
199
200    /**
201     *  X-Mms-Priority field types.
202     */
203    public static final int PRIORITY_LOW                    = 0x80;
204    public static final int PRIORITY_NORMAL                 = 0x81;
205    public static final int PRIORITY_HIGH                   = 0x82;
206
207    /**
208     *  X-Mms-Response-Status field types.
209     */
210    public static final int RESPONSE_STATUS_OK                   = 0x80;
211    public static final int RESPONSE_STATUS_ERROR_UNSPECIFIED    = 0x81;
212    public static final int RESPONSE_STATUS_ERROR_SERVICE_DENIED = 0x82;
213
214    public static final int RESPONSE_STATUS_ERROR_MESSAGE_FORMAT_CORRUPT     = 0x83;
215    public static final int RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED = 0x84;
216
217    public static final int RESPONSE_STATUS_ERROR_MESSAGE_NOT_FOUND    = 0x85;
218    public static final int RESPONSE_STATUS_ERROR_NETWORK_PROBLEM      = 0x86;
219    public static final int RESPONSE_STATUS_ERROR_CONTENT_NOT_ACCEPTED = 0x87;
220    public static final int RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE  = 0x88;
221    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE    = 0xC0;
222
223    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_SENDNG_ADDRESS_UNRESOLVED = 0xC1;
224    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND         = 0xC2;
225    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM           = 0xC3;
226    public static final int RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS           = 0xC4;
227
228    public static final int RESPONSE_STATUS_ERROR_PERMANENT_FAILURE                             = 0xE0;
229    public static final int RESPONSE_STATUS_ERROR_PERMANENT_SERVICE_DENIED                      = 0xE1;
230    public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT              = 0xE2;
231    public static final int RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED          = 0xE3;
232    public static final int RESPONSE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND                   = 0xE4;
233    public static final int RESPONSE_STATUS_ERROR_PERMANENT_CONTENT_NOT_ACCEPTED                = 0xE5;
234    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_LIMITATIONS_NOT_MET  = 0xE6;
235    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_REQUEST_NOT_ACCEPTED = 0xE6;
236    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_FORWARDING_DENIED    = 0xE8;
237    public static final int RESPONSE_STATUS_ERROR_PERMANENT_REPLY_CHARGING_NOT_SUPPORTED        = 0xE9;
238    public static final int RESPONSE_STATUS_ERROR_PERMANENT_ADDRESS_HIDING_NOT_SUPPORTED        = 0xEA;
239    public static final int RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID                     = 0xEB;
240    public static final int RESPONSE_STATUS_ERROR_PERMANENT_END                                 = 0xFF;
241
242    /**
243     *  X-Mms-Retrieve-Status field types.
244     */
245    public static final int RETRIEVE_STATUS_OK                                  = 0x80;
246    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE             = 0xC0;
247    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_MESSAGE_NOT_FOUND   = 0xC1;
248    public static final int RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM     = 0xC2;
249    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE             = 0xE0;
250    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_SERVICE_DENIED      = 0xE1;
251    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND   = 0xE2;
252    public static final int RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED = 0xE3;
253    public static final int RETRIEVE_STATUS_ERROR_END                           = 0xFF;
254
255    /**
256     *  X-Mms-Sender-Visibility field types.
257     */
258    public static final int SENDER_VISIBILITY_HIDE          = 0x80;
259    public static final int SENDER_VISIBILITY_SHOW          = 0x81;
260
261    /**
262     *  X-Mms-Read-Status field types.
263     */
264    public static final int READ_STATUS_READ                        = 0x80;
265    public static final int READ_STATUS__DELETED_WITHOUT_BEING_READ = 0x81;
266
267    /**
268     *  X-Mms-Cancel-Status field types.
269     */
270    public static final int CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED = 0x80;
271    public static final int CANCEL_STATUS_REQUEST_CORRUPTED             = 0x81;
272
273    /**
274     *  X-Mms-Reply-Charging field types.
275     */
276    public static final int REPLY_CHARGING_REQUESTED           = 0x80;
277    public static final int REPLY_CHARGING_REQUESTED_TEXT_ONLY = 0x81;
278    public static final int REPLY_CHARGING_ACCEPTED            = 0x82;
279    public static final int REPLY_CHARGING_ACCEPTED_TEXT_ONLY  = 0x83;
280
281    /**
282     *  X-Mms-MM-State field types.
283     */
284    public static final int MM_STATE_DRAFT                  = 0x80;
285    public static final int MM_STATE_SENT                   = 0x81;
286    public static final int MM_STATE_NEW                    = 0x82;
287    public static final int MM_STATE_RETRIEVED              = 0x83;
288    public static final int MM_STATE_FORWARDED              = 0x84;
289
290    /**
291     * X-Mms-Recommended-Retrieval-Mode field types.
292     */
293    public static final int RECOMMENDED_RETRIEVAL_MODE_MANUAL = 0x80;
294
295    /**
296     *  X-Mms-Content-Class field types.
297     */
298    public static final int CONTENT_CLASS_TEXT              = 0x80;
299    public static final int CONTENT_CLASS_IMAGE_BASIC       = 0x81;
300    public static final int CONTENT_CLASS_IMAGE_RICH        = 0x82;
301    public static final int CONTENT_CLASS_VIDEO_BASIC       = 0x83;
302    public static final int CONTENT_CLASS_VIDEO_RICH        = 0x84;
303    public static final int CONTENT_CLASS_MEGAPIXEL         = 0x85;
304    public static final int CONTENT_CLASS_CONTENT_BASIC     = 0x86;
305    public static final int CONTENT_CLASS_CONTENT_RICH      = 0x87;
306
307    /**
308     *  X-Mms-Store-Status field types.
309     */
310    public static final int STORE_STATUS_SUCCESS                                = 0x80;
311    public static final int STORE_STATUS_ERROR_TRANSIENT_FAILURE                = 0xC0;
312    public static final int STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM        = 0xC1;
313    public static final int STORE_STATUS_ERROR_PERMANENT_FAILURE                = 0xE0;
314    public static final int STORE_STATUS_ERROR_PERMANENT_SERVICE_DENIED         = 0xE1;
315    public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_FORMAT_CORRUPT = 0xE2;
316    public static final int STORE_STATUS_ERROR_PERMANENT_MESSAGE_NOT_FOUND      = 0xE3;
317    public static final int STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL             = 0xE4;
318    public static final int STORE_STATUS_ERROR_END                              = 0xFF;
319
320    /**
321     * The map contains the value of all headers.
322     */
323    private HashMap<Integer, Object> mHeaderMap = null;
324
325    /**
326     * Constructor of PduHeaders.
327     */
328    public PduHeaders() {
329        mHeaderMap = new HashMap<Integer, Object>();
330    }
331
332    /**
333     * Get octet value by header field.
334     *
335     * @param field the field
336     * @return the octet value of the pdu header
337     *          with specified header field. Return 0 if
338     *          the value is not set.
339     */
340    protected int getOctet(int field) {
341        Integer octet = (Integer) mHeaderMap.get(field);
342        if (null == octet) {
343            return 0;
344        }
345
346        return octet;
347    }
348
349    /**
350     * Set octet value to pdu header by header field.
351     *
352     * @param value the value
353     * @param field the field
354     * @throws InvalidHeaderValueException if the value is invalid.
355     */
356    protected void setOctet(int value, int field)
357            throws InvalidHeaderValueException{
358        /**
359         * Check whether this field can be set for specific
360         * header and check validity of the field.
361         */
362        switch (field) {
363            case REPORT_ALLOWED:
364            case ADAPTATION_ALLOWED:
365            case DELIVERY_REPORT:
366            case DRM_CONTENT:
367            case DISTRIBUTION_INDICATOR:
368            case QUOTAS:
369            case READ_REPORT:
370            case STORE:
371            case STORED:
372            case TOTALS:
373            case SENDER_VISIBILITY:
374                if ((VALUE_YES != value) && (VALUE_NO != value)) {
375                    // Invalid value.
376                    throw new InvalidHeaderValueException("Invalid Octet value!");
377                }
378                break;
379            case READ_STATUS:
380                if ((READ_STATUS_READ != value) &&
381                        (READ_STATUS__DELETED_WITHOUT_BEING_READ != value)) {
382                    // Invalid value.
383                    throw new InvalidHeaderValueException("Invalid Octet value!");
384                }
385                break;
386            case CANCEL_STATUS:
387                if ((CANCEL_STATUS_REQUEST_SUCCESSFULLY_RECEIVED != value) &&
388                        (CANCEL_STATUS_REQUEST_CORRUPTED != value)) {
389                    // Invalid value.
390                    throw new InvalidHeaderValueException("Invalid Octet value!");
391                }
392                break;
393            case PRIORITY:
394                if ((value < PRIORITY_LOW) || (value > PRIORITY_HIGH)) {
395                    // Invalid value.
396                    throw new InvalidHeaderValueException("Invalid Octet value!");
397                }
398                break;
399            case STATUS:
400                if ((value < STATUS_EXPIRED) || (value > STATUS_UNREACHABLE)) {
401                    // Invalid value.
402                    throw new InvalidHeaderValueException("Invalid Octet value!");
403                }
404                break;
405            case REPLY_CHARGING:
406                if ((value < REPLY_CHARGING_REQUESTED)
407                        || (value > REPLY_CHARGING_ACCEPTED_TEXT_ONLY)) {
408                    // Invalid value.
409                    throw new InvalidHeaderValueException("Invalid Octet value!");
410                }
411                break;
412            case MM_STATE:
413                if ((value < MM_STATE_DRAFT) || (value > MM_STATE_FORWARDED)) {
414                    // Invalid value.
415                    throw new InvalidHeaderValueException("Invalid Octet value!");
416                }
417                break;
418            case RECOMMENDED_RETRIEVAL_MODE:
419                if (RECOMMENDED_RETRIEVAL_MODE_MANUAL != value) {
420                    // Invalid value.
421                    throw new InvalidHeaderValueException("Invalid Octet value!");
422                }
423                break;
424            case CONTENT_CLASS:
425                if ((value < CONTENT_CLASS_TEXT)
426                        || (value > CONTENT_CLASS_CONTENT_RICH)) {
427                    // Invalid value.
428                    throw new InvalidHeaderValueException("Invalid Octet value!");
429                }
430                break;
431            case RETRIEVE_STATUS:
432                // According to oma-ts-mms-enc-v1_3, section 7.3.50, we modify the invalid value.
433                if ((value > RETRIEVE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
434                        (value < RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE)) {
435                    value = RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE;
436                } else if ((value > RETRIEVE_STATUS_ERROR_PERMANENT_CONTENT_UNSUPPORTED) &&
437                        (value <= RETRIEVE_STATUS_ERROR_END)) {
438                    value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
439                } else if ((value < RETRIEVE_STATUS_OK) ||
440                        ((value > RETRIEVE_STATUS_OK) &&
441                                (value < RETRIEVE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
442                                (value > RETRIEVE_STATUS_ERROR_END)) {
443                    value = RETRIEVE_STATUS_ERROR_PERMANENT_FAILURE;
444                }
445                break;
446            case STORE_STATUS:
447                // According to oma-ts-mms-enc-v1_3, section 7.3.58, we modify the invalid value.
448                if ((value > STORE_STATUS_ERROR_TRANSIENT_NETWORK_PROBLEM) &&
449                        (value < STORE_STATUS_ERROR_PERMANENT_FAILURE)) {
450                    value = STORE_STATUS_ERROR_TRANSIENT_FAILURE;
451                } else if ((value > STORE_STATUS_ERROR_PERMANENT_MMBOX_FULL) &&
452                        (value <= STORE_STATUS_ERROR_END)) {
453                    value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
454                } else if ((value < STORE_STATUS_SUCCESS) ||
455                        ((value > STORE_STATUS_SUCCESS) &&
456                                (value < STORE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
457                                (value > STORE_STATUS_ERROR_END)) {
458                    value = STORE_STATUS_ERROR_PERMANENT_FAILURE;
459                }
460                break;
461            case RESPONSE_STATUS:
462                // According to oma-ts-mms-enc-v1_3, section 7.3.48, we modify the invalid value.
463                if ((value > RESPONSE_STATUS_ERROR_TRANSIENT_PARTIAL_SUCCESS) &&
464                        (value < RESPONSE_STATUS_ERROR_PERMANENT_FAILURE)) {
465                    value = RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE;
466                } else if (((value > RESPONSE_STATUS_ERROR_PERMANENT_LACK_OF_PREPAID) &&
467                        (value <= RESPONSE_STATUS_ERROR_PERMANENT_END)) ||
468                        (value < RESPONSE_STATUS_OK) ||
469                        ((value > RESPONSE_STATUS_ERROR_UNSUPPORTED_MESSAGE) &&
470                                (value < RESPONSE_STATUS_ERROR_TRANSIENT_FAILURE)) ||
471                                (value > RESPONSE_STATUS_ERROR_PERMANENT_END)) {
472                    value = RESPONSE_STATUS_ERROR_PERMANENT_FAILURE;
473                }
474                break;
475            case MMS_VERSION:
476                if ((value < MMS_VERSION_1_0)|| (value > MMS_VERSION_1_3)) {
477                    value = CURRENT_MMS_VERSION; // Current version is the default value.
478                }
479                break;
480            case MESSAGE_TYPE:
481                if ((value < MESSAGE_TYPE_SEND_REQ) || (value > MESSAGE_TYPE_CANCEL_CONF)) {
482                    // Invalid value.
483                    throw new InvalidHeaderValueException("Invalid Octet value!");
484                }
485                break;
486            default:
487                // This header value should not be Octect.
488                throw new RuntimeException("Invalid header field!");
489        }
490        mHeaderMap.put(field, value);
491    }
492
493    /**
494     * Get TextString value by header field.
495     *
496     * @param field the field
497     * @return the TextString value of the pdu header
498     *          with specified header field
499     */
500    protected byte[] getTextString(int field) {
501        return (byte[]) mHeaderMap.get(field);
502    }
503
504    /**
505     * Set TextString value to pdu header by header field.
506     *
507     * @param value the value
508     * @param field the field
509     * @return the TextString value of the pdu header
510     *          with specified header field
511     * @throws NullPointerException if the value is null.
512     */
513    protected void setTextString(byte[] value, int field) {
514        /**
515         * Check whether this field can be set for specific
516         * header and check validity of the field.
517         */
518        if (null == value) {
519            throw new NullPointerException();
520        }
521
522        switch (field) {
523            case TRANSACTION_ID:
524            case REPLY_CHARGING_ID:
525            case AUX_APPLIC_ID:
526            case APPLIC_ID:
527            case REPLY_APPLIC_ID:
528            case MESSAGE_ID:
529            case REPLACE_ID:
530            case CANCEL_ID:
531            case CONTENT_LOCATION:
532            case MESSAGE_CLASS:
533            case CONTENT_TYPE:
534                break;
535            default:
536                // This header value should not be Text-String.
537                throw new RuntimeException("Invalid header field!");
538        }
539        mHeaderMap.put(field, value);
540    }
541
542    /**
543     * Get EncodedStringValue value by header field.
544     *
545     * @param field the field
546     * @return the EncodedStringValue value of the pdu header
547     *          with specified header field
548     */
549    protected EncodedStringValue getEncodedStringValue(int field) {
550        return (EncodedStringValue) mHeaderMap.get(field);
551    }
552
553    /**
554     * Get TO, CC or BCC header value.
555     *
556     * @param field the field
557     * @return the EncodeStringValue array of the pdu header
558     *          with specified header field
559     */
560    protected EncodedStringValue[] getEncodedStringValues(int field) {
561        ArrayList<EncodedStringValue> list =
562                (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
563        if (null == list) {
564            return null;
565        }
566        EncodedStringValue[] values = new EncodedStringValue[list.size()];
567        return list.toArray(values);
568    }
569
570    /**
571     * Set EncodedStringValue value to pdu header by header field.
572     *
573     * @param value the value
574     * @param field the field
575     * @return the EncodedStringValue value of the pdu header
576     *          with specified header field
577     * @throws NullPointerException if the value is null.
578     */
579    protected void setEncodedStringValue(EncodedStringValue value, int field) {
580        /**
581         * Check whether this field can be set for specific
582         * header and check validity of the field.
583         */
584        if (null == value) {
585            throw new NullPointerException();
586        }
587
588        switch (field) {
589            case SUBJECT:
590            case RECOMMENDED_RETRIEVAL_MODE_TEXT:
591            case RETRIEVE_TEXT:
592            case STATUS_TEXT:
593            case STORE_STATUS_TEXT:
594            case RESPONSE_TEXT:
595            case FROM:
596            case PREVIOUSLY_SENT_BY:
597            case MM_FLAGS:
598                break;
599            default:
600                // This header value should not be Encoded-String-Value.
601                throw new RuntimeException("Invalid header field!");
602        }
603
604        mHeaderMap.put(field, value);
605    }
606
607    /**
608     * Set TO, CC or BCC header value.
609     *
610     * @param value the value
611     * @param field the field
612     * @return the EncodedStringValue value array of the pdu header
613     *          with specified header field
614     * @throws NullPointerException if the value is null.
615     */
616    protected void setEncodedStringValues(EncodedStringValue[] value, int field) {
617        /**
618         * Check whether this field can be set for specific
619         * header and check validity of the field.
620         */
621        if (null == value) {
622            throw new NullPointerException();
623        }
624
625        switch (field) {
626            case BCC:
627            case CC:
628            case TO:
629                break;
630            default:
631                // This header value should not be Encoded-String-Value.
632                throw new RuntimeException("Invalid header field!");
633        }
634
635        ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
636        for (int i = 0; i < value.length; i++) {
637            list.add(value[i]);
638        }
639        mHeaderMap.put(field, list);
640    }
641
642    /**
643     * Append one EncodedStringValue to another.
644     *
645     * @param value the EncodedStringValue to append
646     * @param field the field
647     * @throws NullPointerException if the value is null.
648     */
649    protected void appendEncodedStringValue(EncodedStringValue value,
650                                    int field) {
651        if (null == value) {
652            throw new NullPointerException();
653        }
654
655        switch (field) {
656            case BCC:
657            case CC:
658            case TO:
659                break;
660            default:
661                throw new RuntimeException("Invalid header field!");
662        }
663
664        ArrayList<EncodedStringValue> list =
665            (ArrayList<EncodedStringValue>) mHeaderMap.get(field);
666        if (null == list) {
667            list  = new ArrayList<EncodedStringValue>();
668        }
669        list.add(value);
670        mHeaderMap.put(field, list);
671    }
672
673    /**
674     * Get LongInteger value by header field.
675     *
676     * @param field the field
677     * @return the LongInteger value of the pdu header
678     *          with specified header field. if return -1, the
679     *          field is not existed in pdu header.
680     */
681    protected long getLongInteger(int field) {
682        Long longInteger = (Long) mHeaderMap.get(field);
683        if (null == longInteger) {
684            return -1;
685        }
686
687        return longInteger.longValue();
688    }
689
690    /**
691     * Set LongInteger value to pdu header by header field.
692     *
693     * @param value the value
694     * @param field the field
695     */
696    protected void setLongInteger(long value, int field) {
697        /**
698         * Check whether this field can be set for specific
699         * header and check validity of the field.
700         */
701        switch (field) {
702            case DATE:
703            case REPLY_CHARGING_SIZE:
704            case MESSAGE_SIZE:
705            case MESSAGE_COUNT:
706            case START:
707            case LIMIT:
708            case DELIVERY_TIME:
709            case EXPIRY:
710            case REPLY_CHARGING_DEADLINE:
711            case PREVIOUSLY_SENT_DATE:
712                break;
713            default:
714                // This header value should not be LongInteger.
715                throw new RuntimeException("Invalid header field!");
716        }
717        mHeaderMap.put(field, value);
718    }
719}
720