* #31001: com.savoirfaire -> org.sflphone
diff --git a/src/org/sflphone/loaders/AccountsLoader.java b/src/org/sflphone/loaders/AccountsLoader.java
new file mode 100644
index 0000000..65a0f38
--- /dev/null
+++ b/src/org/sflphone/loaders/AccountsLoader.java
@@ -0,0 +1,53 @@
+package org.sflphone.loaders;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.sflphone.model.Account;
+import org.sflphone.service.ISipService;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+public class AccountsLoader extends AsyncTaskLoader<ArrayList<Account>> {
+
+    private static final String TAG = AccountsLoader.class.getSimpleName();
+
+    ISipService service;
+
+    public AccountsLoader(Context context, ISipService ref) {
+        super(context);
+        service = ref;
+    }
+
+    @SuppressWarnings("unchecked") // Hashmap runtime cast 
+    @Override
+    public ArrayList<Account> loadInBackground() {
+
+        ArrayList<Account> result = new ArrayList<Account>();
+
+        ArrayList<String> accountIDs;
+        HashMap<String, String> details;
+        try {
+            accountIDs = (ArrayList<String>) service.getAccountList();
+            for (String id : accountIDs) {
+
+                if (id.contentEquals("IP2IP")) {
+                    continue;
+                }
+                details = (HashMap<String, String>) service.getAccountDetails(id);
+                result.add(new Account(id, details));
+
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, e.toString());
+        } catch (NullPointerException e1) {
+            Log.e(TAG, e1.toString());
+        }
+
+        return result;
+    }
+
+}
diff --git a/src/org/sflphone/loaders/ContactsLoader.java b/src/org/sflphone/loaders/ContactsLoader.java
new file mode 100644
index 0000000..de0dd51
--- /dev/null
+++ b/src/org/sflphone/loaders/ContactsLoader.java
@@ -0,0 +1,82 @@
+package org.sflphone.loaders;
+
+import java.util.ArrayList;
+
+import org.sflphone.model.CallContact;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
+import android.provider.ContactsContract.Contacts;
+
+public class ContactsLoader extends AsyncTaskLoader<Bundle> {
+    
+//    private static final String TAG = ContactsLoader.class.getSimpleName();
+
+    // These are the Contacts rows that we will retrieve.
+    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY, Contacts.STARRED };
+    static final String[] CONTACTS_PHONES_PROJECTION = new String[] { Phone.NUMBER, Phone.TYPE };
+    static final String[] CONTACTS_SIP_PROJECTION = new String[] { SipAddress.SIP_ADDRESS, SipAddress.TYPE };
+
+    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))";
+    Uri baseUri;
+
+    public ContactsLoader(Context context, Uri u) {
+        super(context);
+        baseUri = u;
+    }
+
+    @Override
+    public Bundle loadInBackground() {
+        ArrayList<CallContact> contacts = new ArrayList<CallContact>();
+        ArrayList<CallContact> starred = new ArrayList<CallContact>();
+
+        Cursor result = getContext().getContentResolver().query(baseUri, CONTACTS_SUMMARY_PROJECTION, select, null,
+                Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
+        int iID = result.getColumnIndex(Contacts._ID);
+        int iName = result.getColumnIndex(Contacts.DISPLAY_NAME);
+        int iPhoto = result.getColumnIndex(Contacts.PHOTO_ID);
+        int iStarred = result.getColumnIndex(Contacts.STARRED);
+        CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
+        
+        while (result.moveToNext()) {
+            builder.startNewContact(result.getLong(iID), result.getString(iName), result.getLong(iPhoto));
+            
+//            Cursor cPhones = getContext().getContentResolver().query(Phone.CONTENT_URI, CONTACTS_PHONES_PROJECTION,
+//                    Phone.CONTACT_ID + " =" + result.getLong(iID), null, null);
+
+//            while (cPhones.moveToNext()) {
+//                builder.addPhoneNumber(cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)), cPhones.getInt(cPhones.getColumnIndex(Phone.TYPE)));
+////                Log.i(TAG,"Phone:"+cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)));
+//            }
+//            cPhones.close();
+//
+//            Cursor cSip = getContext().getContentResolver().query(Phone.CONTENT_URI, CONTACTS_SIP_PROJECTION,
+//                    Phone.CONTACT_ID + "=" + result.getLong(iID), null, null);
+//
+//            while (cSip.moveToNext()) {
+//                builder.addSipNumber(cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)), cSip.getInt(cSip.getColumnIndex(SipAddress.TYPE)));
+////                Log.i(TAG,"Phone:"+cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)));
+//            }
+//            cSip.close();
+
+            contacts.add(builder.build());
+            if (result.getInt(iStarred) == 1) {
+                starred.add(builder.build());
+            }
+           
+        }        
+        
+        result.close();
+        Bundle toReturn = new Bundle();
+        
+       toReturn.putParcelableArrayList("Contacts", contacts);
+       toReturn.putParcelableArrayList("Starred", starred);
+
+        return toReturn;
+    }
+}
diff --git a/src/org/sflphone/loaders/HistoryLoader.java b/src/org/sflphone/loaders/HistoryLoader.java
new file mode 100644
index 0000000..6e4673d
--- /dev/null
+++ b/src/org/sflphone/loaders/HistoryLoader.java
@@ -0,0 +1,104 @@
+package org.sflphone.loaders;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.sflphone.model.CallContact;
+import org.sflphone.model.CallContact.ContactBuilder;
+import org.sflphone.model.HistoryEntry;
+import org.sflphone.model.HistoryEntry.HistoryCall;
+import org.sflphone.service.ISipService;
+import org.sflphone.service.ServiceConstants;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.util.Log;
+
+public class HistoryLoader extends AsyncTaskLoader<ArrayList<HistoryEntry>> {
+
+    private static final String TAG = HistoryLoader.class.getSimpleName();
+    private ISipService service;
+    HashMap<String, HistoryEntry> historyEntries;
+
+    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY,
+            Contacts.STARRED };
+
+    public HistoryLoader(Context context, ISipService isip) {
+        super(context);
+        service = isip;
+    }
+
+    @SuppressWarnings("unchecked") // Hashmap runtime cast 
+    @Override
+    public ArrayList<HistoryEntry> loadInBackground() {
+
+        historyEntries = new HashMap<String, HistoryEntry>();
+
+        if (service == null) {
+            return new ArrayList<HistoryEntry>();
+        }
+        try {
+            ArrayList<HashMap<String, String>> history = (ArrayList<HashMap<String, String>>) service.getHistory();
+//            Log.i(TAG, "history size:" + history.size());
+            CallContact.ContactBuilder builder = new CallContact.ContactBuilder();
+            for (HashMap<String, String> entry : history) {
+                entry.get(ServiceConstants.history.ACCOUNT_ID_KEY);
+                long timestampEnd = Long.parseLong(entry.get(ServiceConstants.history.TIMESTAMP_STOP_KEY));
+                long timestampStart = Long.parseLong(entry.get(ServiceConstants.history.TIMESTAMP_START_KEY));
+                String call_state = entry.get(ServiceConstants.history.STATE_KEY);
+
+                String number_called = entry.get(ServiceConstants.history.PEER_NUMBER_KEY);
+
+//                Log.w(TAG, "----------------------Record" + entry.get(ServiceConstants.history.RECORDING_PATH_KEY));
+                CallContact c = null;
+                if (historyEntries.containsKey(number_called)) {
+                    historyEntries.get(number_called).addHistoryCall(
+                            new HistoryCall(timestampStart, timestampEnd, number_called, call_state, entry
+                                    .get(ServiceConstants.history.RECORDING_PATH_KEY)));
+                } else {
+
+                    Pattern p = Pattern.compile("<sip:([^@]+)@([^>]+)>");
+                    Matcher m = p.matcher(number_called);
+                    if (m.find()) {
+                        // String s1 = m.group(1);
+                        // System.out.println(s1);
+                        // String s2 = m.group(2);
+                        // System.out.println(s2);
+
+                        Cursor result = getContext().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
+                                ContactsContract.CommonDataKinds.Phone.NUMBER + " = " + m.group(1), null, null);
+
+                        if (result.getCount() > 0) {
+                            result.moveToFirst();
+                            builder.startNewContact(result.getLong(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)),
+                                    result.getString(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)),
+                                    result.getLong(result.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_ID)));
+                            builder.addPhoneNumber(number_called, 0);
+                            c = builder.build();
+                        } else {
+                            c = ContactBuilder.buildUnknownContact(number_called);
+                        }
+                        result.close();
+                    } else {
+                        c = ContactBuilder.buildUnknownContact(number_called);
+                    }
+                    HistoryEntry e = new HistoryEntry(entry.get(ServiceConstants.history.ACCOUNT_ID_KEY), c);
+                    e.addHistoryCall(new HistoryCall(timestampStart, timestampEnd, number_called, call_state, entry
+                            .get(ServiceConstants.history.RECORDING_PATH_KEY)));
+                    historyEntries.put(number_called, e);
+                }
+
+            }
+
+        } catch (RemoteException e) {
+            Log.i(TAG, e.toString());
+        }
+        return new ArrayList<HistoryEntry>(historyEntries.values());
+    }
+}
diff --git a/src/org/sflphone/loaders/LoaderConstants.java b/src/org/sflphone/loaders/LoaderConstants.java
new file mode 100644
index 0000000..ced535e
--- /dev/null
+++ b/src/org/sflphone/loaders/LoaderConstants.java
@@ -0,0 +1,9 @@
+package org.sflphone.loaders;
+
+public class LoaderConstants {
+    
+    public static final int CONTACT_LOADER = 0;
+    public static final int ACCOUNTS_LOADER = 1;
+    public static final int HISTORY_LOADER = 2;
+
+}