Home | History | Annotate | Download | only in obex
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.bluetooth.mapclient;
     18 
     19 import android.util.Log;
     20 
     21 import org.json.JSONException;
     22 import org.json.JSONObject;
     23 import org.xmlpull.v1.XmlPullParser;
     24 import org.xmlpull.v1.XmlPullParserException;
     25 import org.xmlpull.v1.XmlPullParserFactory;
     26 
     27 import java.io.DataInputStream;
     28 import java.io.IOException;
     29 import java.math.BigInteger;
     30 import java.util.HashMap;
     31 
     32 /**
     33  * Object representation of event report received by MNS
     34  * <p>
     35  * This object will be received in {@link Client#EVENT_EVENT_REPORT}
     36  * callback message.
     37  */
     38 public class EventReport {
     39     private final static String TAG = "EventReport";
     40     private final Type mType;
     41     private final String mHandle;
     42     private final String mFolder;
     43     private final String mOldFolder;
     44     private final Bmessage.Type mMsgType;
     45 
     46     private EventReport(HashMap<String, String> attrs) throws IllegalArgumentException {
     47         mType = parseType(attrs.get("type"));
     48 
     49         if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) {
     50             String handle = attrs.get("handle");
     51             try {
     52                 /* just to validate */
     53                 new BigInteger(attrs.get("handle"), 16);
     54 
     55                 mHandle = attrs.get("handle");
     56             } catch (NumberFormatException e) {
     57                 throw new IllegalArgumentException("Invalid value for handle:" + handle);
     58             }
     59         } else {
     60             mHandle = null;
     61         }
     62 
     63         mFolder = attrs.get("folder");
     64 
     65         mOldFolder = attrs.get("old_folder");
     66 
     67         if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) {
     68             String s = attrs.get("msg_type");
     69 
     70             if ("".equals(s)) {
     71                 // Some phones (e.g. SGS3 for MessageDeleted) send empty
     72                 // msg_type, in such case leave it as null rather than throw
     73                 // parse exception
     74                 mMsgType = null;
     75             } else {
     76                 mMsgType = parseMsgType(s);
     77             }
     78         } else {
     79             mMsgType = null;
     80         }
     81     }
     82 
     83     static EventReport fromStream(DataInputStream in) {
     84         EventReport ev = null;
     85 
     86         try {
     87             XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser();
     88             xpp.setInput(in, "utf-8");
     89 
     90             int event = xpp.getEventType();
     91             while (event != XmlPullParser.END_DOCUMENT) {
     92                 switch (event) {
     93                     case XmlPullParser.START_TAG:
     94                         if (xpp.getName().equals("event")) {
     95                             HashMap<String, String> attrs = new HashMap<String, String>();
     96 
     97                             for (int i = 0; i < xpp.getAttributeCount(); i++) {
     98                                 attrs.put(xpp.getAttributeName(i), xpp.getAttributeValue(i));
     99                             }
    100 
    101                             ev = new EventReport(attrs);
    102 
    103                             // return immediately, only one event should be here
    104                             return ev;
    105                         }
    106                         break;
    107                 }
    108 
    109                 event = xpp.next();
    110             }
    111 
    112         } catch (XmlPullParserException e) {
    113             Log.e(TAG, "XML parser error when parsing XML", e);
    114         } catch (IOException e) {
    115             Log.e(TAG, "I/O error when parsing XML", e);
    116         } catch (IllegalArgumentException e) {
    117             Log.e(TAG, "Invalid event received", e);
    118         }
    119 
    120         return ev;
    121     }
    122 
    123     private Type parseType(String type) throws IllegalArgumentException {
    124         for (Type t : Type.values()) {
    125             if (t.toString().equals(type)) {
    126                 return t;
    127             }
    128         }
    129 
    130         throw new IllegalArgumentException("Invalid value for type: " + type);
    131     }
    132 
    133     private Bmessage.Type parseMsgType(String msgType) throws IllegalArgumentException {
    134         for (Bmessage.Type t : Bmessage.Type.values()) {
    135             if (t.name().equals(msgType)) {
    136                 return t;
    137             }
    138         }
    139 
    140         throw new IllegalArgumentException("Invalid value for msg_type: " + msgType);
    141     }
    142 
    143     /**
    144      * @return {@link EventReport.Type} object corresponding to
    145      * <code>type</code> application parameter in MAP specification
    146      */
    147     public Type getType() {
    148         return mType;
    149     }
    150 
    151     /**
    152      * @return value corresponding to <code>handle</code> parameter in MAP
    153      * specification
    154      */
    155     public String getHandle() {
    156         return mHandle;
    157     }
    158 
    159     /**
    160      * @return value corresponding to <code>folder</code> parameter in MAP
    161      * specification
    162      */
    163     public String getFolder() {
    164         return mFolder;
    165     }
    166 
    167     /**
    168      * @return value corresponding to <code>old_folder</code> parameter in MAP
    169      * specification
    170      */
    171     public String getOldFolder() {
    172         return mOldFolder;
    173     }
    174 
    175     /**
    176      * @return {@link Bmessage.Type} object corresponding to
    177      * <code>msg_type</code> application parameter in MAP specification
    178      */
    179     public Bmessage.Type getMsgType() {
    180         return mMsgType;
    181     }
    182 
    183     @Override
    184     public String toString() {
    185         JSONObject json = new JSONObject();
    186 
    187         try {
    188             json.put("type", mType);
    189             json.put("handle", mHandle);
    190             json.put("folder", mFolder);
    191             json.put("old_folder", mOldFolder);
    192             json.put("msg_type", mMsgType);
    193         } catch (JSONException e) {
    194             // do nothing
    195         }
    196 
    197         return json.toString();
    198     }
    199 
    200     public enum Type {
    201         NEW_MESSAGE("NewMessage"), DELIVERY_SUCCESS("DeliverySuccess"),
    202         SENDING_SUCCESS("SendingSuccess"), DELIVERY_FAILURE("DeliveryFailure"),
    203         SENDING_FAILURE("SendingFailure"), MEMORY_FULL("MemoryFull"),
    204         MEMORY_AVAILABLE("MemoryAvailable"), MESSAGE_DELETED("MessageDeleted"),
    205         MESSAGE_SHIFT("MessageShift");
    206 
    207         private final String mSpecName;
    208 
    209         private Type(String specName) {
    210             mSpecName = specName;
    211         }
    212 
    213         @Override
    214         public String toString() {
    215             return mSpecName;
    216         }
    217     }
    218 }
    219