1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-27 19:52:17 -05:00

Added code to upgrade settings on import

This allows us to import files with an outdated content version, then
upgrade the settings to the current content version.
This commit is contained in:
cketti 2011-12-11 04:57:47 +01:00
parent d57e684296
commit 18a58e2872
7 changed files with 192 additions and 28 deletions

View File

@ -4,6 +4,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import android.content.SharedPreferences;
@ -18,6 +19,7 @@ import com.fsck.k9.preferences.Settings.*;
public class AccountSettings {
public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
public static final Map<Integer, SettingsUpgrader> UPGRADERS;
static {
Map<String, TreeMap<Integer, SettingsDescription>> s =
@ -204,6 +206,9 @@ public class AccountSettings {
));
SETTINGS = Collections.unmodifiableMap(s);
Map<Integer, SettingsUpgrader> u = new HashMap<Integer, SettingsUpgrader>();
UPGRADERS = Collections.unmodifiableMap(u);
}
public static Map<String, String> validate(int version, Map<String, String> importedSettings,
@ -211,6 +216,10 @@ public class AccountSettings {
return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
}
public static Set<String> upgrade(int version, Map<String, String> validatedSettings) {
return Settings.upgrade(version, UPGRADERS, SETTINGS, validatedSettings);
}
public static Map<String, String> getAccountSettings(SharedPreferences storage, String uuid) {
Map<String, String> result = new HashMap<String, String>();
String prefix = uuid + ".";

View File

@ -4,6 +4,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import android.content.SharedPreferences;
@ -13,6 +14,7 @@ import com.fsck.k9.preferences.Settings.*;
public class FolderSettings {
public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
public static final Map<Integer, SettingsUpgrader> UPGRADERS;
static {
Map<String, TreeMap<Integer, SettingsDescription>> s =
@ -35,6 +37,9 @@ public class FolderSettings {
));
SETTINGS = Collections.unmodifiableMap(s);
Map<Integer, SettingsUpgrader> u = new HashMap<Integer, SettingsUpgrader>();
UPGRADERS = Collections.unmodifiableMap(u);
}
public static Map<String, String> validate(int version, Map<String, String> importedSettings,
@ -42,6 +47,10 @@ public class FolderSettings {
return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
}
public static Set<String> upgrade(int version, Map<String, String> validatedSettings) {
return Settings.upgrade(version, UPGRADERS, SETTINGS, validatedSettings);
}
public static Map<String, String> getFolderSettings(SharedPreferences storage, String uuid,
String folderName) {
Map<String, String> result = new HashMap<String, String>();

View File

@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import android.content.SharedPreferences;
@ -19,6 +20,7 @@ import com.fsck.k9.preferences.Settings.*;
public class GlobalSettings {
public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
public static final Map<Integer, SettingsUpgrader> UPGRADERS;
static {
Map<String, TreeMap<Integer, SettingsDescription>> s =
@ -191,12 +193,19 @@ public class GlobalSettings {
));
SETTINGS = Collections.unmodifiableMap(s);
Map<Integer, SettingsUpgrader> u = new HashMap<Integer, SettingsUpgrader>();
UPGRADERS = Collections.unmodifiableMap(u);
}
public static Map<String, String> validate(int version, Map<String, String> importedSettings) {
return Settings.validate(version, SETTINGS, importedSettings, false);
}
public static Set<String> upgrade(int version, Map<String, String> validatedSettings) {
return Settings.upgrade(version, UPGRADERS, SETTINGS, validatedSettings);
}
public static Map<String, String> getGlobalSettings(SharedPreferences storage) {
Map<String, String> result = new HashMap<String, String>();
for (String key : SETTINGS.keySet()) {

View File

@ -4,6 +4,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import android.content.SharedPreferences;
@ -15,6 +16,7 @@ import com.fsck.k9.preferences.Settings.*;
public class IdentitySettings {
public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
public static final Map<Integer, SettingsUpgrader> UPGRADERS;
static {
Map<String, TreeMap<Integer, SettingsDescription>> s =
@ -31,6 +33,9 @@ public class IdentitySettings {
));
SETTINGS = Collections.unmodifiableMap(s);
Map<Integer, SettingsUpgrader> u = new HashMap<Integer, SettingsUpgrader>();
UPGRADERS = Collections.unmodifiableMap(u);
}
public static Map<String, String> validate(int version, Map<String, String> importedSettings,
@ -38,6 +43,10 @@ public class IdentitySettings {
return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
}
public static Set<String> upgrade(int version, Map<String, String> validatedSettings) {
return Settings.upgrade(version, UPGRADERS, SETTINGS, validatedSettings);
}
public static Map<String, String> getIdentitySettings(SharedPreferences storage, String uuid,
int identityIndex) {
Map<String, String> result = new HashMap<String, String>();

View File

@ -2,7 +2,9 @@ package com.fsck.k9.preferences;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
@ -13,7 +15,6 @@ import com.fsck.k9.K9;
/*
* TODO:
* - add support for different settings versions (validate old version and upgrade to new format)
* - use the default values defined in GlobalSettings and AccountSettings when creating new
* accounts
* - think of a better way to validate enums than to use the resource arrays (i.e. get rid of
@ -83,6 +84,82 @@ public class Settings {
return validatedSettings;
}
/**
* Upgrade settings using the settings structure and/or special upgrade code.
*
* @param version
* The content version of the settings in {@code validatedSettings}.
* @param upgraders
* A map of {@link SettingsUpgrader}s for nontrivial settings upgrades.
* @param settings
* The structure describing the different settings, possibly containing multiple
* versions.
* @param validatedSettings
* The settings as returned by {@link Settings#validate(int, Map, Map, boolean)}.
* This map is modified and contains the upgraded settings when this method returns.
*
* @return A set of setting names that were removed during the upgrade process or {@code null}
* if none were removed.
*/
public static Set<String> upgrade(int version, Map<Integer, SettingsUpgrader> upgraders,
Map<String, TreeMap<Integer, SettingsDescription>> settings,
Map<String, String> validatedSettings) {
Map<String, String> upgradedSettings = validatedSettings;
Set<String> deletedSettings = null;
for (int toVersion = version + 1; toVersion <= VERSION; toVersion++) {
// Check if there's an SettingsUpgrader for that version
SettingsUpgrader upgrader = upgraders.get(toVersion);
if (upgrader != null) {
deletedSettings = upgrader.upgrade(upgradedSettings);
}
// Deal with settings that don't need special upgrade code
for (Entry<String, TreeMap<Integer, SettingsDescription>> versions :
settings.entrySet()) {
String settingName = versions.getKey();
TreeMap<Integer, SettingsDescription> versionedSettings = versions.getValue();
// Handle newly added settings
if (versionedSettings.firstKey().intValue() == toVersion) {
// Check if it was already added to upgradedSettings by the SettingsUpgrader
if (!upgradedSettings.containsKey(settingName)) {
// Insert default value to upgradedSettings
SettingsDescription setting = versionedSettings.firstEntry().getValue();
Object defaultValue = setting.getDefaultValue();
upgradedSettings.put(settingName, setting.toString(defaultValue));
if (K9.DEBUG) {
String prettyValue = setting.toPrettyString(defaultValue);
Log.v(K9.LOG_TAG, "Added new setting \"" + settingName +
"\" with default value \"" + prettyValue + "\"");
}
}
}
// Handle removed settings
Entry<Integer, SettingsDescription> lastEntry = versionedSettings.lastEntry();
if (lastEntry.getKey().intValue() == toVersion && lastEntry.getValue() == null) {
upgradedSettings.remove(settingName);
if (deletedSettings == null) {
deletedSettings = new HashSet<String>();
}
deletedSettings.add(settingName);
if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Removed setting \"" + settingName + "\"");
}
}
}
}
return deletedSettings;
}
/**
* Creates a {@link TreeMap} linking version numbers to {@link SettingsDescription} instances.
*
@ -234,6 +311,25 @@ public class Settings {
}
}
/**
* Used for a nontrivial settings upgrade.
*
* @see Settings#upgrade(int, Map, Map, Map)
*/
public interface SettingsUpgrader {
/**
* Upgrade the provided settings.
*
* @param settings
* The settings to upgrade. This map is modified and contains the upgraded
* settings when this method returns.
*
* @return A set of setting names that were removed during the upgrade process or
* {@code null} if none were removed.
*/
public Set<String> upgrade(Map<String, String> settings);
}
/**
* A string setting.

View File

@ -173,6 +173,11 @@ public class SettingsExporter {
String key = versionedSetting.getKey();
String valueString = (String) prefs.get(key);
SettingsDescription setting = versionedSetting.getValue().lastEntry().getValue();
if (setting == null) {
// Setting was removed.
continue;
}
if (valueString != null) {
try {
Object value = setting.fromString(valueString);
@ -319,6 +324,7 @@ public class SettingsExporter {
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
if (setting != null) {
// Only export account settings that can be found in AccountSettings.SETTINGS
try {
Object value = setting.fromString(valueString);
@ -331,6 +337,7 @@ public class SettingsExporter {
}
}
}
}
serializer.endTag(null, SETTINGS_ELEMENT);
if (identities.size() > 0) {
@ -411,6 +418,7 @@ public class SettingsExporter {
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
if (setting != null) {
// Only write settings that have an entry in IdentitySettings.SETTINGS
try {
Object value = setting.fromString(valueString);
@ -423,6 +431,7 @@ public class SettingsExporter {
}
}
}
}
serializer.endTag(null, SETTINGS_ELEMENT);
serializer.endTag(null, IDENTITY_ELEMENT);
@ -460,6 +469,7 @@ public class SettingsExporter {
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
if (setting != null) {
// Only write settings that have an entry in FolderSettings.SETTINGS
try {
Object value = setting.fromString(valueString);
@ -472,6 +482,7 @@ public class SettingsExporter {
}
}
}
}
serializer.endTag(null, FOLDER_ELEMENT);
}

View File

@ -303,9 +303,15 @@ public class SettingsImporter {
private static void importGlobalSettings(SharedPreferences storage,
SharedPreferences.Editor editor, int contentVersion, ImportedSettings settings) {
// Validate global settings
Map<String, String> validatedSettings = GlobalSettings.validate(contentVersion,
settings.settings);
// Upgrade global settings to current content version
if (contentVersion != Settings.VERSION) {
GlobalSettings.upgrade(contentVersion, validatedSettings);
}
// Use current global settings as base and overwrite with validated settings read from the
// import file.
Map<String, String> mergedSettings =
@ -396,6 +402,11 @@ public class SettingsImporter {
AccountSettings.validate(contentVersion, account.settings.settings,
!mergeImportedAccount);
// Upgrade account settings to current content version
if (contentVersion != Settings.VERSION) {
AccountSettings.upgrade(contentVersion, validatedSettings);
}
// Merge account settings if necessary
Map<String, String> writeSettings;
if (mergeImportedAccount) {
@ -448,6 +459,11 @@ public class SettingsImporter {
Map<String, String> validatedSettings =
FolderSettings.validate(contentVersion, folder.settings.settings, !overwrite);
// Upgrade folder settings to current content version
if (contentVersion != Settings.VERSION) {
FolderSettings.upgrade(contentVersion, validatedSettings);
}
// Merge folder settings if necessary
Map<String, String> writeSettings;
if (overwrite) {
@ -537,6 +553,11 @@ public class SettingsImporter {
Map<String, String> validatedSettings = IdentitySettings.validate(
contentVersion, identity.settings.settings, !mergeSettings);
// Upgrade identity settings to current content version
if (contentVersion != Settings.VERSION) {
IdentitySettings.upgrade(contentVersion, validatedSettings);
}
// Merge identity settings if necessary
Map<String, String> writeSettings;
if (mergeSettings) {