Home | History | Annotate | Download | only in map
      1 /*
      2 * Copyright (C) 2014 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 
     18 import android.util.Log;
     19 import org.xmlpull.v1.XmlSerializer;
     20 
     21 import com.android.internal.util.FastXmlSerializer;
     22 
     23 import java.io.IOException;
     24 import java.io.StringWriter;
     25 import java.io.UnsupportedEncodingException;
     26 import java.util.ArrayList;
     27 import java.util.Collection;
     28 import java.util.HashMap;
     29 import java.util.Locale;
     30 import java.util.Map.Entry;
     31 
     32 
     33 /**
     34  * Class to contain a single folder element representation.
     35  *
     36  */
     37 public class BluetoothMapFolderElement {
     38     private String mName;
     39     private BluetoothMapFolderElement mParent = null;
     40     private boolean mHasSmsMmsContent = false;
     41     private long mEmailFolderId = -1;
     42     private HashMap<String, BluetoothMapFolderElement> mSubFolders;
     43 
     44     private static final boolean D = BluetoothMapService.DEBUG;
     45     private static final boolean V = BluetoothMapService.VERBOSE;
     46 
     47     private final static String TAG = "BluetoothMapFolderElement";
     48 
     49     public BluetoothMapFolderElement( String name, BluetoothMapFolderElement parrent){
     50         this.mName = name;
     51         this.mParent = parrent;
     52         mSubFolders = new HashMap<String, BluetoothMapFolderElement>();
     53     }
     54 
     55     public String getName() {
     56         return mName;
     57     }
     58 
     59     public boolean hasSmsMmsContent(){
     60         return mHasSmsMmsContent;
     61     }
     62 
     63     public long getEmailFolderId(){
     64         return mEmailFolderId;
     65     }
     66 
     67     public void setEmailFolderId(long emailFolderId) {
     68         this.mEmailFolderId = emailFolderId;
     69     }
     70 
     71     public void setHasSmsMmsContent(boolean hasSmsMmsContent) {
     72         this.mHasSmsMmsContent = hasSmsMmsContent;
     73     }
     74 
     75     /**
     76      * Fetch the parent folder.
     77      * @return the parent folder or null if we are at the root folder.
     78      */
     79     public BluetoothMapFolderElement getParent() {
     80         return mParent;
     81     }
     82 
     83     /**
     84      * Build the full path to this folder
     85      * @return a string representing the full path.
     86      */
     87     public String getFullPath() {
     88         StringBuilder sb = new StringBuilder(mName);
     89         BluetoothMapFolderElement current = mParent;
     90         while(current != null) {
     91             if(current.getParent() != null) {
     92                 sb.insert(0, current.mName + "/");
     93             }
     94             current = current.getParent();
     95         }
     96         //sb.insert(0, "/"); Should this be included? The MAP spec. do not include it in examples.
     97         return sb.toString();
     98     }
     99 
    100 
    101     public BluetoothMapFolderElement getEmailFolderByName(String name) {
    102         BluetoothMapFolderElement folderElement = this.getRoot();
    103         folderElement = folderElement.getSubFolder("telecom");
    104         folderElement = folderElement.getSubFolder("msg");
    105         folderElement = folderElement.getSubFolder(name);
    106         if (folderElement != null && folderElement.getEmailFolderId() == -1 )
    107             folderElement = null;
    108         return folderElement;
    109     }
    110 
    111     public BluetoothMapFolderElement getEmailFolderById(long id) {
    112         return getEmailFolderById(id, this);
    113     }
    114 
    115     public static BluetoothMapFolderElement getEmailFolderById(long id,
    116             BluetoothMapFolderElement folderStructure) {
    117         if(folderStructure == null) {
    118             return null;
    119         }
    120         return findEmailFolderById(id, folderStructure.getRoot());
    121     }
    122 
    123     private static BluetoothMapFolderElement findEmailFolderById(long id,
    124             BluetoothMapFolderElement folder) {
    125         if(folder.getEmailFolderId() == id) {
    126             return folder;
    127         }
    128         /* Else */
    129         for(BluetoothMapFolderElement subFolder : folder.mSubFolders.values().toArray(
    130                 new BluetoothMapFolderElement[folder.mSubFolders.size()]))
    131         {
    132             BluetoothMapFolderElement ret = findEmailFolderById(id, subFolder);
    133             if(ret != null) {
    134                 return ret;
    135             }
    136         }
    137         return null;
    138     }
    139 
    140 
    141     /**
    142      * Fetch the root folder.
    143      * @return the parent folder or null if we are at the root folder.
    144      */
    145     public BluetoothMapFolderElement getRoot() {
    146         BluetoothMapFolderElement rootFolder = this;
    147         while(rootFolder.getParent() != null)
    148             rootFolder = rootFolder.getParent();
    149         return rootFolder;
    150     }
    151 
    152     /**
    153      * Add a virtual folder.
    154      * @param name the name of the folder to add.
    155      * @return the added folder element.
    156      */
    157     public BluetoothMapFolderElement addFolder(String name){
    158         name = name.toLowerCase(Locale.US);
    159         BluetoothMapFolderElement newFolder = mSubFolders.get(name);
    160         if(D) Log.i(TAG,"addFolder():" + name);
    161         if(newFolder == null) {
    162             newFolder = new BluetoothMapFolderElement(name, this);
    163             mSubFolders.put(name, newFolder);
    164         }
    165         return newFolder;
    166     }
    167 
    168     /**
    169      * Add a sms/mms folder.
    170      * @param name the name of the folder to add.
    171      * @return the added folder element.
    172      */
    173     public BluetoothMapFolderElement addSmsMmsFolder(String name){
    174         name = name.toLowerCase(Locale.US);
    175         BluetoothMapFolderElement newFolder = mSubFolders.get(name);
    176         if(D) Log.i(TAG,"addSmsMmsFolder():" + name);
    177         if(newFolder == null) {
    178             newFolder = new BluetoothMapFolderElement(name, this);
    179             mSubFolders.put(name, newFolder);
    180         }
    181         newFolder.setHasSmsMmsContent(true);
    182         return newFolder;
    183     }
    184 
    185     /**
    186      * Add an Email folder.
    187      * @param name the name of the folder to add.
    188      * @return the added folder element.
    189      */
    190     public BluetoothMapFolderElement addEmailFolder(String name, long emailFolderId){
    191         name = name.toLowerCase();
    192         BluetoothMapFolderElement newFolder = mSubFolders.get(name);
    193         if(V) Log.v(TAG,"addEmailFolder(): name = " + name
    194                  + "id = " + emailFolderId);
    195         if(newFolder == null) {
    196             newFolder = new BluetoothMapFolderElement(name, this);
    197             mSubFolders.put(name, newFolder);
    198         }
    199         newFolder.setEmailFolderId(emailFolderId);
    200         return newFolder;
    201     }
    202 
    203     /**
    204      * Fetch the number of sub folders.
    205      * @return returns the number of sub folders.
    206      */
    207     public int getSubFolderCount(){
    208         return mSubFolders.size();
    209     }
    210 
    211     /**
    212      * Returns the subFolder element matching the supplied folder name.
    213      * @param folderName the name of the subFolder to find.
    214      * @return the subFolder element if found {@code null} otherwise.
    215      */
    216     public BluetoothMapFolderElement getSubFolder(String folderName){
    217         return mSubFolders.get(folderName.toLowerCase());
    218     }
    219 
    220     public byte[] encode(int offset, int count) throws UnsupportedEncodingException {
    221         StringWriter sw = new StringWriter();
    222         XmlSerializer xmlMsgElement = new FastXmlSerializer();
    223         int i, stopIndex;
    224         // We need index based access to the subFolders
    225         BluetoothMapFolderElement[] folders = mSubFolders.values().toArray(new BluetoothMapFolderElement[mSubFolders.size()]);
    226 
    227         if(offset > mSubFolders.size())
    228             throw new IllegalArgumentException("FolderListingEncode: offset > subFolders.size()");
    229 
    230         stopIndex = offset + count;
    231         if(stopIndex > mSubFolders.size())
    232             stopIndex = mSubFolders.size();
    233 
    234         try {
    235             xmlMsgElement.setOutput(sw);
    236             xmlMsgElement.startDocument("UTF-8", true);
    237             xmlMsgElement.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    238             xmlMsgElement.startTag(null, "folder-listing");
    239             xmlMsgElement.attribute(null, "version", "1.0");
    240             for(i = offset; i<stopIndex; i++)
    241             {
    242                 xmlMsgElement.startTag(null, "folder");
    243                 xmlMsgElement.attribute(null, "name", folders[i].getName());
    244                 xmlMsgElement.endTag(null, "folder");
    245             }
    246             xmlMsgElement.endTag(null, "folder-listing");
    247             xmlMsgElement.endDocument();
    248         } catch (IllegalArgumentException e) {
    249             if(D) Log.w(TAG,e);
    250             throw new IllegalArgumentException("error encoding folderElement");
    251         } catch (IllegalStateException e) {
    252             if(D) Log.w(TAG,e);
    253             throw new IllegalArgumentException("error encoding folderElement");
    254         } catch (IOException e) {
    255             if(D) Log.w(TAG,e);
    256             throw new IllegalArgumentException("error encoding folderElement");
    257         }
    258         return sw.toString().getBytes("UTF-8");
    259     }
    260 }
    261