1 /* 2 * Copyright (C) 2015 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.IOException; 18 import java.io.InputStream; 19 import java.io.StringWriter; 20 import java.io.UnsupportedEncodingException; 21 import java.text.ParseException; 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.List; 25 26 import org.xmlpull.v1.XmlPullParser; 27 import org.xmlpull.v1.XmlPullParserException; 28 import org.xmlpull.v1.XmlSerializer; 29 30 import android.util.Log; 31 import android.util.Xml; 32 33 import com.android.internal.util.FastXmlSerializer; 34 import com.android.internal.util.XmlUtils; 35 36 public class BluetoothMapConvoListing { 37 private boolean hasUnread = false; 38 private static final String TAG = "BluetoothMapConvoListing"; 39 private static final boolean D = BluetoothMapService.DEBUG; 40 private static final String XML_TAG = "MAP-convo-listing"; 41 42 private List<BluetoothMapConvoListingElement> mList; 43 BluetoothMapConvoListing()44 public BluetoothMapConvoListing(){ 45 mList = new ArrayList<BluetoothMapConvoListingElement>(); 46 } add(BluetoothMapConvoListingElement element)47 public void add(BluetoothMapConvoListingElement element) { 48 mList.add(element); 49 /* update info regarding whether the list contains unread conversations */ 50 if (element.getReadBool()) 51 { 52 hasUnread = true; 53 } 54 } 55 56 /** 57 * Used to fetch the number of BluetoothMapConvoListingElement elements in the list. 58 * @return the number of elements in the list. 59 */ getCount()60 public int getCount() { 61 if(mList != null) 62 { 63 return mList.size(); 64 } 65 return 0; 66 } 67 68 /** 69 * does the list contain any unread messages 70 * @return true if unread messages have been added to the list, else false 71 */ hasUnread()72 public boolean hasUnread() 73 { 74 return hasUnread; 75 } 76 77 78 /** 79 * returns the entire list as a list 80 * @return list 81 */ getList()82 public List<BluetoothMapConvoListingElement> getList(){ 83 return mList; 84 } 85 86 /** 87 * Encode the list of BluetoothMapMessageListingElement(s) into a UTF-8 88 * formatted XML-string in a trimmed byte array 89 * 90 * @return a reference to the encoded byte array. 91 * @throws UnsupportedEncodingException 92 * if UTF-8 encoding is unsupported on the platform. 93 */ encode()94 public byte[] encode() throws UnsupportedEncodingException { 95 StringWriter sw = new StringWriter(); 96 XmlSerializer xmlConvoElement = new FastXmlSerializer(); 97 try { 98 xmlConvoElement.setOutput(sw); 99 xmlConvoElement.startDocument("UTF-8", true); 100 xmlConvoElement.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", 101 true); 102 xmlConvoElement.startTag(null, XML_TAG); 103 xmlConvoElement.attribute(null, "version", "1.0"); 104 // Do the XML encoding of list 105 for (BluetoothMapConvoListingElement element : mList) { 106 element.encode(xmlConvoElement); // Append the list element 107 } 108 xmlConvoElement.endTag(null, XML_TAG); 109 xmlConvoElement.endDocument(); 110 } catch (IllegalArgumentException e) { 111 Log.w(TAG, e); 112 } catch (IllegalStateException e) { 113 Log.w(TAG, e); 114 } catch (IOException e) { 115 Log.w(TAG, e); 116 } 117 return sw.toString().getBytes("UTF-8"); 118 } 119 sort()120 public void sort() { 121 Collections.sort(mList); 122 } 123 segment(int count, int offset)124 public void segment(int count, int offset) { 125 count = Math.min(count, mList.size() - offset); 126 if (count > 0) { 127 mList = mList.subList(offset, offset + count); 128 if(mList == null) { 129 mList = new ArrayList<BluetoothMapConvoListingElement>(); // Return an empty list 130 } 131 } else { 132 if(offset > mList.size()) { 133 mList = new ArrayList<BluetoothMapConvoListingElement>(); 134 Log.d(TAG, "offset greater than list size. Returning empty list"); 135 } else { 136 mList = mList.subList(offset, mList.size()); 137 } 138 } 139 } 140 appendFromXml(InputStream xmlDocument)141 public void appendFromXml(InputStream xmlDocument) 142 throws XmlPullParserException, IOException, ParseException { 143 try { 144 XmlPullParser parser = Xml.newPullParser(); 145 int type; 146 parser.setInput(xmlDocument, "UTF-8"); 147 148 // First find the folder-listing 149 while((type=parser.next()) != XmlPullParser.END_TAG 150 && type != XmlPullParser.END_DOCUMENT ) { 151 // Skip until we get a start tag 152 if (parser.getEventType() != XmlPullParser.START_TAG) { 153 continue; 154 } 155 // Skip until we get a folder-listing tag 156 String name = parser.getName(); 157 if(!name.equalsIgnoreCase(XML_TAG)) { 158 if(D) Log.i(TAG,"Unknown XML tag: " + name); 159 XmlUtils.skipCurrentTag(parser); 160 } 161 readConversations(parser); 162 } 163 } finally { 164 xmlDocument.close(); 165 } 166 } 167 168 /** 169 * Parses folder elements, and add to mSubFolders. 170 * @param parser the Xml Parser currently pointing to an folder-listing tag. 171 * @throws XmlPullParserException 172 * @throws IOException 173 * @throws 174 */ readConversations(XmlPullParser parser)175 private void readConversations(XmlPullParser parser) 176 throws XmlPullParserException, IOException, ParseException { 177 int type; 178 if(D) Log.i(TAG,"readConversations(): "); 179 while((type=parser.next()) != XmlPullParser.END_TAG 180 && type != XmlPullParser.END_DOCUMENT ) { 181 // Skip until we get a start tag 182 if (parser.getEventType() != XmlPullParser.START_TAG) { 183 continue; 184 } 185 // Skip until we get a folder-listing tag 186 String name = parser.getName(); 187 if(name.trim().equalsIgnoreCase(BluetoothMapConvoListingElement.XML_TAG_CONVERSATION) 188 == false) { 189 if(D) Log.i(TAG,"Unknown XML tag: " + name); 190 XmlUtils.skipCurrentTag(parser); 191 continue; 192 } 193 // Add a single conversation 194 add(BluetoothMapConvoListingElement.createFromXml(parser)); 195 } 196 } 197 198 199 @Override equals(Object obj)200 public boolean equals(Object obj) { 201 if (this == obj) { 202 return true; 203 } 204 if (obj == null) { 205 return false; 206 } 207 if (getClass() != obj.getClass()) { 208 return false; 209 } 210 BluetoothMapConvoListing other = (BluetoothMapConvoListing) obj; 211 if (hasUnread != other.hasUnread) { 212 return false; 213 } 214 if (mList == null) { 215 if (other.mList != null) { 216 return false; 217 } 218 } else if (!mList.equals(other.mList)) { 219 return false; 220 } 221 return true; 222 } 223 224 } 225