1fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/* 25a60e47497f21f64e6d79420dc4c56c1907df22akschulz* Copyright (C) 2015 Samsung System LSI 3fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Licensed under the Apache License, Version 2.0 (the "License"); 4fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* you may not use this file except in compliance with the License. 5fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* You may obtain a copy of the License at 6fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* 7fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* http://www.apache.org/licenses/LICENSE-2.0 8fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* 9fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Unless required by applicable law or agreed to in writing, software 10fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* distributed under the License is distributed on an "AS IS" BASIS, 11fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* See the License for the specific language governing permissions and 13fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* limitations under the License. 14fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie*/ 15fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepackage com.android.bluetooth.map; 16fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 17326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 18fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.IOException; 195a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.io.InputStream; 20fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.StringWriter; 21fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.UnsupportedEncodingException; 225a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport java.util.Arrays; 23326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport java.util.HashMap; 24326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bondeimport java.util.Locale; 255a60e47497f21f64e6d79420dc4c56c1907df22akschulz 265a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport org.xmlpull.v1.XmlPullParser; 275a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport org.xmlpull.v1.XmlPullParserException; 285a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport org.xmlpull.v1.XmlSerializer; 295a60e47497f21f64e6d79420dc4c56c1907df22akschulz 305a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport android.util.Log; 315a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport android.util.Xml; 325a60e47497f21f64e6d79420dc4c56c1907df22akschulz 335a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.internal.util.FastXmlSerializer; 345a60e47497f21f64e6d79420dc4c56c1907df22akschulzimport com.android.internal.util.XmlUtils; 35fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 36fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 37fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/** 38326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * Class to contain a single folder element representation. 39fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * 40fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 415a60e47497f21f64e6d79420dc4c56c1907df22akschulzpublic class BluetoothMapFolderElement implements Comparable<BluetoothMapFolderElement>{ 42326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private String mName; 43326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private BluetoothMapFolderElement mParent = null; 445a60e47497f21f64e6d79420dc4c56c1907df22akschulz private long mFolderId = -1; 45326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private boolean mHasSmsMmsContent = false; 465a60e47497f21f64e6d79420dc4c56c1907df22akschulz private boolean mHasImContent = false; 470dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz private boolean mHasEmailContent = false; 485a60e47497f21f64e6d79420dc4c56c1907df22akschulz 495a60e47497f21f64e6d79420dc4c56c1907df22akschulz private boolean mIgnore = false; 505a60e47497f21f64e6d79420dc4c56c1907df22akschulz 51326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private HashMap<String, BluetoothMapFolderElement> mSubFolders; 52326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 53326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private static final boolean D = BluetoothMapService.DEBUG; 54326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private static final boolean V = BluetoothMapService.VERBOSE; 55326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 56326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde private final static String TAG = "BluetoothMapFolderElement"; 57fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 58326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public BluetoothMapFolderElement( String name, BluetoothMapFolderElement parrent){ 59326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde this.mName = name; 60326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde this.mParent = parrent; 61326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mSubFolders = new HashMap<String, BluetoothMapFolderElement>(); 62fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 63fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 645a60e47497f21f64e6d79420dc4c56c1907df22akschulz public void setIngore(boolean ignore) { 655a60e47497f21f64e6d79420dc4c56c1907df22akschulz mIgnore = ignore; 665a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 675a60e47497f21f64e6d79420dc4c56c1907df22akschulz 685a60e47497f21f64e6d79420dc4c56c1907df22akschulz public boolean shouldIgnore() { 695a60e47497f21f64e6d79420dc4c56c1907df22akschulz return mIgnore; 705a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 715a60e47497f21f64e6d79420dc4c56c1907df22akschulz 72fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public String getName() { 73326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return mName; 74326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 75326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 76326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public boolean hasSmsMmsContent(){ 77326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return mHasSmsMmsContent; 78326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 79326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 805a60e47497f21f64e6d79420dc4c56c1907df22akschulz public long getFolderId(){ 815a60e47497f21f64e6d79420dc4c56c1907df22akschulz return mFolderId; 82326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 830dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz public boolean hasEmailContent(){ 840dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz return mHasEmailContent; 850dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz } 86326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 875a60e47497f21f64e6d79420dc4c56c1907df22akschulz public void setFolderId(long folderId) { 885a60e47497f21f64e6d79420dc4c56c1907df22akschulz this.mFolderId = folderId; 89326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 90326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public void setHasSmsMmsContent(boolean hasSmsMmsContent) { 91326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde this.mHasSmsMmsContent = hasSmsMmsContent; 92fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 930dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz public void setHasEmailContent(boolean hasEmailContent) { 940dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz this.mHasEmailContent = hasEmailContent; 950dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz } 965a60e47497f21f64e6d79420dc4c56c1907df22akschulz public void setHasImContent(boolean hasImContent) { 975a60e47497f21f64e6d79420dc4c56c1907df22akschulz this.mHasImContent = hasImContent; 985a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 995a60e47497f21f64e6d79420dc4c56c1907df22akschulz 1005a60e47497f21f64e6d79420dc4c56c1907df22akschulz public boolean hasImContent(){ 1015a60e47497f21f64e6d79420dc4c56c1907df22akschulz return mHasImContent; 1025a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 1030dcecb2cfd921916ed586183d64ec9fd250a6e4ckschulz 104fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /** 105fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * Fetch the parent folder. 106fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * @return the parent folder or null if we are at the root folder. 107fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 108fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public BluetoothMapFolderElement getParent() { 109326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return mParent; 110fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 111fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 112fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /** 113326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * Build the full path to this folder 114326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @return a string representing the full path. 115326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde */ 116326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public String getFullPath() { 117326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde StringBuilder sb = new StringBuilder(mName); 118326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde BluetoothMapFolderElement current = mParent; 119326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde while(current != null) { 120326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(current.getParent() != null) { 121326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde sb.insert(0, current.mName + "/"); 122326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 123326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde current = current.getParent(); 124326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 125326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde //sb.insert(0, "/"); Should this be included? The MAP spec. do not include it in examples. 126326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return sb.toString(); 127326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 128326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 129326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 1305a60e47497f21f64e6d79420dc4c56c1907df22akschulz public BluetoothMapFolderElement getFolderByName(String name) { 131326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde BluetoothMapFolderElement folderElement = this.getRoot(); 132326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde folderElement = folderElement.getSubFolder("telecom"); 133326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde folderElement = folderElement.getSubFolder("msg"); 134326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde folderElement = folderElement.getSubFolder(name); 1355a60e47497f21f64e6d79420dc4c56c1907df22akschulz if (folderElement != null && folderElement.getFolderId() == -1 ) 136326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde folderElement = null; 137326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return folderElement; 138326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 139326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 1405a60e47497f21f64e6d79420dc4c56c1907df22akschulz public BluetoothMapFolderElement getFolderById(long id) { 1415a60e47497f21f64e6d79420dc4c56c1907df22akschulz return getFolderById(id, this); 142326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 143326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 1445a60e47497f21f64e6d79420dc4c56c1907df22akschulz public static BluetoothMapFolderElement getFolderById(long id, 145326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde BluetoothMapFolderElement folderStructure) { 146326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(folderStructure == null) { 147326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return null; 148326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 1495a60e47497f21f64e6d79420dc4c56c1907df22akschulz return findFolderById(id, folderStructure.getRoot()); 150326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 151326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 1525a60e47497f21f64e6d79420dc4c56c1907df22akschulz private static BluetoothMapFolderElement findFolderById(long id, 153326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde BluetoothMapFolderElement folder) { 1545a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(folder.getFolderId() == id) { 155326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return folder; 156326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 157326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /* Else */ 158326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde for(BluetoothMapFolderElement subFolder : folder.mSubFolders.values().toArray( 159326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde new BluetoothMapFolderElement[folder.mSubFolders.size()])) 160326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde { 1615a60e47497f21f64e6d79420dc4c56c1907df22akschulz BluetoothMapFolderElement ret = findFolderById(id, subFolder); 162326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(ret != null) { 163326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return ret; 164326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 165326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 166326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return null; 167326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 168326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 169326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 170326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /** 171fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * Fetch the root folder. 1725a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @return the root folder. 173fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 174fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public BluetoothMapFolderElement getRoot() { 175fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie BluetoothMapFolderElement rootFolder = this; 176fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie while(rootFolder.getParent() != null) 177fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie rootFolder = rootFolder.getParent(); 178fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return rootFolder; 179fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 180fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 181fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /** 182326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * Add a virtual folder. 183fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * @param name the name of the folder to add. 184fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * @return the added folder element. 185fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 186fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public BluetoothMapFolderElement addFolder(String name){ 187326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde name = name.toLowerCase(Locale.US); 188326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde BluetoothMapFolderElement newFolder = mSubFolders.get(name); 189326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(newFolder == null) { 1905a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"addFolder():" + name); 191326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde newFolder = new BluetoothMapFolderElement(name, this); 192326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde mSubFolders.put(name, newFolder); 1935a60e47497f21f64e6d79420dc4c56c1907df22akschulz } else { 1945a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"addFolder():" + name + " already added"); 195326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 196326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return newFolder; 197326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 198326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 199326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /** 200326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * Add a sms/mms folder. 201326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @param name the name of the folder to add. 202326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @return the added folder element. 203326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde */ 204326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public BluetoothMapFolderElement addSmsMmsFolder(String name){ 2055a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"addSmsMmsFolder()"); 2065a60e47497f21f64e6d79420dc4c56c1907df22akschulz BluetoothMapFolderElement newFolder = addFolder(name); 207326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde newFolder.setHasSmsMmsContent(true); 208326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return newFolder; 209326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde } 210326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 211326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde /** 2125a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Add a im folder. 2135a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @param name the name of the folder to add. 2145a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @return the added folder element. 2155a60e47497f21f64e6d79420dc4c56c1907df22akschulz */ 2165a60e47497f21f64e6d79420dc4c56c1907df22akschulz public BluetoothMapFolderElement addImFolder(String name, long idFolder){ 2175a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"addImFolder() id = " + idFolder); 2185a60e47497f21f64e6d79420dc4c56c1907df22akschulz BluetoothMapFolderElement newFolder = addFolder(name); 2195a60e47497f21f64e6d79420dc4c56c1907df22akschulz newFolder.setHasImContent(true); 2205a60e47497f21f64e6d79420dc4c56c1907df22akschulz newFolder.setFolderId(idFolder); 2215a60e47497f21f64e6d79420dc4c56c1907df22akschulz return newFolder; 2225a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 2235a60e47497f21f64e6d79420dc4c56c1907df22akschulz 2245a60e47497f21f64e6d79420dc4c56c1907df22akschulz /** 225326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * Add an Email folder. 226326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @param name the name of the folder to add. 227326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde * @return the added folder element. 228326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde */ 229326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde public BluetoothMapFolderElement addEmailFolder(String name, long emailFolderId){ 2305a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(V) Log.v(TAG,"addEmailFolder() id = " + emailFolderId); 2315a60e47497f21f64e6d79420dc4c56c1907df22akschulz BluetoothMapFolderElement newFolder = addFolder(name); 2325a60e47497f21f64e6d79420dc4c56c1907df22akschulz newFolder.setFolderId(emailFolderId); 2335a60e47497f21f64e6d79420dc4c56c1907df22akschulz newFolder.setHasEmailContent(true); 234fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return newFolder; 235fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 236fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /** 237fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * Fetch the number of sub folders. 238fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * @return returns the number of sub folders. 239fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 240fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public int getSubFolderCount(){ 241326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return mSubFolders.size(); 242fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 243fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 244fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie /** 245fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * Returns the subFolder element matching the supplied folder name. 246fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * @param folderName the name of the subFolder to find. 247fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie * @return the subFolder element if found {@code null} otherwise. 248fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie */ 249fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public BluetoothMapFolderElement getSubFolder(String folderName){ 250326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde return mSubFolders.get(folderName.toLowerCase()); 251fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 252fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 253fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie public byte[] encode(int offset, int count) throws UnsupportedEncodingException { 254fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie StringWriter sw = new StringWriter(); 255326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde XmlSerializer xmlMsgElement = new FastXmlSerializer(); 256fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie int i, stopIndex; 257326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde // We need index based access to the subFolders 258326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde BluetoothMapFolderElement[] folders = mSubFolders.values().toArray(new BluetoothMapFolderElement[mSubFolders.size()]); 259326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde 260326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(offset > mSubFolders.size()) 261fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie throw new IllegalArgumentException("FolderListingEncode: offset > subFolders.size()"); 262fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 263fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie stopIndex = offset + count; 264326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(stopIndex > mSubFolders.size()) 265326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde stopIndex = mSubFolders.size(); 266fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie 267fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie try { 268fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlMsgElement.setOutput(sw); 269326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.startDocument("UTF-8", true); 270326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 271326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.startTag(null, "folder-listing"); 2725a60e47497f21f64e6d79420dc4c56c1907df22akschulz xmlMsgElement.attribute(null, "version", BluetoothMapUtils.MAP_V10_STR); 273fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie for(i = offset; i<stopIndex; i++) 274fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie { 275326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.startTag(null, "folder"); 276326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.attribute(null, "name", folders[i].getName()); 277326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.endTag(null, "folder"); 278fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 279326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde xmlMsgElement.endTag(null, "folder-listing"); 280fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie xmlMsgElement.endDocument(); 281fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IllegalArgumentException e) { 282326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(D) Log.w(TAG,e); 283326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde throw new IllegalArgumentException("error encoding folderElement"); 284fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IllegalStateException e) { 285326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(D) Log.w(TAG,e); 286326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde throw new IllegalArgumentException("error encoding folderElement"); 287fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } catch (IOException e) { 288326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde if(D) Log.w(TAG,e); 289326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde throw new IllegalArgumentException("error encoding folderElement"); 290fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 291fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie return sw.toString().getBytes("UTF-8"); 292fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie } 2935a60e47497f21f64e6d79420dc4c56c1907df22akschulz 2945a60e47497f21f64e6d79420dc4c56c1907df22akschulz /* The functions below are useful for implementing a MAP client, reusing the object. 2955a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Currently they are only used for test purposes. 2965a60e47497f21f64e6d79420dc4c56c1907df22akschulz * */ 2975a60e47497f21f64e6d79420dc4c56c1907df22akschulz 2985a60e47497f21f64e6d79420dc4c56c1907df22akschulz /** 2995a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Append sub folders from an XML document as specified in the MAP specification. 3005a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Attributes will be inherited from parent folder - with regards to message types in the 3015a60e47497f21f64e6d79420dc4c56c1907df22akschulz * folder. 3025a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @param xmlDocument - InputStream with the document 3035a60e47497f21f64e6d79420dc4c56c1907df22akschulz * 3045a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @throws XmlPullParserException 3055a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @throws IOException 3065a60e47497f21f64e6d79420dc4c56c1907df22akschulz */ 3075a60e47497f21f64e6d79420dc4c56c1907df22akschulz public void appendSubfolders(InputStream xmlDocument) 3085a60e47497f21f64e6d79420dc4c56c1907df22akschulz throws XmlPullParserException, IOException { 3095a60e47497f21f64e6d79420dc4c56c1907df22akschulz try { 3105a60e47497f21f64e6d79420dc4c56c1907df22akschulz XmlPullParser parser = Xml.newPullParser(); 3115a60e47497f21f64e6d79420dc4c56c1907df22akschulz int type; 3125a60e47497f21f64e6d79420dc4c56c1907df22akschulz parser.setInput(xmlDocument, "UTF-8"); 3135a60e47497f21f64e6d79420dc4c56c1907df22akschulz 3145a60e47497f21f64e6d79420dc4c56c1907df22akschulz // First find the folder-listing 3155a60e47497f21f64e6d79420dc4c56c1907df22akschulz while((type=parser.next()) != XmlPullParser.END_TAG 3165a60e47497f21f64e6d79420dc4c56c1907df22akschulz && type != XmlPullParser.END_DOCUMENT ) { 3175a60e47497f21f64e6d79420dc4c56c1907df22akschulz // Skip until we get a start tag 3185a60e47497f21f64e6d79420dc4c56c1907df22akschulz if (parser.getEventType() != XmlPullParser.START_TAG) { 3195a60e47497f21f64e6d79420dc4c56c1907df22akschulz continue; 3205a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3215a60e47497f21f64e6d79420dc4c56c1907df22akschulz // Skip until we get a folder-listing tag 3225a60e47497f21f64e6d79420dc4c56c1907df22akschulz String name = parser.getName(); 3235a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(!name.equalsIgnoreCase("folder-listing")) { 3245a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"Unknown XML tag: " + name); 3255a60e47497f21f64e6d79420dc4c56c1907df22akschulz XmlUtils.skipCurrentTag(parser); 3265a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3275a60e47497f21f64e6d79420dc4c56c1907df22akschulz readFolders(parser); 3285a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3295a60e47497f21f64e6d79420dc4c56c1907df22akschulz } finally { 3305a60e47497f21f64e6d79420dc4c56c1907df22akschulz xmlDocument.close(); 3315a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3325a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3335a60e47497f21f64e6d79420dc4c56c1907df22akschulz 3345a60e47497f21f64e6d79420dc4c56c1907df22akschulz /** 3355a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Parses folder elements, and add to mSubFolders. 3365a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @param parser the Xml Parser currently pointing to an folder-listing tag. 3375a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @throws XmlPullParserException 3385a60e47497f21f64e6d79420dc4c56c1907df22akschulz * @throws IOException 3395a60e47497f21f64e6d79420dc4c56c1907df22akschulz */ 3405a60e47497f21f64e6d79420dc4c56c1907df22akschulz public void readFolders(XmlPullParser parser) 3415a60e47497f21f64e6d79420dc4c56c1907df22akschulz throws XmlPullParserException, IOException { 3425a60e47497f21f64e6d79420dc4c56c1907df22akschulz int type; 3435a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"readFolders(): "); 3445a60e47497f21f64e6d79420dc4c56c1907df22akschulz while((type=parser.next()) != XmlPullParser.END_TAG 3455a60e47497f21f64e6d79420dc4c56c1907df22akschulz && type != XmlPullParser.END_DOCUMENT ) { 3465a60e47497f21f64e6d79420dc4c56c1907df22akschulz // Skip until we get a start tag 3475a60e47497f21f64e6d79420dc4c56c1907df22akschulz if (parser.getEventType() != XmlPullParser.START_TAG) { 3485a60e47497f21f64e6d79420dc4c56c1907df22akschulz continue; 3495a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3505a60e47497f21f64e6d79420dc4c56c1907df22akschulz // Skip until we get a folder-listing tag 3515a60e47497f21f64e6d79420dc4c56c1907df22akschulz String name = parser.getName(); 3525a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(name.trim().equalsIgnoreCase("folder") == false) { 3535a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"Unknown XML tag: " + name); 3545a60e47497f21f64e6d79420dc4c56c1907df22akschulz XmlUtils.skipCurrentTag(parser); 3555a60e47497f21f64e6d79420dc4c56c1907df22akschulz continue; 3565a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3575a60e47497f21f64e6d79420dc4c56c1907df22akschulz int count = parser.getAttributeCount(); 3585a60e47497f21f64e6d79420dc4c56c1907df22akschulz for (int i = 0; i<count; i++) { 3595a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(parser.getAttributeName(i).trim().equalsIgnoreCase("name")) { 3605a60e47497f21f64e6d79420dc4c56c1907df22akschulz // We found a folder, append to sub folders. 3615a60e47497f21f64e6d79420dc4c56c1907df22akschulz BluetoothMapFolderElement element = 3625a60e47497f21f64e6d79420dc4c56c1907df22akschulz addFolder(parser.getAttributeValue(i).trim()); 3635a60e47497f21f64e6d79420dc4c56c1907df22akschulz element.setHasEmailContent(mHasEmailContent); 3645a60e47497f21f64e6d79420dc4c56c1907df22akschulz element.setHasImContent(mHasImContent); 3655a60e47497f21f64e6d79420dc4c56c1907df22akschulz element.setHasSmsMmsContent(mHasSmsMmsContent); 3665a60e47497f21f64e6d79420dc4c56c1907df22akschulz } else { 3675a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG,"Unknown XML attribute: " + parser.getAttributeName(i)); 3685a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3695a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3705a60e47497f21f64e6d79420dc4c56c1907df22akschulz parser.nextTag(); 3715a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3725a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3735a60e47497f21f64e6d79420dc4c56c1907df22akschulz 3745a60e47497f21f64e6d79420dc4c56c1907df22akschulz /** 3755a60e47497f21f64e6d79420dc4c56c1907df22akschulz * Recursive compare of all folder names 3765a60e47497f21f64e6d79420dc4c56c1907df22akschulz */ 3775a60e47497f21f64e6d79420dc4c56c1907df22akschulz @Override 3785a60e47497f21f64e6d79420dc4c56c1907df22akschulz public int compareTo(BluetoothMapFolderElement another) { 3795a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(another == null) return 1; 3805a60e47497f21f64e6d79420dc4c56c1907df22akschulz int ret = mName.compareToIgnoreCase(another.mName); 3815a60e47497f21f64e6d79420dc4c56c1907df22akschulz // TODO: Do we want to add compare of folder type? 3825a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(ret == 0) { 3835a60e47497f21f64e6d79420dc4c56c1907df22akschulz ret = mSubFolders.size() - another.mSubFolders.size(); 3845a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(ret == 0) { 3855a60e47497f21f64e6d79420dc4c56c1907df22akschulz // Compare all sub folder elements (will do nothing if mSubFolders is empty) 3865a60e47497f21f64e6d79420dc4c56c1907df22akschulz for(BluetoothMapFolderElement subfolder : mSubFolders.values()) { 3875a60e47497f21f64e6d79420dc4c56c1907df22akschulz BluetoothMapFolderElement subfolderAnother = 3885a60e47497f21f64e6d79420dc4c56c1907df22akschulz another.mSubFolders.get(subfolder.getName()); 3895a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(subfolderAnother == null) { 3905a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG, subfolder.getFullPath() + " not in another"); 3915a60e47497f21f64e6d79420dc4c56c1907df22akschulz return 1; 3925a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3935a60e47497f21f64e6d79420dc4c56c1907df22akschulz ret = subfolder.compareTo(subfolderAnother); 3945a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(ret != 0) { 3955a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG, subfolder.getFullPath() + " filed compareTo()"); 3965a60e47497f21f64e6d79420dc4c56c1907df22akschulz return ret; 3975a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3985a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 3995a60e47497f21f64e6d79420dc4c56c1907df22akschulz } else { 4005a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG, "mSubFolders.size(): " + mSubFolders.size() + 4015a60e47497f21f64e6d79420dc4c56c1907df22akschulz " another.mSubFolders.size(): " + another.mSubFolders.size()); 4025a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 4035a60e47497f21f64e6d79420dc4c56c1907df22akschulz } else { 4045a60e47497f21f64e6d79420dc4c56c1907df22akschulz if(D) Log.i(TAG, "mName: " + mName + " another.mName: " + another.mName); 4055a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 4065a60e47497f21f64e6d79420dc4c56c1907df22akschulz return ret; 4075a60e47497f21f64e6d79420dc4c56c1907df22akschulz } 408fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie} 409