package com.fsck.k9; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import android.content.Context; import timber.log.Timber; import com.fsck.k9.mail.store.RemoteStore; import com.fsck.k9.mailstore.LocalStore; import com.fsck.k9.preferences.StorageEditor; import com.fsck.k9.preferences.Storage; public class Preferences { private static Preferences preferences; public static synchronized Preferences getPreferences(Context context) { Context appContext = context.getApplicationContext(); if (preferences == null) { preferences = new Preferences(appContext); } return preferences; } private Storage storage; private Map<String, Account> accounts = null; private List<Account> accountsInOrder = null; private Account newAccount; private Context context; private Preferences(Context context) { storage = Storage.getStorage(context); this.context = context; if (storage.isEmpty()) { Timber.i("Preferences storage is zero-size, importing from Android-style preferences"); StorageEditor editor = storage.edit(); editor.copy(context.getSharedPreferences("AndroidMail.Main", Context.MODE_PRIVATE)); editor.commit(); } } public synchronized void loadAccounts() { accounts = new HashMap<>(); accountsInOrder = new LinkedList<>(); String accountUuids = getStorage().getString("accountUuids", null); if ((accountUuids != null) && (accountUuids.length() != 0)) { String[] uuids = accountUuids.split(","); for (String uuid : uuids) { Account newAccount = new Account(this, uuid); accounts.put(uuid, newAccount); accountsInOrder.add(newAccount); } } if ((newAccount != null) && newAccount.getAccountNumber() != -1) { accounts.put(newAccount.getUuid(), newAccount); if (!accountsInOrder.contains(newAccount)) { accountsInOrder.add(newAccount); } newAccount = null; } } /** * Returns an array of the accounts on the system. If no accounts are * registered the method returns an empty array. * * @return all accounts */ public synchronized List<Account> getAccounts() { if (accounts == null) { loadAccounts(); } return Collections.unmodifiableList(new ArrayList<>(accountsInOrder)); } /** * Returns an array of the accounts on the system. If no accounts are * registered the method returns an empty array. * * @return all accounts with {@link Account#isAvailable(Context)} */ public synchronized Collection<Account> getAvailableAccounts() { List<Account> allAccounts = getAccounts(); Collection<Account> retval = new ArrayList<>(accounts.size()); for (Account account : allAccounts) { if (account.isEnabled() && account.isAvailable(context)) { retval.add(account); } } return retval; } public synchronized Account getAccount(String uuid) { if (accounts == null) { loadAccounts(); } return accounts.get(uuid); } public synchronized Account newAccount() { newAccount = new Account(context); accounts.put(newAccount.getUuid(), newAccount); accountsInOrder.add(newAccount); return newAccount; } public synchronized void deleteAccount(Account account) { if (accounts != null) { accounts.remove(account.getUuid()); } if (accountsInOrder != null) { accountsInOrder.remove(account); } try { RemoteStore.removeInstance(account); } catch (Exception e) { Timber.e(e, "Failed to reset remote store for account %s", account.getUuid()); } LocalStore.removeAccount(account); account.delete(this); if (newAccount == account) { newAccount = null; } } /** * Returns the Account marked as default. If no account is marked as default * the first account in the list is marked as default and then returned. If * there are no accounts on the system the method returns null. */ public Account getDefaultAccount() { String defaultAccountUuid = getStorage().getString("defaultAccountUuid", null); Account defaultAccount = getAccount(defaultAccountUuid); if (defaultAccount == null) { Collection<Account> accounts = getAvailableAccounts(); if (!accounts.isEmpty()) { defaultAccount = accounts.iterator().next(); setDefaultAccount(defaultAccount); } } return defaultAccount; } public void setDefaultAccount(Account account) { getStorage().edit().putString("defaultAccountUuid", account.getUuid()).commit(); } public Storage getStorage() { return storage; } static <T extends Enum<T>> T getEnumStringPref(Storage storage, String key, T defaultEnum) { String stringPref = storage.getString(key, null); if (stringPref == null) { return defaultEnum; } else { try { return Enum.valueOf(defaultEnum.getDeclaringClass(), stringPref); } catch (IllegalArgumentException ex) { Timber.w(ex, "Unable to convert preference key [%s] value [%s] to enum of type %s", key, stringPref, defaultEnum.getDeclaringClass()); return defaultEnum; } } } }