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*/
15package com.android.bluetooth.map;
16
17import java.io.IOException;
18import java.io.StringWriter;
19import java.io.UnsupportedEncodingException;
20import java.util.ArrayList;
21import java.util.Collections;
22import java.util.List;
23import com.android.internal.util.FastXmlSerializer;
24
25import org.xmlpull.v1.XmlSerializer;
26
27import android.util.Log;
28import android.util.Xml;
29
30public class BluetoothMapMessageListing {
31    private boolean hasUnread = false;
32    private static final String TAG = "BluetoothMapMessageListing";
33    private static final boolean D = BluetoothMapService.DEBUG;
34
35    private List<BluetoothMapMessageListingElement> mList;
36
37    public BluetoothMapMessageListing(){
38        mList = new ArrayList<BluetoothMapMessageListingElement>();
39    }
40    public void add(BluetoothMapMessageListingElement element) {
41        mList.add(element);
42        /* update info regarding whether the list contains unread messages */
43        if (element.getReadBool())
44        {
45            hasUnread = true;
46        }
47    }
48
49    /**
50     * Used to fetch the number of BluetoothMapMessageListingElement elements in the list.
51     * @return the number of elements in the list.
52     */
53    public int getCount() {
54        if(mList != null)
55        {
56            return mList.size();
57        }
58        return 0;
59    }
60
61    /**
62     * does the list contain any unread messages
63     * @return true if unread messages have been added to the list, else false
64     */
65    public boolean hasUnread()
66    {
67        return hasUnread;
68    }
69
70
71    /**
72     *  returns the entire list as a list
73     * @return list
74     */
75    public List<BluetoothMapMessageListingElement> getList(){
76        return mList;
77    }
78
79    /**
80     * Encode the list of BluetoothMapMessageListingElement(s) into a UTF-8
81     * formatted XML-string in a trimmed byte array
82     *
83     * @param version the version as a string.
84     *        Set the listing version to e.g. "1.0" or "1.1".
85     *        To make this future proof, no check is added to validate the value, hence be careful.
86     * @return a reference to the encoded byte array.
87     * @throws UnsupportedEncodingException
88     *             if UTF-8 encoding is unsupported on the platform.
89     */
90    // TODO: Remove includeThreadId when MAP-IM is adopted
91    public byte[] encode(boolean includeThreadId, String version) throws UnsupportedEncodingException {
92        StringWriter sw = new StringWriter();
93        XmlSerializer xmlMsgElement = new FastXmlSerializer();
94        try {
95            xmlMsgElement.setOutput(sw);
96            xmlMsgElement.startDocument("UTF-8", true);
97            xmlMsgElement.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
98            xmlMsgElement.startTag(null, "MAP-msg-listing");
99            xmlMsgElement.attribute(null, "version", version);
100            // Do the XML encoding of list
101            for (BluetoothMapMessageListingElement element : mList) {
102                element.encode(xmlMsgElement, includeThreadId); // Append the list element
103            }
104            xmlMsgElement.endTag(null, "MAP-msg-listing");
105            xmlMsgElement.endDocument();
106        } catch (IllegalArgumentException e) {
107            Log.w(TAG, e);
108        } catch (IllegalStateException e) {
109            Log.w(TAG, e);
110        } catch (IOException e) {
111            Log.w(TAG, e);
112        }
113        return sw.toString().getBytes("UTF-8");
114    }
115
116    public void sort() {
117        Collections.sort(mList);
118    }
119
120    public void segment(int count, int offset) {
121        count = Math.min(count, mList.size() - offset);
122        if (count > 0) {
123            mList = mList.subList(offset, offset + count);
124            if(mList == null) {
125                mList = new ArrayList<BluetoothMapMessageListingElement>(); // Return an empty list
126            }
127        } else {
128            if(offset > mList.size()) {
129               mList = new ArrayList<BluetoothMapMessageListingElement>();
130               Log.d(TAG, "offset greater than list size. Returning empty list");
131            } else {
132               mList = mList.subList(offset, mList.size());
133            }
134        }
135    }
136}
137