From a46be312c09ca649e4c0c37a7ce63f8e0768e55a Mon Sep 17 00:00:00 2001 From: sspanak Date: Wed, 16 Oct 2024 18:41:22 +0300 Subject: [PATCH] word pairs are now deleted when a language is deleted; DataStore code cleanup --- .../github/sspanak/tt9/db/BaseSyncStore.java | 18 ++++ .../io/github/sspanak/tt9/db/DataStore.java | 82 ++++++++++++------- .../tt9/db/wordPairs/WordPairStore.java | 20 +++-- .../sspanak/tt9/db/words/WordStore.java | 20 ++--- .../screens/languages/ItemTruncateAll.java | 9 +- .../languages/ItemTruncateUnselected.java | 10 ++- 6 files changed, 97 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/io/github/sspanak/tt9/db/BaseSyncStore.java b/app/src/main/java/io/github/sspanak/tt9/db/BaseSyncStore.java index 8bde9a79..11e5cca4 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/BaseSyncStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/BaseSyncStore.java @@ -26,4 +26,22 @@ public class BaseSyncStore { return true; } + + public void startTransaction() { + if (sqlite != null) { + sqlite.beginTransaction(); + } + } + + public void failTransaction() { + if (sqlite != null) { + sqlite.failTransaction(); + } + } + + public void finishTransaction() { + if (sqlite != null) { + sqlite.finishTransaction(); + } + } } diff --git a/app/src/main/java/io/github/sspanak/tt9/db/DataStore.java b/app/src/main/java/io/github/sspanak/tt9/db/DataStore.java index 576b98a5..e9e1bb2e 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/DataStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/DataStore.java @@ -13,6 +13,7 @@ import io.github.sspanak.tt9.db.words.DictionaryLoader; import io.github.sspanak.tt9.db.words.WordStore; import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.util.ConsumerCompat; +import io.github.sspanak.tt9.util.Logger; public class DataStore { private static final Handler asyncHandler = new Handler(); @@ -26,67 +27,92 @@ public class DataStore { } + private static void runInThread(@NonNull Runnable action) { + new Thread(action).start(); + } + + + private static void runInTransaction(@NonNull Runnable action, @NonNull Runnable onFinish, @NonNull String errorMessagePrefix) { + runInThread(() -> { + try { + words.startTransaction(); + action.run(); + words.finishTransaction(); + } catch (Exception e) { + words.failTransaction(); + Logger.e(DataStore.class.getSimpleName(), errorMessagePrefix + " " + e.getMessage()); + } + onFinish.run(); + }); + } + + public static void normalizeNext() { - new Thread(() -> words.normalizeNext()).start(); + runInThread(() -> words.normalizeNext()); } public static void getLastLanguageUpdateTime(ConsumerCompat notification, Language language) { - new Thread(() -> notification.accept(words.getLanguageFileHash(language))).start(); + runInThread(() -> notification.accept(words.getLanguageFileHash(language))); } public static void deleteCustomWord(Runnable notification, Language language, String word) { - new Thread(() -> { + runInThread(() -> { words.removeCustomWord(language, word); notification.run(); - }).start(); + }); } - public static void deleteWords(Runnable notification, @NonNull ArrayList languageIds) { - new Thread(() -> { - words.remove(languageIds); - notification.run(); - }).start(); + public static void deleteLanguages(Runnable notification, @NonNull ArrayList languages) { + runInTransaction( + () -> { words.remove(languages); pairs.remove(languages); }, + notification, + "Failed deleting languages." + ); } public static void put(ConsumerCompat statusHandler, Language language, String word) { - new Thread(() -> statusHandler.accept(words.put(language, word))).start(); + runInThread(() -> statusHandler.accept(words.put(language, word))); } public static void makeTopWord(@NonNull Language language, @NonNull String word, @NonNull String sequence) { - new Thread(() -> words.makeTopWord(language, word, sequence)).start(); + runInThread(() -> words.makeTopWord(language, word, sequence)); } public static void getWords(ConsumerCompat> dataHandler, Language language, String sequence, String filter, int minWords, int maxWords) { - new Thread(() -> asyncHandler.post(() -> dataHandler.accept( - words.getSimilar(language, sequence, filter, minWords, maxWords))) - ).start(); + runInThread(() -> { + ArrayList data = words.getSimilar(language, sequence, filter, minWords, maxWords); + asyncHandler.post(() -> dataHandler.accept(data)); + }); } public static void getCustomWords(ConsumerCompat> dataHandler, String wordFilter, int maxWords) { - new Thread(() -> asyncHandler.post(() -> dataHandler.accept( - words.getSimilarCustom(wordFilter, maxWords))) - ).start(); + runInThread(() -> { + ArrayList data = words.getSimilarCustom(wordFilter, maxWords); + asyncHandler.post(() -> dataHandler.accept(data)); + }); } public static void countCustomWords(ConsumerCompat dataHandler) { - new Thread(() -> asyncHandler.post(() -> dataHandler.accept( - words.countCustom())) - ).start(); + runInThread(() -> { + long data = words.countCustom(); + asyncHandler.post(() -> dataHandler.accept(data)); + }); } public static void exists(ConsumerCompat> dataHandler, ArrayList languages) { - new Thread(() -> asyncHandler.post(() -> dataHandler.accept( - words.exists(languages)) - )).start(); + runInThread(() -> { + ArrayList data = words.exists(languages); + asyncHandler.post(() -> dataHandler.accept(data)); + }); } @@ -101,12 +127,12 @@ public class DataStore { public static void saveWordPairs() { - new Thread(() -> pairs.save()).start(); + runInThread(() -> pairs.save()); } public static void loadWordPairs(DictionaryLoader dictionaryLoader, ArrayList languages) { - new Thread(() -> pairs.load(dictionaryLoader, languages)).start(); + runInThread(() -> pairs.load(dictionaryLoader, languages)); } @@ -114,11 +140,9 @@ public class DataStore { pairs.clearCache(); } + public static void deleteWordPairs(@NonNull ArrayList languages, @NonNull Runnable onDeleted) { - new Thread(() -> { - pairs.delete(languages); - onDeleted.run(); - }).start(); + runInTransaction(() -> pairs.remove(languages), onDeleted, "Failed deleting word pairs."); } diff --git a/app/src/main/java/io/github/sspanak/tt9/db/wordPairs/WordPairStore.java b/app/src/main/java/io/github/sspanak/tt9/db/wordPairs/WordPairStore.java index 7d7488ce..962e1365 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/wordPairs/WordPairStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/wordPairs/WordPairStore.java @@ -21,6 +21,8 @@ import io.github.sspanak.tt9.util.Logger; import io.github.sspanak.tt9.util.Timer; public class WordPairStore extends BaseSyncStore { + private static final String LOG_TAG = WordPairStore.class.getSimpleName(); + // data private final ConcurrentHashMap> pairs = new ConcurrentHashMap<>(); @@ -111,7 +113,7 @@ public class WordPairStore extends BaseSyncStore { long currentTime = Timer.stop(SAVE_TIMER_NAME); slowestSaveTime = Math.max(slowestSaveTime, currentTime); - Logger.d(getClass().getSimpleName(), "Saved all word pairs in: " + currentTime + " ms"); + Logger.d(LOG_TAG, "Saved all word pairs in: " + currentTime + " ms"); } @@ -121,12 +123,12 @@ public class WordPairStore extends BaseSyncStore { } if (dictionaryLoader.isRunning()) { - Logger.e(getClass().getSimpleName(), "Cannot load word pairs while the DictionaryLoader is working."); + Logger.e(LOG_TAG, "Cannot load word pairs while the DictionaryLoader is working."); return; } if (languages == null) { - Logger.e(getClass().getSimpleName(), "Cannot load word pairs for NULL language list."); + Logger.e(LOG_TAG, "Cannot load word pairs for NULL language list."); return; } @@ -149,25 +151,27 @@ public class WordPairStore extends BaseSyncStore { wordPairs.put(pair, pair); } - Logger.d(getClass().getSimpleName(), "Loaded " + wordPairs.size() + " word pairs for language: " + language.getId()); + Logger.d(LOG_TAG, "Loaded " + wordPairs.size() + " word pairs for language: " + language.getId()); } long currentTime = Timer.stop(LOAD_TIMER_NAME); slowestLoadTime = Math.max(slowestLoadTime, currentTime); - Logger.d(getClass().getSimpleName(), "Loaded " + totalPairs + " word pairs in " + currentTime + " ms"); + Logger.d(LOG_TAG, "Loaded " + totalPairs + " word pairs in " + currentTime + " ms"); } - public void delete(@NonNull ArrayList languages) { + public void remove(@NonNull ArrayList languages) { if (!checkOrNotify()) { return; } - sqlite.beginTransaction(); + Timer.start(LOG_TAG); + for (Language language : languages) { DeleteOps.deleteWordPairs(sqlite.getDb(), language.getId()); } - sqlite.finishTransaction(); + + Logger.d(LOG_TAG, "Deleted " + languages.size() + " word pair groups. Time: " + Timer.stop(LOG_TAG) + " ms"); slowestLoadTime = 0; slowestSaveTime = 0; diff --git a/app/src/main/java/io/github/sspanak/tt9/db/words/WordStore.java b/app/src/main/java/io/github/sspanak/tt9/db/words/WordStore.java index adfa2754..8d8ff151 100644 --- a/app/src/main/java/io/github/sspanak/tt9/db/words/WordStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/db/words/WordStore.java @@ -109,26 +109,20 @@ public class WordStore extends BaseSyncStore { } - public void remove(ArrayList languageIds) { + public void remove(ArrayList languages) { if (!checkOrNotify()) { return; } Timer.start(LOG_TAG); - try { - sqlite.beginTransaction(); - for (int langId : languageIds) { - if (readOps.exists(sqlite.getDb(), langId)) { - DeleteOps.delete(sqlite.getDb(), langId); - } - } - sqlite.finishTransaction(); - Logger.d(LOG_TAG, "Deleted " + languageIds.size() + " languages. Time: " + Timer.stop(LOG_TAG) + " ms"); - } catch (Exception e) { - sqlite.failTransaction(); - Logger.e(LOG_TAG, "Failed deleting languages. " + e.getMessage()); + for (Language lang : languages) { + if (readOps.exists(sqlite.getDb(), lang.getId())) { + DeleteOps.delete(sqlite.getDb(), lang.getId()); + } } + + Logger.d(LOG_TAG, "Deleted " + languages.size() + " languages. Time: " + Timer.stop(LOG_TAG) + " ms"); } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateAll.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateAll.java index b1ba964a..69e1d7a1 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateAll.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateAll.java @@ -2,11 +2,8 @@ package io.github.sspanak.tt9.preferences.screens.languages; import androidx.preference.Preference; -import java.util.ArrayList; - import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.db.DataStore; -import io.github.sspanak.tt9.languages.Language; import io.github.sspanak.tt9.languages.LanguageCollection; import io.github.sspanak.tt9.preferences.PreferencesActivity; import io.github.sspanak.tt9.preferences.items.ItemClickable; @@ -32,11 +29,7 @@ class ItemTruncateAll extends ItemClickable { @Override protected boolean onClick(Preference p) { onStartDeleting(); - ArrayList languageIds = new ArrayList<>(); - for (Language lang : LanguageCollection.getAll(activity, false)) { - languageIds.add(lang.getId()); - } - DataStore.deleteWords(this::onFinishDeleting, languageIds); + DataStore.deleteLanguages(this::onFinishDeleting, LanguageCollection.getAll(activity, false)); return true; } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateUnselected.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateUnselected.java index 586a992f..aca5a26b 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateUnselected.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/languages/ItemTruncateUnselected.java @@ -3,6 +3,8 @@ package io.github.sspanak.tt9.preferences.screens.languages; import androidx.preference.Preference; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import io.github.sspanak.tt9.db.DataStore; import io.github.sspanak.tt9.languages.Language; @@ -21,16 +23,16 @@ class ItemTruncateUnselected extends ItemTruncateAll { @Override protected boolean onClick(Preference p) { - ArrayList unselectedLanguageIds = new ArrayList<>(); - ArrayList selectedLanguageIds = activity.getSettings().getEnabledLanguageIds(); + ArrayList unselectedLanguages = new ArrayList<>(); + Set selectedLanguageIds = new HashSet<>(activity.getSettings().getEnabledLanguageIds()); for (Language lang : LanguageCollection.getAll(activity, false)) { if (!selectedLanguageIds.contains(lang.getId())) { - unselectedLanguageIds.add(lang.getId()); + unselectedLanguages.add(lang); } } onStartDeleting(); - DataStore.deleteWords(this::onFinishDeleting, unselectedLanguageIds); + DataStore.deleteLanguages(this::onFinishDeleting, unselectedLanguages); return true; }