1fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie/*
2fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie* Copyright (C) 2013 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
17fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.IOException;
18fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.StringWriter;
19fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.io.UnsupportedEncodingException;
20fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.ArrayList;
21fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.Collections;
22fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport java.util.List;
235079ae05a3fa7cf09d2d8e564b71382dfc70a1aeHemant Guptaimport com.android.internal.util.FastXmlSerializer;
24fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
25fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport org.xmlpull.v1.XmlSerializer;
26fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
27fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Log;
28fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xieimport android.util.Xml;
29fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
30fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xiepublic class BluetoothMapMessageListing {
3170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    private boolean hasUnread = false;
32fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    private static final String TAG = "BluetoothMapMessageListing";
33326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    private static final boolean D = BluetoothMapService.DEBUG;
34326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
355a60e47497f21f64e6d79420dc4c56c1907df22akschulz    private List<BluetoothMapMessageListingElement> mList;
36fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
37fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public BluetoothMapMessageListing(){
385a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mList = new ArrayList<BluetoothMapMessageListingElement>();
39fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
40fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void add(BluetoothMapMessageListingElement element) {
415a60e47497f21f64e6d79420dc4c56c1907df22akschulz        mList.add(element);
4270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        /* update info regarding whether the list contains unread messages */
43326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (element.getReadBool())
4470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        {
4570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz            hasUnread = true;
4670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
47fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
48fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
49fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    /**
50fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * Used to fetch the number of BluetoothMapMessageListingElement elements in the list.
51fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * @return the number of elements in the list.
52fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     */
53fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public int getCount() {
545a60e47497f21f64e6d79420dc4c56c1907df22akschulz        if(mList != null)
5570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        {
565a60e47497f21f64e6d79420dc4c56c1907df22akschulz            return mList.size();
5770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        }
5870be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return 0;
5970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    }
6070be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
6170be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    /**
6270be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz     * does the list contain any unread messages
6370be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz     * @return true if unread messages have been added to the list, else false
6470be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz     */
6570be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    public boolean hasUnread()
6670be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz    {
6770be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz        return hasUnread;
68fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
6970be005a18a35ec5fcb46152f0dfbe82156efa3aKim Schulz
70326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
71326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    /**
72326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     *  returns the entire list as a list
73326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     * @return list
74326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde     */
75326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    public List<BluetoothMapMessageListingElement> getList(){
765a60e47497f21f64e6d79420dc4c56c1907df22akschulz        return mList;
77326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde    }
78326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde
79fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    /**
80fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * Encode the list of BluetoothMapMessageListingElement(s) into a UTF-8
81fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * formatted XML-string in a trimmed byte array
82fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     *
835a60e47497f21f64e6d79420dc4c56c1907df22akschulz     * @param version the version as a string.
845a60e47497f21f64e6d79420dc4c56c1907df22akschulz     *        Set the listing version to e.g. "1.0" or "1.1".
855a60e47497f21f64e6d79420dc4c56c1907df22akschulz     *        To make this future proof, no check is added to validate the value, hence be careful.
86fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * @return a reference to the encoded byte array.
87fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     * @throws UnsupportedEncodingException
88fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     *             if UTF-8 encoding is unsupported on the platform.
89fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie     */
905a60e47497f21f64e6d79420dc4c56c1907df22akschulz    // TODO: Remove includeThreadId when MAP-IM is adopted
915a60e47497f21f64e6d79420dc4c56c1907df22akschulz    public byte[] encode(boolean includeThreadId, String version) throws UnsupportedEncodingException {
92fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        StringWriter sw = new StringWriter();
935079ae05a3fa7cf09d2d8e564b71382dfc70a1aeHemant Gupta        XmlSerializer xmlMsgElement = new FastXmlSerializer();
94fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        try {
95fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            xmlMsgElement.setOutput(sw);
965079ae05a3fa7cf09d2d8e564b71382dfc70a1aeHemant Gupta            xmlMsgElement.startDocument("UTF-8", true);
975079ae05a3fa7cf09d2d8e564b71382dfc70a1aeHemant Gupta            xmlMsgElement.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
985079ae05a3fa7cf09d2d8e564b71382dfc70a1aeHemant Gupta            xmlMsgElement.startTag(null, "MAP-msg-listing");
995a60e47497f21f64e6d79420dc4c56c1907df22akschulz            xmlMsgElement.attribute(null, "version", version);
100fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            // Do the XML encoding of list
1015a60e47497f21f64e6d79420dc4c56c1907df22akschulz            for (BluetoothMapMessageListingElement element : mList) {
102326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde                element.encode(xmlMsgElement, includeThreadId); // Append the list element
103fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            }
1045079ae05a3fa7cf09d2d8e564b71382dfc70a1aeHemant Gupta            xmlMsgElement.endTag(null, "MAP-msg-listing");
105fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie            xmlMsgElement.endDocument();
106fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (IllegalArgumentException e) {
107326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, e);
108fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (IllegalStateException e) {
109326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, e);
110fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } catch (IOException e) {
111326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            Log.w(TAG, e);
112fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
113fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        return sw.toString().getBytes("UTF-8");
114fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
115fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
116fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void sort() {
1175a60e47497f21f64e6d79420dc4c56c1907df22akschulz        Collections.sort(mList);
118fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
119fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie
120fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    public void segment(int count, int offset) {
1215a60e47497f21f64e6d79420dc4c56c1907df22akschulz        count = Math.min(count, mList.size() - offset);
122326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde        if (count > 0) {
1235a60e47497f21f64e6d79420dc4c56c1907df22akschulz            mList = mList.subList(offset, offset + count);
1245a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(mList == null) {
1255a60e47497f21f64e6d79420dc4c56c1907df22akschulz                mList = new ArrayList<BluetoothMapMessageListingElement>(); // Return an empty list
126326b5e610063ac24c0ba467ac585bd4c7f618a67Casper Bonde            }
127fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        } else {
1285a60e47497f21f64e6d79420dc4c56c1907df22akschulz            if(offset > mList.size()) {
1295a60e47497f21f64e6d79420dc4c56c1907df22akschulz               mList = new ArrayList<BluetoothMapMessageListingElement>();
130c1f597b3ec02ccc112f3c917fd079588034c3eacHemant Gupta               Log.d(TAG, "offset greater than list size. Returning empty list");
131c1f597b3ec02ccc112f3c917fd079588034c3eacHemant Gupta            } else {
1325a60e47497f21f64e6d79420dc4c56c1907df22akschulz               mList = mList.subList(offset, mList.size());
133c1f597b3ec02ccc112f3c917fd079588034c3eacHemant Gupta            }
134fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie        }
135fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie    }
136fd6603b8bf9ed72dcc8bd59aaef3209251b6e17cMatthew Xie}
137