Home | History | Annotate | Download | only in map
      1 /*
      2 * Copyright (C) 2013 Samsung System LSI
      3 * Licensed under the Apache License, Version 2.0 (the "License");
      4 * you may not use this file except in compliance with the License.
      5 * You may obtain a copy of the License at
      6 *
      7 *      http://www.apache.org/licenses/LICENSE-2.0
      8 *
      9 * Unless required by applicable law or agreed to in writing, software
     10 * distributed under the License is distributed on an "AS IS" BASIS,
     11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 * See the License for the specific language governing permissions and
     13 * limitations under the License.
     14 */
     15 package com.android.bluetooth.map;
     16 
     17 import java.io.UnsupportedEncodingException;
     18 import java.nio.ByteBuffer;
     19 import java.nio.ByteOrder;
     20 import java.text.ParseException;
     21 import java.text.SimpleDateFormat;
     22 import java.util.Arrays;
     23 import java.util.Date;
     24 
     25 import android.util.Log;
     26 
     27 /**
     28  * This class encapsulates the appParams needed for MAP.
     29  */
     30 public class BluetoothMapAppParams {
     31 
     32     private static final String TAG = "BluetoothMapAppParams";
     33 
     34     private static final int MAX_LIST_COUNT           = 0x01;
     35     private static final int MAX_LIST_COUNT_LEN       = 0x02; //, 0x0000, 0xFFFF),
     36     private static final int START_OFFSET             = 0x02;
     37     private static final int START_OFFSET_LEN         = 0x02; //, 0x0000, 0xFFFF),
     38     private static final int FILTER_MESSAGE_TYPE      = 0x03;
     39     private static final int FILTER_MESSAGE_TYPE_LEN  = 0x01; //, 0x0000, 0x000f),
     40     private static final int FILTER_PERIOD_BEGIN      = 0x04;
     41     private static final int FILTER_PERIOD_END        = 0x05;
     42     private static final int FILTER_READ_STATUS       = 0x06;
     43     private static final int FILTER_READ_STATUS_LEN   = 0x01; //, 0x0000, 0x0002),
     44     private static final int FILTER_RECIPIENT         = 0x07;
     45     private static final int FILTER_ORIGINATOR        = 0x08;
     46     private static final int FILTER_PRIORITY          = 0x09;
     47     private static final int FILTER_PRIORITY_LEN      = 0x01; //, 0x0000, 0x0002),
     48     private static final int ATTACHMENT               = 0x0A;
     49     private static final int ATTACHMENT_LEN           = 0x01; //, 0x0000, 0x0001),
     50     private static final int TRANSPARENT              = 0x0B;
     51     private static final int TRANSPARENT_LEN          = 0x01; //, 0x0000, 0x0001),
     52     private static final int RETRY                    = 0x0C;
     53     private static final int RETRY_LEN                = 0x01; //, 0x0000, 0x0001),
     54     private static final int NEW_MESSAGE              = 0x0D;
     55     private static final int NEW_MESSAGE_LEN          = 0x01; //, 0x0000, 0x0001),
     56     private static final int NOTIFICATION_STATUS      = 0x0E;
     57     private static final int NOTIFICATION_STATUS_LEN  = 0x01; //, 0x0000, 0xFFFF),
     58     private static final int MAS_INSTANCE_ID          = 0x0F;
     59     private static final int MAS_INSTANCE_ID_LEN      = 0x01; //, 0x0000, 0x00FF),
     60     private static final int PARAMETER_MASK           = 0x10;
     61     private static final int PARAMETER_MASK_LEN       = 0x04; //, 0x0000, 0x0000),
     62     private static final int FOLDER_LISTING_SIZE      = 0x11;
     63     private static final int FOLDER_LISTING_SIZE_LEN  = 0x02; //, 0x0000, 0xFFFF),
     64     private static final int MESSAGE_LISTING_SIZE     = 0x12;
     65     private static final int MESSAGE_LISTING_SIZE_LEN = 0x02; //, 0x0000, 0xFFFF),
     66     private static final int SUBJECT_LENGTH           = 0x13;
     67     private static final int SUBJECT_LENGTH_LEN       = 0x01; //, 0x0000, 0x00FF),
     68     private static final int CHARSET                  = 0x14;
     69     private static final int CHARSET_LEN              = 0x01; //, 0x0000, 0x0001),
     70     private static final int FRACTION_REQUEST         = 0x15;
     71     private static final int FRACTION_REQUEST_LEN     = 0x01; //, 0x0000, 0x0001),
     72     private static final int FRACTION_DELIVER         = 0x16;
     73     private static final int FRACTION_DELIVER_LEN     = 0x01; //, 0x0000, 0x0001),
     74     private static final int STATUS_INDICATOR         = 0x17;
     75     private static final int STATUS_INDICATOR_LEN     = 0x01; //, 0x0000, 0x0001),
     76     private static final int STATUS_VALUE             = 0x18;
     77     private static final int STATUS_VALUE_LEN         = 0x01; //, 0x0000, 0x0001),
     78     private static final int MSE_TIME                 = 0x19;
     79 
     80     public static final int INVALID_VALUE_PARAMETER = -1;
     81     public static final int NOTIFICATION_STATUS_NO = 0;
     82     public static final int NOTIFICATION_STATUS_YES = 1;
     83     public static final int STATUS_INDICATOR_READ = 0;
     84     public static final int STATUS_INDICATOR_DELETED = 1;
     85     public static final int STATUS_VALUE_YES = 1;
     86     public static final int STATUS_VALUE_NO = 0;
     87     public static final int CHARSET_NATIVE = 0;
     88     public static final int CHARSET_UTF8 = 1;
     89 
     90     private int maxListCount        = INVALID_VALUE_PARAMETER;
     91     private int startOffset         = INVALID_VALUE_PARAMETER;
     92     private int filterMessageType   = INVALID_VALUE_PARAMETER;
     93     private long filterPeriodBegin  = INVALID_VALUE_PARAMETER;
     94     private long filterPeriodEnd    = INVALID_VALUE_PARAMETER;
     95     private int filterReadStatus    = INVALID_VALUE_PARAMETER;
     96     private String filterRecipient   = null;
     97     private String filterOriginator  = null;
     98     private int filterPriority      = INVALID_VALUE_PARAMETER;
     99     private int attachment          = INVALID_VALUE_PARAMETER;
    100     private int transparent         = INVALID_VALUE_PARAMETER;
    101     private int retry               = INVALID_VALUE_PARAMETER;
    102     private int newMessage          = INVALID_VALUE_PARAMETER;
    103     private int notificationStatus  = INVALID_VALUE_PARAMETER;
    104     private int masInstanceId       = INVALID_VALUE_PARAMETER;
    105     private long parameterMask      = INVALID_VALUE_PARAMETER;
    106     private int folderListingSize   = INVALID_VALUE_PARAMETER;
    107     private int messageListingSize  = INVALID_VALUE_PARAMETER;
    108     private int subjectLength       = INVALID_VALUE_PARAMETER;
    109     private int charset             = INVALID_VALUE_PARAMETER;
    110     private int fractionRequest     = INVALID_VALUE_PARAMETER;
    111     private int fractionDeliver     = INVALID_VALUE_PARAMETER;
    112     private int statusIndicator     = INVALID_VALUE_PARAMETER;
    113     private int statusValue         = INVALID_VALUE_PARAMETER;
    114     private long mseTime            = INVALID_VALUE_PARAMETER;
    115 
    116     /**
    117      * Default constructor, used to build an application parameter object to be
    118      * encoded. By default the member variables will be initialized to
    119      * {@link INVALID_VALUE_PARAMETER} for values, and empty strings for String
    120      * typed members.
    121      */
    122     public BluetoothMapAppParams() {
    123     }
    124 
    125     /**
    126      * Creates an application parameter object based on a application parameter
    127      * OBEX header. The content of the {@link appParam} byte array will be
    128      * parsed, and its content will be stored in the member variables.
    129      * {@link INVALID_VALUE_PARAMETER} can be used to determine if a value is
    130      * set or not, where strings will be empty, if {@link appParam} did not
    131      * contain the parameter.
    132      *
    133      * @param appParams
    134      *            the byte array containing the application parameters OBEX
    135      *            header
    136      * @throws IllegalArgumentException
    137      *             when a parameter does not respect the valid ranges specified
    138      *             in the MAP spec.
    139      * @throws ParseException
    140      *             if a parameter string if formated incorrectly.
    141      */
    142     public BluetoothMapAppParams(final byte[] appParams)
    143                  throws IllegalArgumentException, ParseException {
    144         ParseParams(appParams);
    145     }
    146 
    147     /**
    148      * Parse an application parameter OBEX header stored in a ByteArray.
    149      *
    150      * @param appParams
    151      *            the byte array containing the application parameters OBEX
    152      *            header
    153      * @throws IllegalArgumentException
    154      *             when a parameter does not respect the valid ranges specified
    155      *             in the MAP spec.
    156      * @throws ParseException
    157      *             if a parameter string if formated incorrectly.
    158      */
    159     private void ParseParams(final byte[] appParams) throws ParseException,
    160               IllegalArgumentException {
    161         int i = 0;
    162         int tagId, tagLength;
    163         ByteBuffer appParamBuf = ByteBuffer.wrap(appParams);
    164         appParamBuf.order(ByteOrder.BIG_ENDIAN);
    165         while (i < appParams.length) {
    166             tagId = appParams[i++] & 0xff;     // Convert to unsigned to support values above 127
    167             tagLength = appParams[i++] & 0xff; // Convert to unsigned to support values above 127
    168             switch (tagId) {
    169             case MAX_LIST_COUNT:
    170                 if (tagLength != MAX_LIST_COUNT_LEN) {
    171                     Log.w(TAG, "MAX_LIST_COUNT: Wrong length received: " + tagLength
    172                                + " expected: " + MAX_LIST_COUNT_LEN);
    173                     break;
    174                 }
    175                 setMaxListCount(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    176                 break;
    177             case START_OFFSET:
    178                 if (tagLength != START_OFFSET_LEN) {
    179                     Log.w(TAG, "START_OFFSET: Wrong length received: " + tagLength + " expected: "
    180                                + START_OFFSET_LEN);
    181                     break;
    182                 }
    183                 setStartOffset(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    184                 break;
    185             case FILTER_MESSAGE_TYPE:
    186                 if (tagLength != FILTER_MESSAGE_TYPE_LEN) {
    187                     Log.w(TAG, "FILTER_MESSAGE_TYPE: Wrong length received: " + tagLength + " expected: "
    188                             + FILTER_MESSAGE_TYPE_LEN);
    189                     break;
    190                 }
    191                     setFilterMessageType(appParams[i] & 0x0f);
    192                 break;
    193             case FILTER_PERIOD_BEGIN:
    194                 if(tagLength != 0) {
    195                     setFilterPeriodBegin(new String(appParams, i, tagLength));
    196                 }
    197                 break;
    198             case FILTER_PERIOD_END:
    199                 if(tagLength != 0) {
    200                     setFilterPeriodEnd(new String(appParams, i, tagLength));
    201                 }
    202                 break;
    203             case FILTER_READ_STATUS:
    204                 if (tagLength != FILTER_READ_STATUS_LEN) {
    205                      Log.w(TAG, "FILTER_READ_STATUS: Wrong length received: " + tagLength + " expected: "
    206                              + FILTER_READ_STATUS_LEN);
    207                      break;
    208                  }
    209                 setFilterReadStatus(appParams[i] & 0x03); // Lower two bits
    210                 break;
    211             case FILTER_RECIPIENT:
    212                 setFilterRecipient(new String(appParams, i, tagLength));
    213                 break;
    214             case FILTER_ORIGINATOR:
    215                 setFilterOriginator(new String(appParams, i, tagLength));
    216                 break;
    217             case FILTER_PRIORITY:
    218                 if (tagLength != FILTER_PRIORITY_LEN) {
    219                      Log.w(TAG, "FILTER_PRIORITY: Wrong length received: " + tagLength + " expected: "
    220                              + FILTER_PRIORITY_LEN);
    221                      break;
    222                 }
    223                 setFilterPriority(appParams[i] & 0x03); // Lower two bits
    224                 break;
    225             case ATTACHMENT:
    226                 if (tagLength != ATTACHMENT_LEN) {
    227                      Log.w(TAG, "ATTACHMENT: Wrong length received: " + tagLength + " expected: "
    228                              + ATTACHMENT_LEN);
    229                      break;
    230                 }
    231                 setAttachment(appParams[i] & 0x01); // Lower bit
    232                 break;
    233             case TRANSPARENT:
    234                 if (tagLength != TRANSPARENT_LEN) {
    235                      Log.w(TAG, "TRANSPARENT: Wrong length received: " + tagLength + " expected: "
    236                              + TRANSPARENT_LEN);
    237                      break;
    238                 }
    239                 setTransparent(appParams[i] & 0x01); // Lower bit
    240                 break;
    241             case RETRY:
    242                 if (tagLength != RETRY_LEN) {
    243                      Log.w(TAG, "RETRY: Wrong length received: " + tagLength + " expected: "
    244                              + RETRY_LEN);
    245                      break;
    246                 }
    247                 setRetry(appParams[i] & 0x01); // Lower bit
    248                 break;
    249             case NEW_MESSAGE:
    250                 if (tagLength != NEW_MESSAGE_LEN) {
    251                      Log.w(TAG, "NEW_MESSAGE: Wrong length received: " + tagLength + " expected: "
    252                              + NEW_MESSAGE_LEN);
    253                      break;
    254                 }
    255                 setNewMessage(appParams[i] & 0x01); // Lower bit
    256                 break;
    257             case NOTIFICATION_STATUS:
    258                 if (tagLength != NOTIFICATION_STATUS_LEN) {
    259                      Log.w(TAG, "NOTIFICATION_STATUS: Wrong length received: " + tagLength + " expected: "
    260                              + NOTIFICATION_STATUS_LEN);
    261                      break;
    262                 }
    263                 setNotificationStatus(appParams[i] & 0x01); // Lower bit
    264                 break;
    265             case MAS_INSTANCE_ID:
    266                 if (tagLength != MAS_INSTANCE_ID_LEN) {
    267                     Log.w(TAG, "MAS_INSTANCE_ID: Wrong length received: " + tagLength + " expected: "
    268                             + MAS_INSTANCE_ID_LEN);
    269                     break;
    270                 }
    271                 setMasInstanceId(appParams[i] & 0xff);
    272                 break;
    273             case PARAMETER_MASK:
    274                 if (tagLength != PARAMETER_MASK_LEN) {
    275                     Log.w(TAG, "PARAMETER_MASK: Wrong length received: " + tagLength + " expected: "
    276                             + PARAMETER_MASK_LEN);
    277                     break;
    278                 }
    279                 setParameterMask(appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned
    280                 break;
    281             case FOLDER_LISTING_SIZE:
    282                 if (tagLength != FOLDER_LISTING_SIZE_LEN) {
    283                     Log.w(TAG, "FOLDER_LISTING_SIZE: Wrong length received: " + tagLength + " expected: "
    284                             + FOLDER_LISTING_SIZE_LEN);
    285                     break;
    286                 }
    287                 setFolderListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    288                 break;
    289             case MESSAGE_LISTING_SIZE:
    290                 if (tagLength != MESSAGE_LISTING_SIZE_LEN) {
    291                     Log.w(TAG, "MESSAGE_LISTING_SIZE: Wrong length received: " + tagLength + " expected: "
    292                             + MESSAGE_LISTING_SIZE_LEN);
    293                     break;
    294                 }
    295                 setMessageListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    296                 break;
    297             case SUBJECT_LENGTH:
    298                 if (tagLength != SUBJECT_LENGTH_LEN) {
    299                     Log.w(TAG, "SUBJECT_LENGTH: Wrong length received: " + tagLength + " expected: "
    300                             + SUBJECT_LENGTH_LEN);
    301                     break;
    302                 }
    303                 setSubjectLength(appParams[i] & 0xff);
    304                 break;
    305             case CHARSET:
    306                 if (tagLength != CHARSET_LEN) {
    307                     Log.w(TAG, "CHARSET: Wrong length received: " + tagLength + " expected: "
    308                             + CHARSET_LEN);
    309                     break;
    310                 }
    311                 setCharset(appParams[i] & 0x01); // Lower bit
    312                 break;
    313             case FRACTION_REQUEST:
    314                 if (tagLength != FRACTION_REQUEST_LEN) {
    315                     Log.w(TAG, "FRACTION_REQUEST: Wrong length received: " + tagLength + " expected: "
    316                             + FRACTION_REQUEST_LEN);
    317                     break;
    318                 }
    319                 setFractionRequest(appParams[i] & 0x01); // Lower bit
    320                 break;
    321             case FRACTION_DELIVER:
    322                 if (tagLength != FRACTION_DELIVER_LEN) {
    323                     Log.w(TAG, "FRACTION_DELIVER: Wrong length received: " + tagLength + " expected: "
    324                             + FRACTION_DELIVER_LEN);
    325                     break;
    326                 }
    327                 setFractionDeliver(appParams[i] & 0x01); // Lower bit
    328                 break;
    329             case STATUS_INDICATOR:
    330                 if (tagLength != STATUS_INDICATOR_LEN) {
    331                     Log.w(TAG, "STATUS_INDICATOR: Wrong length received: " + tagLength + " expected: "
    332                             + STATUS_INDICATOR_LEN);
    333                     break;
    334                 }
    335                 setStatusIndicator(appParams[i] & 0x01); // Lower bit
    336                 break;
    337             case STATUS_VALUE:
    338                 if (tagLength != STATUS_VALUE_LEN) {
    339                     Log.w(TAG, "STATUS_VALUER: Wrong length received: " + tagLength + " expected: "
    340                             + STATUS_VALUE_LEN);
    341                     break;
    342                 }
    343                 setStatusValue(appParams[i] & 0x01); // Lower bit
    344                 break;
    345             case MSE_TIME:
    346                 setMseTime(new String(appParams, i, tagLength));
    347                 break;
    348             default:
    349                 // Just skip unknown Tags, no need to report error
    350                 Log.w(TAG, "Unknown TagId received ( 0x" + Integer.toString(tagId, 16)
    351                            + "), skipping...");
    352                 break;
    353             }
    354             i += tagLength; // Offset to next TagId
    355         }
    356     }
    357 
    358     /**
    359      * Get the approximate length needed to store the appParameters in a byte
    360      * array.
    361      *
    362      * @return the length in bytes
    363      * @throws UnsupportedEncodingException
    364      *             if the platform does not support UTF-8 encoding.
    365      */
    366     private int getParamMaxLength() throws UnsupportedEncodingException {
    367         int length = 0;
    368         length += 25 * 2; // tagId + tagLength
    369         length += 27; // fixed sizes
    370         length += getFilterPeriodBegin() == INVALID_VALUE_PARAMETER ? 0 : 15;
    371         length += getFilterPeriodEnd() == INVALID_VALUE_PARAMETER ? 0 : 15;
    372         if (getFilterRecipient() != null)
    373             length += getFilterRecipient().getBytes("UTF-8").length;
    374         if (getFilterOriginator() != null)
    375             length += getFilterOriginator().getBytes("UTF-8").length;
    376         length += getMseTime() == INVALID_VALUE_PARAMETER ? 0 : 20;
    377         return length;
    378     }
    379 
    380     /**
    381      * Encode the application parameter object to a byte array.
    382      *
    383      * @return a byte Array representation of the application parameter object.
    384      * @throws UnsupportedEncodingException
    385      *             if the platform does not support UTF-8 encoding.
    386      */
    387     public byte[] EncodeParams() throws UnsupportedEncodingException {
    388         ByteBuffer appParamBuf = ByteBuffer.allocate(getParamMaxLength());
    389         appParamBuf.order(ByteOrder.BIG_ENDIAN);
    390         byte[] retBuf;
    391 
    392         if (getMaxListCount() != INVALID_VALUE_PARAMETER) {
    393             appParamBuf.put((byte) MAX_LIST_COUNT);
    394             appParamBuf.put((byte) MAX_LIST_COUNT_LEN);
    395             appParamBuf.putShort((short) getMaxListCount());
    396         }
    397         if (getStartOffset() != INVALID_VALUE_PARAMETER) {
    398             appParamBuf.put((byte) START_OFFSET);
    399             appParamBuf.put((byte) START_OFFSET_LEN);
    400             appParamBuf.putShort((short) getStartOffset());
    401         }
    402         if (getFilterMessageType() != INVALID_VALUE_PARAMETER) {
    403             appParamBuf.put((byte) FILTER_MESSAGE_TYPE);
    404             appParamBuf.put((byte) FILTER_MESSAGE_TYPE_LEN);
    405             appParamBuf.put((byte) getFilterMessageType());
    406         }
    407         if (getFilterPeriodBegin() != INVALID_VALUE_PARAMETER) {
    408             appParamBuf.put((byte) FILTER_PERIOD_BEGIN);
    409             appParamBuf.put((byte) getFilterPeriodBeginString().getBytes("UTF-8").length);
    410             appParamBuf.put(getFilterPeriodBeginString().getBytes("UTF-8"));
    411         }
    412         if (getFilterPeriodEnd() != INVALID_VALUE_PARAMETER) {
    413             appParamBuf.put((byte) FILTER_PERIOD_END);
    414             appParamBuf.put((byte) getFilterPeriodEndString().getBytes("UTF-8").length);
    415             appParamBuf.put(getFilterPeriodEndString().getBytes("UTF-8"));
    416         }
    417         if (getFilterReadStatus() != INVALID_VALUE_PARAMETER) {
    418             appParamBuf.put((byte) FILTER_READ_STATUS);
    419             appParamBuf.put((byte) FILTER_READ_STATUS_LEN);
    420             appParamBuf.put((byte) getFilterReadStatus());
    421         }
    422         if (getFilterRecipient() != null) {
    423             appParamBuf.put((byte) FILTER_RECIPIENT);
    424             appParamBuf.put((byte) getFilterRecipient().getBytes("UTF-8").length);
    425             appParamBuf.put(getFilterRecipient().getBytes("UTF-8"));
    426         }
    427         if (getFilterOriginator() != null) {
    428             appParamBuf.put((byte) FILTER_ORIGINATOR);
    429             appParamBuf.put((byte) getFilterOriginator().getBytes("UTF-8").length);
    430             appParamBuf.put(getFilterOriginator().getBytes("UTF-8"));
    431         }
    432         if (getFilterPriority() != INVALID_VALUE_PARAMETER) {
    433             appParamBuf.put((byte) FILTER_PRIORITY);
    434             appParamBuf.put((byte) FILTER_PRIORITY_LEN);
    435             appParamBuf.put((byte) getFilterPriority());
    436         }
    437         if (getAttachment() != INVALID_VALUE_PARAMETER) {
    438             appParamBuf.put((byte) ATTACHMENT);
    439             appParamBuf.put((byte) ATTACHMENT_LEN);
    440             appParamBuf.put((byte) getAttachment());
    441         }
    442         if (getTransparent() != INVALID_VALUE_PARAMETER) {
    443             appParamBuf.put((byte) TRANSPARENT);
    444             appParamBuf.put((byte) TRANSPARENT_LEN);
    445             appParamBuf.put((byte) getTransparent());
    446         }
    447         if (getRetry() != INVALID_VALUE_PARAMETER) {
    448             appParamBuf.put((byte) RETRY);
    449             appParamBuf.put((byte) RETRY_LEN);
    450             appParamBuf.put((byte) getRetry());
    451         }
    452         if (getNewMessage() != INVALID_VALUE_PARAMETER) {
    453             appParamBuf.put((byte) NEW_MESSAGE);
    454             appParamBuf.put((byte) NEW_MESSAGE_LEN);
    455             appParamBuf.put((byte) getNewMessage());
    456         }
    457         if (getNotificationStatus() != INVALID_VALUE_PARAMETER) {
    458             appParamBuf.put((byte) NOTIFICATION_STATUS);
    459             appParamBuf.put((byte) NOTIFICATION_STATUS_LEN);
    460             appParamBuf.putShort((short) getNotificationStatus());
    461         }
    462         if (getMasInstanceId() != INVALID_VALUE_PARAMETER) {
    463             appParamBuf.put((byte) MAS_INSTANCE_ID);
    464             appParamBuf.put((byte) MAS_INSTANCE_ID_LEN);
    465             appParamBuf.put((byte) getMasInstanceId());
    466         }
    467         if (getParameterMask() != INVALID_VALUE_PARAMETER) {
    468             appParamBuf.put((byte) PARAMETER_MASK);
    469             appParamBuf.put((byte) PARAMETER_MASK_LEN);
    470             appParamBuf.putInt((int) getParameterMask());
    471         }
    472         if (getFolderListingSize() != INVALID_VALUE_PARAMETER) {
    473             appParamBuf.put((byte) FOLDER_LISTING_SIZE);
    474             appParamBuf.put((byte) FOLDER_LISTING_SIZE_LEN);
    475             appParamBuf.putShort((short) getFolderListingSize());
    476         }
    477         if (getMessageListingSize() != INVALID_VALUE_PARAMETER) {
    478             appParamBuf.put((byte) MESSAGE_LISTING_SIZE);
    479             appParamBuf.put((byte) MESSAGE_LISTING_SIZE_LEN);
    480             appParamBuf.putShort((short) getMessageListingSize());
    481         }
    482         if (getSubjectLength() != INVALID_VALUE_PARAMETER) {
    483             appParamBuf.put((byte) SUBJECT_LENGTH);
    484             appParamBuf.put((byte) SUBJECT_LENGTH_LEN);
    485             appParamBuf.put((byte) getSubjectLength());
    486         }
    487         if (getCharset() != INVALID_VALUE_PARAMETER) {
    488             appParamBuf.put((byte) CHARSET);
    489             appParamBuf.put((byte) CHARSET_LEN);
    490             appParamBuf.put((byte) getCharset());
    491         }
    492         if (getFractionRequest() != INVALID_VALUE_PARAMETER) {
    493             appParamBuf.put((byte) FRACTION_REQUEST);
    494             appParamBuf.put((byte) FRACTION_REQUEST_LEN);
    495             appParamBuf.put((byte) getFractionRequest());
    496         }
    497         if (getFractionDeliver() != INVALID_VALUE_PARAMETER) {
    498             appParamBuf.put((byte) FRACTION_DELIVER);
    499             appParamBuf.put((byte) FRACTION_DELIVER_LEN);
    500             appParamBuf.put((byte) getFractionDeliver());
    501         }
    502         if (getStatusIndicator() != INVALID_VALUE_PARAMETER) {
    503             appParamBuf.put((byte) STATUS_INDICATOR);
    504             appParamBuf.put((byte) STATUS_INDICATOR_LEN);
    505             appParamBuf.put((byte) getStatusIndicator());
    506         }
    507         if (getStatusValue() != INVALID_VALUE_PARAMETER) {
    508             appParamBuf.put((byte) STATUS_VALUE);
    509             appParamBuf.put((byte) STATUS_VALUE_LEN);
    510             appParamBuf.put((byte) getStatusValue());
    511         }
    512         if (getMseTime() != INVALID_VALUE_PARAMETER) {
    513             appParamBuf.put((byte) MSE_TIME);
    514             appParamBuf.put((byte) getMseTimeString().getBytes("UTF-8").length);
    515             appParamBuf.put(getMseTimeString().getBytes("UTF-8"));
    516         }
    517         // We need to reduce the length of the array to match the content
    518         retBuf = Arrays.copyOfRange(appParamBuf.array(), appParamBuf.arrayOffset(),
    519                                     appParamBuf.arrayOffset() + appParamBuf.position());
    520         return retBuf;
    521     }
    522 
    523     public int getMaxListCount() {
    524         return maxListCount;
    525     }
    526 
    527     public void setMaxListCount(int maxListCount) throws IllegalArgumentException {
    528         if (maxListCount < 0 || maxListCount > 0xFFFF)
    529             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    530         this.maxListCount = maxListCount;
    531     }
    532 
    533     public int getStartOffset() {
    534         return startOffset;
    535     }
    536 
    537     public void setStartOffset(int startOffset) throws IllegalArgumentException {
    538         if (startOffset < 0 || startOffset > 0xFFFF)
    539             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    540         this.startOffset = startOffset;
    541     }
    542 
    543     public int getFilterMessageType() {
    544         return filterMessageType;
    545     }
    546 
    547     public void setFilterMessageType(int filterMessageType) throws IllegalArgumentException {
    548         if (filterMessageType < 0 || filterMessageType > 0x000F)
    549             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x000F");
    550         this.filterMessageType = filterMessageType;
    551     }
    552 
    553     public long getFilterPeriodBegin() {
    554         return filterPeriodBegin;
    555     }
    556 
    557     public String getFilterPeriodBeginString() {
    558         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    559         Date date = new Date(filterPeriodBegin);
    560         return format.format(date); // Format to YYYYMMDDTHHMMSS local time
    561     }
    562 
    563     public void setFilterPeriodBegin(long filterPeriodBegin) {
    564         this.filterPeriodBegin = filterPeriodBegin;
    565     }
    566 
    567     public void setFilterPeriodBegin(String filterPeriodBegin) throws ParseException {
    568         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    569         Date date = format.parse(filterPeriodBegin);
    570         this.filterPeriodBegin = date.getTime();
    571     }
    572 
    573     public long getFilterPeriodEnd() {
    574         return filterPeriodEnd;
    575     }
    576 
    577     public String getFilterPeriodEndString() {
    578         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    579         Date date = new Date(filterPeriodEnd);
    580         return format.format(date); // Format to YYYYMMDDTHHMMSS local time
    581     }
    582 
    583     public void setFilterPeriodEnd(long filterPeriodEnd) {
    584         this.filterPeriodEnd = filterPeriodEnd;
    585     }
    586 
    587     public void setFilterPeriodEnd(String filterPeriodEnd) throws ParseException {
    588         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    589         Date date = format.parse(filterPeriodEnd);
    590         this.filterPeriodEnd = date.getTime();
    591     }
    592 
    593     public int getFilterReadStatus() {
    594         return filterReadStatus;
    595     }
    596 
    597     public void setFilterReadStatus(int filterReadStatus) throws IllegalArgumentException {
    598         if (filterReadStatus < 0 || filterReadStatus > 0x0002)
    599             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002");
    600         this.filterReadStatus = filterReadStatus;
    601     }
    602 
    603     public String getFilterRecipient() {
    604         return filterRecipient;
    605     }
    606 
    607     public void setFilterRecipient(String filterRecipient) {
    608         this.filterRecipient = filterRecipient;
    609     }
    610 
    611     public String getFilterOriginator() {
    612         return filterOriginator;
    613     }
    614 
    615     public void setFilterOriginator(String filterOriginator) {
    616         this.filterOriginator = filterOriginator;
    617     }
    618 
    619     public int getFilterPriority() {
    620         return filterPriority;
    621     }
    622 
    623     public void setFilterPriority(int filterPriority) throws IllegalArgumentException {
    624         if (filterPriority < 0 || filterPriority > 0x0002)
    625             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002");
    626         this.filterPriority = filterPriority;
    627     }
    628 
    629     public int getAttachment() {
    630         return attachment;
    631     }
    632 
    633     public void setAttachment(int attachment) throws IllegalArgumentException {
    634         if (attachment < 0 || attachment > 0x0001)
    635             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    636         this.attachment = attachment;
    637     }
    638 
    639     public int getTransparent() {
    640         return transparent;
    641     }
    642 
    643     public void setTransparent(int transparent) throws IllegalArgumentException {
    644         if (transparent < 0 || transparent > 0x0001)
    645             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    646         this.transparent = transparent;
    647     }
    648 
    649     public int getRetry() {
    650         return retry;
    651     }
    652 
    653     public void setRetry(int retry) throws IllegalArgumentException {
    654         if (retry < 0 || retry > 0x0001)
    655             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    656         this.retry = retry;
    657     }
    658 
    659     public int getNewMessage() {
    660         return newMessage;
    661     }
    662 
    663     public void setNewMessage(int newMessage) throws IllegalArgumentException {
    664         if (newMessage < 0 || newMessage > 0x0001)
    665             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    666         this.newMessage = newMessage;
    667     }
    668 
    669     public int getNotificationStatus() {
    670         return notificationStatus;
    671     }
    672 
    673     public void setNotificationStatus(int notificationStatus) throws IllegalArgumentException {
    674         if (notificationStatus < 0 || notificationStatus > 0x0001)
    675             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    676         this.notificationStatus = notificationStatus;
    677     }
    678 
    679     public int getMasInstanceId() {
    680         return masInstanceId;
    681     }
    682 
    683     public void setMasInstanceId(int masInstanceId) {
    684         if (masInstanceId < 0 || masInstanceId > 0x00FF)
    685             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF");
    686         this.masInstanceId = masInstanceId;
    687     }
    688 
    689     public long getParameterMask() {
    690         return parameterMask;
    691     }
    692 
    693     public void setParameterMask(long parameterMask) {
    694         if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL)
    695             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF");
    696         this.parameterMask = parameterMask;
    697     }
    698 
    699     public int getFolderListingSize() {
    700         return folderListingSize;
    701     }
    702 
    703     public void setFolderListingSize(int folderListingSize) {
    704         if (folderListingSize < 0 || folderListingSize > 0xFFFF)
    705             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    706         this.folderListingSize = folderListingSize;
    707     }
    708 
    709     public int getMessageListingSize() {
    710         return messageListingSize;
    711     }
    712 
    713     public void setMessageListingSize(int messageListingSize) {
    714         if (messageListingSize < 0 || messageListingSize > 0xFFFF)
    715             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    716         this.messageListingSize = messageListingSize;
    717     }
    718 
    719     public int getSubjectLength() {
    720         return subjectLength;
    721     }
    722 
    723     public void setSubjectLength(int subjectLength) {
    724         if (subjectLength < 0 || subjectLength > 0xFF)
    725             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF");
    726         this.subjectLength = subjectLength;
    727     }
    728 
    729     public int getCharset() {
    730         return charset;
    731     }
    732 
    733     public void setCharset(int charset) {
    734         if (charset < 0 || charset > 0x1)
    735             throw new IllegalArgumentException("Out of range: " + charset + ", valid range is 0x0000 to 0x0001");
    736         this.charset = charset;
    737     }
    738 
    739     public int getFractionRequest() {
    740         return fractionRequest;
    741     }
    742 
    743     public void setFractionRequest(int fractionRequest) {
    744         if (fractionRequest < 0 || fractionRequest > 0x1)
    745             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    746         this.fractionRequest = fractionRequest;
    747     }
    748 
    749     public int getFractionDeliver() {
    750         return fractionDeliver;
    751     }
    752 
    753     public void setFractionDeliver(int fractionDeliver) {
    754         if (fractionDeliver < 0 || fractionDeliver > 0x1)
    755             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    756         this.fractionDeliver = fractionDeliver;
    757     }
    758 
    759     public int getStatusIndicator() {
    760         return statusIndicator;
    761     }
    762 
    763     public void setStatusIndicator(int statusIndicator) {
    764         if (statusIndicator < 0 || statusIndicator > 0x1)
    765             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    766         this.statusIndicator = statusIndicator;
    767     }
    768 
    769     public int getStatusValue() {
    770         return statusValue;
    771     }
    772 
    773     public void setStatusValue(int statusValue) {
    774         if (statusValue < 0 || statusValue > 0x1)
    775             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    776         this.statusValue = statusValue;
    777     }
    778 
    779     public long getMseTime() {
    780         return mseTime;
    781     }
    782 
    783     public String getMseTimeString() {
    784         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");
    785         Date date = new Date(getMseTime());
    786         return format.format(date); // Format to YYYYMMDDTHHMMSShhmm UTC time  offset
    787     }
    788 
    789     public void setMseTime(long mseTime) {
    790         this.mseTime = mseTime;
    791     }
    792 
    793     public void setMseTime(String mseTime) throws ParseException {
    794         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");
    795         Date date = format.parse(mseTime);
    796         this.mseTime = date.getTime();
    797     }
    798 }
    799