--- a/src/com/beem/project/beem/ui/ContactList.java Mon May 31 00:56:26 2010 +0200
+++ b/src/com/beem/project/beem/ui/ContactList.java Tue Jun 01 21:32:39 2010 +0200
@@ -50,7 +50,6 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Iterator;
import org.jivesoftware.smack.util.StringUtils;
@@ -96,6 +95,7 @@
import com.beem.project.beem.ui.dialogs.builders.ResendSubscription;
import com.beem.project.beem.utils.BeemBroadcastReceiver;
import com.beem.project.beem.utils.Status;
+import com.beem.project.beem.utils.SortedList;
/**
* The contact list activity displays the roster of the user.
@@ -107,11 +107,14 @@
SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
}
- private static final int REQUEST_CODE = 1;
private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact";
private static final String TAG = "ContactList";
private final BeemContactList mAdapterContactList = new BeemContactList();
private final List<String> mListGroup = new ArrayList<String>();
+
+ /** Map containing a list of the different contacts of a given group.
+ * Each list is a @{link SortedList} so there is no need to sort it again.
+ * */
private final Map<String, List<Contact>> mContactOnGroup = new HashMap<String, List<Contact>>();
private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick();
private final Handler mHandler = new Handler();
@@ -133,7 +136,6 @@
* Constructor.
*/
public ContactList() {
-
}
/**
@@ -226,7 +228,8 @@
result = true;
break;
case R.id.contact_list_context_menu_userinfo_subscription:
- Dialog subscription = new ResendSubscription(ContactList.this, mXmppFacade, mSelectedContact).create();
+ Dialog subscription = new ResendSubscription(ContactList.this,
+ mXmppFacade, mSelectedContact).create();
subscription.show();
result = true;
break;
@@ -300,37 +303,17 @@
}
/**
- * Comparator Contact by status and name.
- */
- private static class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
- /**
- * Constructor.
- */
- public ComparatorContactListByStatusAndName() {
- }
-
- @Override
- public int compare(T c1, T c2) {
- if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
- return 1;
- } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) {
- return -1;
- } else
- return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName());
- }
- }
-
- /**
- * Contact List construction.
+ * Build and display the contact list.
+ * @param group name of the contact list.
*/
private void buildContactList(String group) {
mListContact = mContactOnGroup.get(group);
Log.d(TAG, "buildContactList for group " + group);
- sortBeemContactList();
+ mAdapterContactList.notifyDataSetChanged();
}
/**
- * showGroups.
+ * Show the groups view.
*/
private void showGroups() {
@@ -340,57 +323,21 @@
Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner);
g.setOnItemClickListener(new OnItemClickGroupName());
g.setAdapter(mAdapterBanner);
- } else
+ g.setSelection(0);
+ } else {
((LinearLayout) findViewById(R.id.contactlist_groupstub)).setVisibility(View.VISIBLE);
- }
-
- /**
- * Event simple click on item of the contact list.
- */
- private class BeemContactListOnClick implements OnItemClickListener {
- /**
- * Constructor.
- */
- public BeemContactListOnClick() {
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
- Contact c = mListContact.get(pos);
- Intent i = new Intent(ContactList.this, Chat.class);
- i.setData(c.toUri());
- startActivity(i);
+ Gallery g = (Gallery) findViewById(R.id.contactlist_banner);
+ g.setSelection(0);
}
}
/**
- * Event simple click on middle groupe name.
+ * Hide the groups view.
*/
- private class OnItemClickGroupName implements OnItemClickListener {
-
- /**
- * Constructor.
- */
- public OnItemClickGroupName() {
- }
-
- @Override
- public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
- String group = mListGroup.get(i);
- buildContactList(group);
- }
- }
-
- /**
- * Sort the contact list.
- */
- private void sortBeemContactList() {
- Log.d(TAG, "Sort ");
- Collections.sort(mListContact, mComparator);
- mAdapterContactList.notifyDataSetChanged();
+ private void hideGroups() {
+ View v = findViewById(R.id.contactlist_groupstub);
+ if (v != null)
+ v.setVisibility(View.GONE);
}
/**
@@ -404,133 +351,210 @@
}
/**
- * Refresh the contact list.
+ * {@inheritDoc}
+ * Simple stategy to handle the onEntriesAdded event.
+ * if contact has to be shown :
+ * <ul>
+ * <li> add him to his groups</li>
+ * <li> add him to the specials groups</>
+ * </ul>
*/
- private class RunnableChange implements Runnable {
- /**
- * Constructor.
- */
- public RunnableChange() {
+ @Override
+ public void onEntriesAdded(final List<String> addresses) throws RemoteException {
+ final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+ for (String newName : addresses) {
+ Contact contact = mRoster.getContact(newName);
+ boolean visible = !hideDisconnected || Status.statusOnline(contact.getStatus());
+ List<String> groups = contact.getGroups();
+ if (visible) {
+ for (String group : groups) {
+ if (!mListGroup.contains(group)) {
+ mListGroup.add(mListGroup.size() - 1, group);
+ List<Contact> tmplist = new SortedList<Contact>(new LinkedList<Contact>(), mComparator);
+ mContactOnGroup.put(group, tmplist);
+ }
+ List<Contact> contactByGroups = mContactOnGroup.get(group);
+ if (contactByGroups == mListContact) {
+ updateCurrentList(group, contact);
+ continue;
+ }
+ contactByGroups.add(contact);
+ }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run() {
- sortBeemContactList();
- mAdapterContactList.notifyDataSetChanged();
- mAdapterBanner.notifyDataSetChanged();
+ // add the contact to all and no groups
+ addToSpecialList(contact);
+ }
}
}
/**
* {@inheritDoc}
+ * Simple stategy to handle the onEntriesDeleted event.
+ * <ul>
+ * <li> Remove the contact from all groups</li>
+ * </ul>
*/
@Override
- public void onEntriesAdded(List<String> addresses) throws RemoteException {
- boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
- for (String newName : addresses) {
- Contact c = mRoster.getContact(newName);
- if (!hideDisconnected || Status.statusOnline(c.getStatus())) {
- mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
- if (c.getGroups().size() == 0)
- mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
- for (String group : c.getGroups()) {
- if (!mListGroup.contains(group)) {
- mListGroup.add(mListGroup.size() - 1, group);
- List<Contact> tmplist = new LinkedList<Contact>();
- mContactOnGroup.put(group, tmplist);
- }
- mContactOnGroup.get(group).add(c);
+ public void onEntriesDeleted(final List<String> addresses) throws RemoteException {
+ Log.d(TAG, "onEntries deleted " + addresses);
+ for (String cToDelete : addresses) {
+ Contact contact = new Contact(cToDelete);
+ for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+ List<Contact> contactByGroups = entry.getValue();
+ if (contactByGroups == mListContact) {
+ updateCurrentList(entry.getKey(), contact);
+ continue;
}
+ contactByGroups.remove(contact);
}
+ cleanBannerGroup();
}
- mHandler.post(new RunnableChange());
+
+ mHandler.post(new Runnable() {
+ public void run() {
+ mListContact = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
+ mAdapterContactList.notifyDataSetChanged();
+ }
+ });
+
}
/**
* {@inheritDoc}
+ * Simple stategy to handle the onEntriesUpdated event.
+ * <ul>
+ * <li> Remove the contact from all groups</li>
+ * <li> if contact has to be shown add it to his groups</li>
+ * <li> if contact has to be shown add it to the specials groups</li>
+ * </ul>
*/
@Override
- public void onEntriesDeleted(List<String> addresses) throws RemoteException {
- Log.d(TAG, "onEntries deleted " + addresses);
- for (String cToDelete : addresses) {
- Contact contact = mRoster.getContact(cToDelete);
- for (List<Contact> contactByGroups : mContactOnGroup.values()) {
+ public void onEntriesUpdated(final List<String> addresses) throws RemoteException {
+ final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+ for (String adr : addresses) {
+ Contact contact = mRoster.getContact(adr);
+ boolean visible = !hideDisconnected || Status.statusOnline(contact.getStatus());
+ List<String> groups = contact.getGroups();
+ for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+ List<Contact> contactByGroups = entry.getValue();
+ if (contactByGroups == mListContact) {
+ updateCurrentList(entry.getKey(), contact);
+ continue;
+ }
contactByGroups.remove(contact);
+ if (visible) {
+ for (String group : groups) {
+ if (!mListGroup.contains(group)) {
+ mListGroup.add(mListGroup.size() - 1, group);
+ List<Contact> tmplist = new SortedList<Contact>(
+ new LinkedList<Contact>(), mComparator);
+ mContactOnGroup.put(group, tmplist);
+ }
+ mContactOnGroup.get(group).remove(contact);
+ }
+ }
+
}
- cleanBannerGroup();
+
+ // add the contact to all and no groups
+ if (visible) {
+ addToSpecialList(contact);
+ }
}
- mListContact = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
- mHandler.post(new RunnableChange());
+ cleanBannerGroup();
}
/**
* {@inheritDoc}
+ * Simple stategy to handle the onPresenceChanged event.
+ * <ul>
+ * <li> Remove the contact from all groups</li>
+ * <li> if contact has to be shown add it to his groups</li>
+ * <li> if contact has to be shown add it to the specials groups</li>
+ * </ul>
*/
@Override
- public void onEntriesUpdated(List<String> addresses) throws RemoteException {
- boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
- for (String adr : addresses) {
- Contact c = mRoster.getContact(adr);
- List<String> groups = c.getGroups();
- for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
- List<Contact> contactByGroups = entry.getValue();
- contactByGroups.remove(c);
+ public void onPresenceChanged(PresenceAdapter presence) throws RemoteException {
+ Log.d(TAG, "presence");
+ String from = presence.getFrom();
+ final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+ final Contact contact = mRoster.getContact(StringUtils.parseBareAddress(from));
+ boolean visible = !hideDisconnected || Status.statusOnline(contact.getStatus());
+ List<String> groups = contact.getGroups();
+ for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+ List<Contact> contactByGroups = entry.getValue();
+ if (contactByGroups == mListContact) {
+ updateCurrentList(entry.getKey(), contact);
+ continue;
}
- if (!hideDisconnected || Status.statusOnline(c.getStatus())) {
- mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
- if (c.getGroups().size() == 0)
- mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
- for (String group : c.getGroups()) {
- if (!mListGroup.contains(group)) {
- mListGroup.add(mListGroup.size() - 1, group);
- List<Contact> tmplist = new LinkedList<Contact>();
- mContactOnGroup.put(group, tmplist);
- }
- mContactOnGroup.get(group).add(c);
+ contactByGroups.remove(contact);
+ if (visible) {
+ if (groups.contains(entry.getKey())) {
+ contactByGroups.add(contact);
}
}
}
- cleanBannerGroup();
- mHandler.post(new RunnableChange());
+ if (visible) {
+ addToSpecialList(contact);
+ }
+ }
+
+ /**
+ * Add a contact to the special list No Group and All contacts.
+ * The contact will be added if the list is not the current list otherwise
+ * the list must be modified in a Handler.
+ *
+ * @param contact the contact to add.
+ */
+ private void addToSpecialList(Contact contact) {
+ List<String> groups = contact.getGroups();
+ List<Contact> list = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
+ if (list != mListContact) {
+ list.add(contact);
+ }
+ list = mContactOnGroup.get(getString(R.string.contact_list_no_group));
+ if (list != mListContact && groups.isEmpty()) {
+ list.add(contact);
+ }
}
- @Override
- public void onPresenceChanged(PresenceAdapter presence) throws RemoteException {
- String from = presence.getFrom();
- boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
- Contact contact = mRoster.getContact(StringUtils.parseBareAddress(from));
- for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
- List<Contact> contactByGroups = entry.getValue();
- if (contactByGroups.contains(contact)) {
- contactByGroups.remove(contact);
- if (!hideDisconnected || Status.statusOnline(contact.getStatus())) {
- contactByGroups.add(contact);
+ /**
+ * Update the current list with the status of contact.
+ *
+ * @param listName name of the current list
+ * @param contact contact to update
+ */
+ private void updateCurrentList(String listName, final Contact contact) {
+ final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+ final List<String> groups = contact.getGroups();
+ String noGroup = getString(R.string.contact_list_no_group);
+ String allGroup = getString(R.string.contact_list_all_contact);
+ final boolean add = ((!hideDisconnected || Status.statusOnline(contact.getStatus())) && // must show and
+ (
+ (listName.equals(noGroup) && groups.isEmpty()) || // in no group
+ groups.contains(listName) || // or in current
+ listName.equals(allGroup) // or in all
+ ));
+ mHandler.post(new Runnable() {
+ public void run() {
+ mListContact.remove(contact);
+ if (add) {
+ mListContact.add(contact);
}
- } else {
- if (Status.statusOnline(contact.getStatus())) {
- List<String> groups = contact.getGroups();
- if (groups.contains(entry.getKey())) {
- contactByGroups.add(contact);
- }
- }
+ mAdapterContactList.notifyDataSetChanged();
}
- }
- Log.d(TAG, "presence");
- mHandler.post(new RunnableChange());
+ });
+
}
- private void cleanBannerGroup() {
- for (Iterator<String> it = mListGroup.iterator(); it.hasNext(); ){
- String group = it.next();
- if (mContactOnGroup.get(group).size() == 0) {
- mContactOnGroup.remove(group);
- it.remove();
- }
- }
+ /**
+ * Remove old groups on the banner.
+ * @throws RemoteException if an error occur when communicating with the service
+ */
+ private void cleanBannerGroup() throws RemoteException {
+ List<String> rosterGroups = mRoster.getGroupsNames();
+ List<String> realGroups = mListGroup.subList(1, mListContact.size() - 1);
+ realGroups.retainAll(rosterGroups);
}
}
@@ -600,7 +624,8 @@
if (curContact != null) {
TextView v = (TextView) view.findViewById(R.id.contactlistpseudo);
- LevelListDrawable mStatusDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.status_icon);
+ LevelListDrawable mStatusDrawable = (LevelListDrawable) getResources()
+ .getDrawable(R.drawable.status_icon);
mStatusDrawable.setLevel(curContact.getStatus());
v.setCompoundDrawablesWithIntrinsicBounds(mStatusDrawable, null, null, null);
v.setText(curContact.getName());
@@ -619,8 +644,10 @@
/**
* Constructor.
+ * @param inflater the inflater use to create the view for the banner
+ * @param groups list of the differents groups to adapt
*/
- public BeemBanner(LayoutInflater inflater, List<String> groups) {
+ public BeemBanner(final LayoutInflater inflater, final List<String> groups) {
mGroups = groups;
mInflater = inflater;
}
@@ -668,22 +695,23 @@
try {
mRoster = mXmppFacade.getRoster();
if (mRoster != null) {
- mRoster.addRosterListener(mBeemRosterListener);
List<Contact> tmpContactList = mRoster.getContactList();
List<String> tmpGroupList = mRoster.getGroupsNames();
Collections.sort(tmpGroupList);
- if (mListGroup.size() > 0)
- mListGroup.clear();
+ mListGroup.clear();
mListGroup.add(getString(R.string.contact_list_all_contact));
mListGroup.addAll(tmpGroupList);
mListGroup.add(getString(R.string.contact_list_no_group));
assignContactToGroups(mRoster.getContactList(), tmpGroupList);
+ makeSortedList(mContactOnGroup);
if (!mSettings.getBoolean("settings_key_hide_groups", false))
showGroups();
else
hideGroups();
String group = getString(R.string.contact_list_all_contact);
buildContactList(group);
+ mRoster.addRosterListener(mBeemRosterListener);
+ Log.d(TAG, "add rester listneer");
}
} catch (RemoteException e) {
e.printStackTrace();
@@ -704,46 +732,116 @@
mContactOnGroup.clear();
mBinded = false;
}
+
+ /**
+ * Assign the differents contact to their groups.
+ * This methods will fill the mContactOnGroup map.
+ *
+ * @param contacts list of contacts
+ * @param groupNames list of existing groups
+ */
+ private void assignContactToGroups(List<Contact> contacts, List<String> groupNames) {
+ boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+ mContactOnGroup.clear();
+ List<Contact> all = new LinkedList<Contact>();
+ List<Contact> noGroups = new LinkedList<Contact>();
+ for (String group : groupNames) {
+ mContactOnGroup.put(group, new LinkedList<Contact>());
+ }
+ for (Contact c : contacts) {
+ if (hideDisconnected && !Status.statusOnline(c.getStatus())) {
+ continue;
+ }
+ all.add(c);
+ List<String> groups = c.getGroups();
+ if (groups.isEmpty())
+ noGroups.add(c);
+ else {
+ for (String currentGroup : groups) {
+ List<Contact> contactsByGroups = mContactOnGroup.get(currentGroup);
+ contactsByGroups.add(c);
+ }
+ }
+ }
+ mContactOnGroup.put(getString(R.string.contact_list_no_group), noGroups);
+ mContactOnGroup.put(getString(R.string.contact_list_all_contact), all);
+ }
+
+ /**
+ * Make the List of the map became Insertion sorted list.
+ *
+ * @param map the map to convert.
+ */
+ private void makeSortedList(Map<String, List<Contact>> map) {
+ for (Map.Entry<String, List<Contact>> entry : map.entrySet()) {
+ List<Contact> l = entry.getValue();
+ entry.setValue(new SortedList<Contact>(l, mComparator));
+ }
+ }
}
- @Override
- protected void finalize() {
- Log.e(TAG, "FINALIZE");
+
+
+
+ /**
+ * Comparator Contact by status and name.
+ */
+ private static class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
+ /**
+ * Constructor.
+ */
+ public ComparatorContactListByStatusAndName() {
+ }
+
+ @Override
+ public int compare(T c1, T c2) {
+ if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
+ return 1;
+ } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) {
+ return -1;
+ } else
+ return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName());
+ }
}
/**
- * Hide the groups view.
+ * Event simple click on item of the contact list.
*/
- private void hideGroups() {
- View v = findViewById(R.id.contactlist_groupstub);
- if (v != null)
- v.setVisibility(View.GONE);
+ private class BeemContactListOnClick implements OnItemClickListener {
+ /**
+ * Constructor.
+ */
+ public BeemContactListOnClick() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
+ Contact c = mListContact.get(pos);
+ Intent i = new Intent(ContactList.this, Chat.class);
+ i.setData(c.toUri());
+ startActivity(i);
+ }
}
- private void assignContactToGroups(List<Contact> contacts, List<String> groupNames) {
- boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
- mContactOnGroup.clear();
- List<Contact> all = new LinkedList<Contact>();
- List<Contact> noGroups = new LinkedList<Contact>();
- for (String group: groupNames) {
- mContactOnGroup.put(group, new LinkedList<Contact>());
+ /**
+ * Event simple click on middle groupe name.
+ */
+ private class OnItemClickGroupName implements OnItemClickListener {
+
+ /**
+ * Constructor.
+ */
+ public OnItemClickGroupName() {
}
- for (Contact c : contacts) {
- if (hideDisconnected && !Status.statusOnline(c.getStatus())) {
- continue;
- }
- all.add(c);
- List<String> groups = c.getGroups();
- if (groups.size() == 0)
- noGroups.add(c);
- else {
- for (String currentGroup : groups) {
- List<Contact> contactsByGroups = mContactOnGroup.get(currentGroup);
- contactsByGroups.add(c);
- }
- }
+
+ @Override
+ public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
+ String group = mListGroup.get(i);
+ buildContactList(group);
}
- mContactOnGroup.put(getString(R.string.contact_list_no_group), noGroups);
- mContactOnGroup.put(getString(R.string.contact_list_all_contact), all);
}
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/utils/SortedList.java Tue Jun 01 21:32:39 2010 +0200
@@ -0,0 +1,312 @@
+/*
+ BEEM is a videoconference application on the Android Platform.
+
+ Copyright (C) 2009 by Frederic-Charles Barthelery,
+ Jean-Manuel Da Silva,
+ Nikita Kozlov,
+ Philippe Lago,
+ Jean Baptiste Vergely,
+ Vincent Veronis.
+
+ This file is part of BEEM.
+
+ BEEM is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ BEEM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with BEEM. If not, see <http://www.gnu.org/licenses/>.
+
+ Please send bug reports with examples or suggestions to
+ contact@beem-project.com or http://dev.beem-project.com/
+
+*/
+package com.beem.project.beem.utils;
+
+import java.util.List;
+import java.util.Comparator;
+import java.util.ListIterator;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * This class add a sort by insertion to a List.
+ * All methods which allow you to insert an object at a specific index
+ * will throw an UnsupportedOperationException.
+ *
+ * @author Da Risk <da_risk@beem-project.com>
+ * @param <E> the type of elements maintained by this list
+ */
+public class SortedList<E> implements List<E> {
+
+ private final List<E> mBackend;
+ private final Comparator<? super E> mComparator;
+
+ /**
+ * Create a SortedList. The existing elements will be sorted.
+ *
+ * @param list list to sort
+ * @param mComparator mComparator to use.
+ */
+ public SortedList(final List<E> list, final Comparator<? super E> mComparator) {
+ this.mComparator = mComparator;
+ this.mBackend = list;
+ Collections.sort(mBackend, mComparator);
+ }
+
+ @Override
+ public int size() {
+ return mBackend.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mBackend.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return mBackend.contains(o);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new SortedListIterator<E>(mBackend.listIterator());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return mBackend.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return mBackend.toArray(a);
+ }
+
+ @Override
+ public boolean add(E e) {
+ for (ListIterator<E> it = mBackend.listIterator(); it.hasNext();) {
+ if (mComparator.compare(e, it.next()) < 0) {
+ if (it.hasPrevious()) {
+ it.previous();
+ }
+ it.add(e);
+ return true;
+ }
+ }
+ mBackend.add(e);
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return mBackend.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return mBackend.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ boolean result = false;
+ for (E e : c) {
+ boolean t = add(e);
+ if (t) {
+ result = t;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Add all the elements in the specified collection.
+ * The index param is ignored.
+ *
+ * @param index ignored
+ * @param c collection containing elements to be added to this list
+ * @return true if this list changed as a result of the call
+ */
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
+ return addAll(c);
+ }
+
+ /**
+ * Add all the elements in the specified collection.
+ * The index param is ignored.
+ *
+ * @param l collection containing elements to be added to this list
+ * @return true if this list changed as a result of the call
+ * @see addAll(Collection)
+ */
+ public boolean addAll(SortedList<? extends E> l) {
+ if (!l.isEmpty()) {
+ if (mBackend.isEmpty()) {
+ return mBackend.addAll(l);
+ }
+ boolean result = false;
+ E myfirst = mBackend.get(0);
+ E last = l.get(l.size() - 1);
+ E mylast = mBackend.get(mBackend.size() - 1);
+ E first = l.get(0);
+ if (mComparator.compare(last, myfirst) < 0) {
+ result = mBackend.addAll(0, l);
+ } else if (mComparator.compare(first, mylast) > 0) {
+ result = mBackend.addAll(l);
+ } else {
+ Collection<? extends E> c = l;
+ result = addAll(c);
+ }
+ return result;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ return mBackend.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ return mBackend.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ mBackend.clear();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return mBackend.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return mBackend.hashCode();
+ }
+
+ @Override
+ public E get(int index) {
+ return mBackend.get(index);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ throw new UnsupportedOperationException("set() is not supported in SortedList");
+ }
+
+ @Override
+ public void add(int index, E element) {
+ throw new UnsupportedOperationException("add at specific index is not supported in SortedList");
+ }
+
+ @Override
+ public E remove(int index) {
+ return mBackend.remove(index);
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ return mBackend.indexOf(o);
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ return mBackend.lastIndexOf(o);
+ }
+
+ @Override
+ public ListIterator<E> listIterator() {
+ return new SortedListIterator<E>(mBackend.listIterator());
+ }
+
+ @Override
+ public ListIterator<E> listIterator(int index) {
+ return new SortedListIterator<E>(mBackend.listIterator(index));
+ }
+
+ @Override
+ public List<E> subList(int fromIndex, int toIndex) {
+ return mBackend.subList(fromIndex, toIndex);
+ }
+
+ @Override
+ public String toString() {
+ return mBackend.toString();
+ }
+
+ /**
+ * A SortedList.iterator don't allow list modification.
+ * It use the mBackend iterator for the other operations.
+ */
+ private class SortedListIterator<E> implements ListIterator<E> {
+
+ private ListIterator<E> mIt;
+
+ /**
+ * Construct SortedList.Iterator.
+ *
+ * @param iterator the iterator of the backend list
+ */
+ SortedListIterator(final ListIterator<E> iterator) {
+ mIt = iterator;
+ }
+
+ @Override
+ public void add(E e) {
+ throw new UnsupportedOperationException("add() not supported in SortedList iterator");
+ }
+
+ @Override
+ public boolean hasNext() {
+ return mIt.hasNext();
+ }
+
+ @Override
+ public E next() {
+ return mIt.next();
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return mIt.hasPrevious();
+ }
+
+ @Override
+ public E previous() {
+ return mIt.previous();
+ }
+
+ @Override
+ public int nextIndex() {
+ return mIt.nextIndex();
+ }
+
+ @Override
+ public int previousIndex() {
+ return mIt.previousIndex();
+ }
+
+ @Override
+ public void remove() {
+ mIt.remove();
+ }
+
+ @Override
+ public void set(E e) {
+ throw new UnsupportedOperationException("set () not supported in SortedList iterator");
+ }
+ }
+}