diff options
author | ByteHamster <info@bytehamster.com> | 2022-02-27 12:12:24 +0100 |
---|---|---|
committer | ByteHamster <info@bytehamster.com> | 2022-02-27 19:47:41 +0100 |
commit | ff3258c34a1797e75538b83baa1e867d0ea07ceb (patch) | |
tree | 82530a8ce01909638b143ae0d72f3862811c5321 /core | |
parent | 42e36328e3bb6d4bda632da7586fdace912a34e0 (diff) | |
download | AntennaPod-ff3258c34a1797e75538b83baa1e867d0ea07ceb.zip |
Move database to its own module
Diffstat (limited to 'core')
41 files changed, 56 insertions, 2698 deletions
diff --git a/core/build.gradle b/core/build.gradle index 13489f996..9eb9c8c90 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation project(':parser:media') implementation project(':playback:base') implementation project(':playback:cast') + implementation project(':storage:database') implementation project(':ui:app-start-intent') implementation project(':ui:common') implementation project(':ui:i18n') diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java index ac67fb042..e03c8118d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java @@ -9,9 +9,9 @@ import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.preferences.UsageStatistics; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; -import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.NetworkUtils; import de.danoeh.antennapod.core.util.gui.NotificationUtils; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import java.io.File; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java index e0e1bbaa5..4cf2703d6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java @@ -22,12 +22,12 @@ import java.util.Set; import java.util.UUID; import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.parser.feed.util.DateUtils; -import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.model.download.DownloadError; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java index a083a7220..7e80fb231 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java @@ -5,7 +5,7 @@ import android.text.TextUtils; import java.util.ArrayList; import java.util.List; -import de.danoeh.antennapod.core.util.LongIntMap; +import de.danoeh.antennapod.storage.database.LongIntMap; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedPreferences; diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 82e1fb55a..f6caa9016 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -13,6 +13,7 @@ import androidx.annotation.VisibleForTesting; import androidx.core.app.NotificationCompat; import androidx.preference.PreferenceManager; +import de.danoeh.antennapod.model.feed.FeedCounter; import org.json.JSONArray; import org.json.JSONException; @@ -141,11 +142,6 @@ public class UserPreferences { public static final int FEED_ORDER_COUNTER = 0; public static final int FEED_ORDER_ALPHABETICAL = 1; public static final int FEED_ORDER_MOST_PLAYED = 3; - public static final int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; - public static final int FEED_COUNTER_SHOW_NEW = 1; - public static final int FEED_COUNTER_SHOW_UNPLAYED = 2; - public static final int FEED_COUNTER_SHOW_NONE = 3; - public static final int FEED_COUNTER_SHOW_DOWNLOADED = 4; private static Context context; private static SharedPreferences prefs; @@ -247,9 +243,9 @@ public class UserPreferences { .apply(); } - public static int getFeedCounterSetting() { - String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FEED_COUNTER_SHOW_NEW); - return Integer.parseInt(value); + public static FeedCounter getFeedCounterSetting() { + String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FeedCounter.SHOW_NEW.id); + return FeedCounter.fromOrdinal(Integer.parseInt(value)); } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 1973c626b..1522f42e2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -20,6 +20,7 @@ import androidx.core.app.ServiceCompat; import androidx.core.content.ContextCompat; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.LocalFeedUpdater; +import de.danoeh.antennapod.model.download.DownloadStatus; import org.apache.commons.io.FileUtils; import org.greenrobot.eventbus.EventBus; @@ -50,7 +51,7 @@ import de.danoeh.antennapod.core.service.download.handler.PostDownloaderTask; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.model.download.DownloadError; /** * Manages the download of feedfiles in the app. Downloads can be enqueued via the startService intent. diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java index 48a9e8017..5c5d665d8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java @@ -10,6 +10,7 @@ import androidx.core.app.NotificationCompat; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.util.DownloadErrorLabel; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.util.gui.NotificationUtils; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java deleted file mode 100644 index 9d4f1ab43..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java +++ /dev/null @@ -1,154 +0,0 @@ -package de.danoeh.antennapod.core.service.download; - -import androidx.annotation.NonNull; - -import java.util.Date; - -import de.danoeh.antennapod.model.feed.FeedFile; -import de.danoeh.antennapod.core.util.DownloadError; - -/** - * Contains status attributes for one download - */ -public class DownloadStatus { - /** - * Downloaders should use this constant for the size attribute if necessary - * so that the listadapters etc. can react properly. - */ - public static final int SIZE_UNKNOWN = -1; - - // ----------------------------------- ATTRIBUTES STORED IN DB - /** - * A human-readable string which is shown to the user so that he can - * identify the download. Should be the title of the item/feed/media or the - * URL if the download has no other title. - */ - private final String title; - private final long feedfileId; - /** - * Is used to determine the type of the feedfile even if the feedfile does - * not exist anymore. The value should be FEEDFILETYPE_FEED, - * FEEDFILETYPE_FEEDIMAGE or FEEDFILETYPE_FEEDMEDIA - */ - private final int feedfileType; - private final boolean initiatedByUser; - /** - * Unique id for storing the object in database. - */ - private long id; - private DownloadError reason; - /** - * A message which can be presented to the user to give more information. - * Should be null if Download was successful. - */ - private String reasonDetailed; - private boolean successful; - private final Date completionDate; - // ------------------------------------ NOT STORED IN DB - private boolean done; - private boolean cancelled; - - /** - * Constructor for creating new completed downloads. - */ - public DownloadStatus(@NonNull FeedFile feedfile, String title, DownloadError reason, boolean successful, - String reasonDetailed, boolean initiatedByUser) { - this(0, title, feedfile.getId(), feedfile.getTypeAsInt(), successful, false, true, reason, new Date(), - reasonDetailed, initiatedByUser); - } - - public DownloadStatus(long id, String title, long feedfileId, int feedfileType, boolean successful, - boolean cancelled, boolean done, DownloadError reason, Date completionDate, - String reasonDetailed, boolean initiatedByUser) { - this.id = id; - this.title = title; - this.feedfileId = feedfileId; - this.reason = reason; - this.successful = successful; - this.cancelled = cancelled; - this.done = done; - this.completionDate = (Date) completionDate.clone(); - this.reasonDetailed = reasonDetailed; - this.feedfileType = feedfileType; - this.initiatedByUser = initiatedByUser; - } - - @Override - @NonNull - public String toString() { - return "DownloadStatus [id=" + id + ", title=" + title + ", reason=" - + reason + ", reasonDetailed=" + reasonDetailed - + ", successful=" + successful + ", completionDate=" - + completionDate + ", feedfileId=" + feedfileId - + ", feedfileType=" + feedfileType + ", done=" + done - + ", cancelled=" + cancelled + "]"; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public DownloadError getReason() { - return reason; - } - - public String getReasonDetailed() { - return reasonDetailed; - } - - public boolean isSuccessful() { - return successful; - } - - public Date getCompletionDate() { - return (Date) completionDate.clone(); - } - - public long getFeedfileId() { - return feedfileId; - } - - public int getFeedfileType() { - return feedfileType; - } - - public boolean isInitiatedByUser() { - return initiatedByUser; - } - - public boolean isDone() { - return done; - } - - public boolean isCancelled() { - return cancelled; - } - - public void setSuccessful() { - this.successful = true; - this.reason = DownloadError.SUCCESS; - this.done = true; - } - - public void setFailed(DownloadError reason, String reasonDetailed) { - this.successful = false; - this.reason = reason; - this.reasonDetailed = reasonDetailed; - this.done = true; - } - - public void setCancelled() { - this.successful = false; - this.reason = DownloadError.ERROR_DOWNLOAD_CANCELLED; - this.done = true; - this.cancelled = true; - } -}
\ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java index 3cc16d12a..fe44faac9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java @@ -9,6 +9,7 @@ import java.util.concurrent.Callable; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.model.download.DownloadStatus; /** * Downloads files diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 698278af9..894428f44 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -5,6 +5,7 @@ import android.text.TextUtils; import android.util.Log; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.danoeh.antennapod.model.download.DownloadStatus; import okhttp3.CacheControl; import org.apache.commons.io.IOUtils; @@ -24,7 +25,7 @@ import java.util.Date; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.parser.feed.util.DateUtils; -import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.model.download.DownloadError; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.URIUtil; import okhttp3.OkHttpClient; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java index f7ed049cd..0e046978e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java @@ -17,12 +17,12 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.model.feed.Feed; +import de.danoeh.antennapod.model.feed.FeedCounter; import de.danoeh.antennapod.model.feed.FeedPreferences; import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.storage.PodDBAdapter; -import de.danoeh.antennapod.core.util.LongIntMap; +import de.danoeh.antennapod.storage.database.LongIntMap; import de.danoeh.antennapod.core.util.gui.NotificationUtils; +import de.danoeh.antennapod.storage.database.PodDBAdapter; public class NewEpisodesNotification { private static final String TAG = "NewEpisodesNotification"; @@ -36,7 +36,7 @@ public class NewEpisodesNotification { public void loadCountersBeforeRefresh() { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - countersBefore = adapter.getFeedCounters(UserPreferences.FEED_COUNTER_SHOW_NEW); + countersBefore = adapter.getFeedCounters(FeedCounter.SHOW_NEW); adapter.close(); } @@ -130,7 +130,7 @@ public class NewEpisodesNotification { private static int getNewEpisodeCount(long feedId) { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - int episodeCount = adapter.getFeedCounters(UserPreferences.FEED_COUNTER_SHOW_NEW, feedId).get(feedId); + int episodeCount = adapter.getFeedCounters(FeedCounter.SHOW_NEW, feedId).get(feedId); adapter.close(); return episodeCount; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java index 7e3b07880..76c464a6d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java @@ -7,11 +7,11 @@ import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedPreferences; import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting; import de.danoeh.antennapod.core.service.download.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.parser.feed.FeedHandler; import de.danoeh.antennapod.parser.feed.FeedHandlerResult; import de.danoeh.antennapod.parser.feed.UnsupportedFeedtypeException; -import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.model.download.DownloadError; import de.danoeh.antennapod.core.util.InvalidFeedException; import org.xml.sax.SAXException; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java index 8f559a889..042a903d3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java @@ -4,7 +4,7 @@ import android.content.Context; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.core.service.download.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.parser.feed.FeedHandlerResult; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java index 541e17cf6..90254c1f3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java @@ -13,12 +13,12 @@ import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.core.service.download.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink; import de.danoeh.antennapod.core.util.ChapterUtils; -import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.model.download.DownloadError; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.net.sync.model.EpisodeAction; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index c7b72c332..64cf446aa 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -15,7 +15,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import de.danoeh.antennapod.core.storage.mapper.DownloadStatusCursorMapper; import de.danoeh.antennapod.model.feed.Chapter; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; @@ -24,13 +23,15 @@ import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.model.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.SubscriptionsFilter; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadStatus; -import de.danoeh.antennapod.core.storage.mapper.ChapterCursorMapper; -import de.danoeh.antennapod.core.storage.mapper.FeedCursorMapper; -import de.danoeh.antennapod.core.storage.mapper.FeedItemCursorMapper; -import de.danoeh.antennapod.core.storage.mapper.FeedMediaCursorMapper; -import de.danoeh.antennapod.core.storage.mapper.FeedPreferencesCursorMapper; -import de.danoeh.antennapod.core.util.LongIntMap; +import de.danoeh.antennapod.model.download.DownloadStatus; +import de.danoeh.antennapod.storage.database.PodDBAdapter; +import de.danoeh.antennapod.storage.database.mapper.DownloadStatusCursorMapper; +import de.danoeh.antennapod.storage.database.mapper.ChapterCursorMapper; +import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper; +import de.danoeh.antennapod.storage.database.mapper.FeedItemCursorMapper; +import de.danoeh.antennapod.storage.database.mapper.FeedMediaCursorMapper; +import de.danoeh.antennapod.storage.database.mapper.FeedPreferencesCursorMapper; +import de.danoeh.antennapod.storage.database.LongIntMap; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; @@ -877,7 +878,7 @@ public final class DBReader { PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - final LongIntMap feedCounters = adapter.getFeedCounters(); + final LongIntMap feedCounters = adapter.getFeedCounters(UserPreferences.getFeedCounterSetting()); SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter(); List<Feed> feeds = subscriptionsFilter.filter(getFeedList(adapter), feedCounters); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index f447090a8..e5310c4ff 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -13,6 +13,8 @@ import androidx.annotation.VisibleForTesting; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.storage.database.PodDBAdapter; +import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper; import org.greenrobot.eventbus.EventBus; import java.util.ArrayList; @@ -32,11 +34,10 @@ import de.danoeh.antennapod.event.FeedItemEvent; import de.danoeh.antennapod.event.FeedListUpdateEvent; import de.danoeh.antennapod.event.MessageEvent; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadStatus; -import de.danoeh.antennapod.core.storage.mapper.FeedCursorMapper; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.core.sync.SyncService; import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink; -import de.danoeh.antennapod.core.util.DownloadError; +import de.danoeh.antennapod.model.download.DownloadError; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; import de.danoeh.antennapod.model.feed.Feed; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java deleted file mode 100644 index 4e0a6aeda..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java +++ /dev/null @@ -1,331 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.media.MediaMetadataRetriever; -import android.util.Log; - -import de.danoeh.antennapod.model.feed.FeedItem; - -import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL; - -class DBUpgrader { - /** - * Upgrades the given database to a new schema version - */ - static void upgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { - if (oldVersion <= 1) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " - + PodDBAdapter.KEY_TYPE + " TEXT"); - } - if (oldVersion <= 2) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS - + " ADD COLUMN " + PodDBAdapter.KEY_LINK + " TEXT"); - } - if (oldVersion <= 3) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " ADD COLUMN " + PodDBAdapter.KEY_ITEM_IDENTIFIER + " TEXT"); - } - if (oldVersion <= 4) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " - + PodDBAdapter.KEY_FEED_IDENTIFIER + " TEXT"); - } - if (oldVersion <= 5) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG - + " ADD COLUMN " + PodDBAdapter.KEY_REASON_DETAILED + " TEXT"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG - + " ADD COLUMN " + PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE + " TEXT"); - } - if (oldVersion <= 6) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS - + " ADD COLUMN " + PodDBAdapter.KEY_CHAPTER_TYPE + " INTEGER"); - } - if (oldVersion <= 7) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " ADD COLUMN " + PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE - + " INTEGER"); - } - if (oldVersion <= 8) { - final int KEY_ID_POSITION = 0; - final int KEY_MEDIA_POSITION = 1; - - // Add feeditem column to feedmedia table - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " ADD COLUMN " + PodDBAdapter.KEY_FEEDITEM - + " INTEGER"); - Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS, - new String[]{PodDBAdapter.KEY_ID, PodDBAdapter.KEY_MEDIA}, "? > 0", - new String[]{PodDBAdapter.KEY_MEDIA}, null, null, null); - if (feeditemCursor.moveToFirst()) { - db.beginTransaction(); - ContentValues contentValues = new ContentValues(); - do { - long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION); - contentValues.put(PodDBAdapter.KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION)); - db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, PodDBAdapter.KEY_ID + "=?", new String[]{String.valueOf(mediaId)}); - contentValues.clear(); - } while (feeditemCursor.moveToNext()); - db.setTransactionSuccessful(); - db.endTransaction(); - } - feeditemCursor.close(); - } - if (oldVersion <= 9) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ENABLED - + " INTEGER DEFAULT 1"); - } - if (oldVersion <= 10) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN flattr_status" - + " INTEGER"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " ADD COLUMN flattr_status" - + " INTEGER"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " ADD COLUMN " + PodDBAdapter.KEY_PLAYED_DURATION - + " INTEGER"); - } - if (oldVersion <= 11) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_USERNAME - + " TEXT"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_PASSWORD - + " TEXT"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " ADD COLUMN image" - + " INTEGER"); - } - if (oldVersion <= 12) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_NEXT_PAGE_LINK + " TEXT"); - } - if (oldVersion <= 13) { - // remove duplicate rows in "Chapters" table that were created because of a bug. - db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " + - "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)", - PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS, - PodDBAdapter.KEY_ID, - PodDBAdapter.KEY_ID, - PodDBAdapter.KEY_ID, - PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS, - PodDBAdapter.KEY_TITLE, - PodDBAdapter.KEY_START, - PodDBAdapter.KEY_FEEDITEM, - PodDBAdapter.KEY_LINK, - PodDBAdapter.KEY_CHAPTER_TYPE)); - } - if (oldVersion <= 14) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ATTEMPTS + " INTEGER"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " SET " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ATTEMPTS + " = " - + "(SELECT " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ENABLED - + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS - + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + PodDBAdapter.KEY_ID - + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_FEED + ")"); - - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_HIDE + " TEXT"); - - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0"); - - // create indexes - db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED); - db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM); - db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM); - db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); - } - if (oldVersion <= 15) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " ADD COLUMN " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0" - + " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=0"); - Cursor c = db.rawQuery("SELECT " + PodDBAdapter.KEY_FILE_URL - + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=1 " - + " AND " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=-1", null); - if (c.moveToFirst()) { - MediaMetadataRetriever mmr = new MediaMetadataRetriever(); - do { - String fileUrl = c.getString(0); - try { - mmr.setDataSource(fileUrl); - byte[] image = mmr.getEmbeddedPicture(); - if (image != null) { - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=1" - + " WHERE " + PodDBAdapter.KEY_FILE_URL + "='" + fileUrl + "'"); - } else { - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0" - + " WHERE " + PodDBAdapter.KEY_FILE_URL + "='" + fileUrl + "'"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } while (c.moveToNext()); - } - c.close(); - } - if (oldVersion <= 16) { - String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID - + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON " - + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID + "=" - + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_FEEDITEM - + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON " - + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID + "=" - + PodDBAdapter.TABLE_NAME_QUEUE + "." + PodDBAdapter.KEY_FEEDITEM - + " WHERE " - + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ + " = 0 AND " // unplayed - + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOADED + " = 0 AND " // undownloaded - + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION + " = 0 AND " // not partially played - + PodDBAdapter.TABLE_NAME_QUEUE + "." + PodDBAdapter.KEY_ID + " IS NULL"; // not in queue - String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " SET " + PodDBAdapter.KEY_READ + "=" + FeedItem.NEW - + " WHERE " + PodDBAdapter.KEY_ID + " IN (" + selectNew + ")"; - Log.d("Migration", "SQL: " + sql); - db.execSQL(sql); - } - if (oldVersion <= 17) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); - } - if (oldVersion < 1030005) { - db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + - "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + - "AND id NOT IN (SELECT feeditem FROM Queue)"); - } - if (oldVersion < 1040001) { - db.execSQL(PodDBAdapter.CREATE_TABLE_FAVORITES); - } - if (oldVersion < 1040002) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA - + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0"); - } - if (oldVersion < 1040013) { - db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE); - db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_READ); - } - if (oldVersion < 1050003) { - // Migrates feed list filter data - - db.beginTransaction(); - - // Change to intermediate values to avoid overwriting in the following find/replace - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'unplayed', 'noplay')"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'not_queued', 'noqueue')"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'not_downloaded', 'nodl')"); - - // Replace played, queued, and downloaded with their opposites - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'played', 'unplayed')"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'queued', 'not_queued')"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'downloaded', 'not_downloaded')"); - - // Now replace intermediates for unplayed, not queued, etc. with their opposites - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'noplay', 'played')"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'noqueue', 'queued')"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'nodl', 'downloaded')"); - - // Paused doesn't have an opposite, so unplayed is the next best option - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" + - "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'paused', 'unplayed')"); - - db.setTransactionSuccessful(); - db.endTransaction(); - - // and now get ready for autodownload filters - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_INCLUDE_FILTER + " TEXT DEFAULT ''"); - - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_EXCLUDE_FILTER + " TEXT DEFAULT ''"); - - // and now auto refresh - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_KEEP_UPDATED + " INTEGER DEFAULT 1"); - } - if (oldVersion < 1050004) { - // prevent old timestamps to be misinterpreted as ETags - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS - + " SET " + PodDBAdapter.KEY_LASTUPDATE + "=NULL"); - } - if (oldVersion < 1060200) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_CUSTOM_TITLE + " TEXT"); - } - if (oldVersion < 1060596) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT"); - - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " SET " + PodDBAdapter.KEY_IMAGE_URL + " = (" - + " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL - + " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES - + " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID - + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + ".image)"); - - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + " SET " + PodDBAdapter.KEY_IMAGE_URL + " = (" - + " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL - + " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES - + " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID - + " = " + PodDBAdapter.TABLE_NAME_FEEDS + ".image)"); - - db.execSQL("DROP TABLE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES); - } - if (oldVersion < 1070400) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL); - } - if (oldVersion < 1070401) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_SORT_ORDER + " TEXT"); - } - if (oldVersion < 1090000) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS - + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT DEFAULT NULL"); - } - if (oldVersion < 1090001) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0;"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0;"); - } - if (oldVersion < 2020000) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0;"); - } - if (oldVersion < 2030000) { - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS - + " SET " + PodDBAdapter.KEY_DESCRIPTION + " = content_encoded, content_encoded = NULL " - + "WHERE length(" + PodDBAdapter.KEY_DESCRIPTION + ") < length(content_encoded)"); - db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " SET content_encoded = NULL"); - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_FEED_TAGS + " TEXT;"); - } - if (oldVersion < 2050000) { - db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS - + " ADD COLUMN " + PodDBAdapter.KEY_MINIMAL_DURATION_FILTER + " INTEGER DEFAULT -1"); - } - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index e572b4d8c..df4094590 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -9,6 +9,7 @@ import androidx.annotation.Nullable; import androidx.core.app.NotificationManagerCompat; import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.greenrobot.eventbus.EventBus; import java.io.File; @@ -34,7 +35,7 @@ import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.core.feed.FeedEvent; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink; import de.danoeh.antennapod.core.util.FeedItemPermutors; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java index a0fac0c74..812080368 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java @@ -8,6 +8,7 @@ import android.os.ParcelFileDescriptor; import android.text.format.Formatter; import android.util.Log; import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java b/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java index 1ec58216a..24b55f9f4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.core.storage; import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.core.util.LongIntMap; +import de.danoeh.antennapod.storage.database.LongIntMap; import java.util.ArrayList; import java.util.List; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java deleted file mode 100644 index ea4617f16..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ /dev/null @@ -1,1439 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.DatabaseErrorHandler; -import android.database.DatabaseUtils; -import android.database.DefaultDatabaseErrorHandler; -import android.database.SQLException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.database.sqlite.SQLiteOpenHelper; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; - -import de.danoeh.antennapod.model.feed.FeedFunding; -import de.danoeh.antennapod.core.storage.mapper.FeedItemFilterQuery; -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import de.danoeh.antennapod.model.feed.Chapter; -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.model.feed.FeedItemFilter; -import de.danoeh.antennapod.model.feed.FeedMedia; -import de.danoeh.antennapod.model.feed.FeedPreferences; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadStatus; -import de.danoeh.antennapod.core.util.LongIntMap; -import de.danoeh.antennapod.model.feed.SortOrder; - -import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL; -import static de.danoeh.antennapod.model.feed.SortOrder.toCodeString; - -/** - * Implements methods for accessing the database - */ -public class PodDBAdapter { - - private static final String TAG = "PodDBAdapter"; - public static final String DATABASE_NAME = "Antennapod.db"; - public static final int VERSION = 2050000; - - /** - * Maximum number of arguments for IN-operator. - */ - private static final int IN_OPERATOR_MAXIMUM = 800; - - // Key-constants - public static final String KEY_ID = "id"; - public static final String KEY_TITLE = "title"; - public static final String KEY_CUSTOM_TITLE = "custom_title"; - public static final String KEY_LINK = "link"; - public static final String KEY_DESCRIPTION = "description"; - public static final String KEY_FILE_URL = "file_url"; - public static final String KEY_DOWNLOAD_URL = "download_url"; - public static final String KEY_PUBDATE = "pubDate"; - public static final String KEY_READ = "read"; - public static final String KEY_DURATION = "duration"; - public static final String KEY_POSITION = "position"; - public static final String KEY_SIZE = "filesize"; - public static final String KEY_MIME_TYPE = "mime_type"; - public static final String KEY_IMAGE_URL = "image_url"; - public static final String KEY_FEED = "feed"; - public static final String KEY_MEDIA = "media"; - public static final String KEY_DOWNLOADED = "downloaded"; - public static final String KEY_LASTUPDATE = "last_update"; - public static final String KEY_FEEDFILE = "feedfile"; - public static final String KEY_REASON = "reason"; - public static final String KEY_SUCCESSFUL = "successful"; - public static final String KEY_FEEDFILETYPE = "feedfile_type"; - public static final String KEY_COMPLETION_DATE = "completion_date"; - public static final String KEY_FEEDITEM = "feeditem"; - public static final String KEY_PAYMENT_LINK = "payment_link"; - public static final String KEY_START = "start"; - public static final String KEY_LANGUAGE = "language"; - public static final String KEY_AUTHOR = "author"; - public static final String KEY_HAS_CHAPTERS = "has_simple_chapters"; - public static final String KEY_TYPE = "type"; - public static final String KEY_ITEM_IDENTIFIER = "item_identifier"; - public static final String KEY_FEED_IDENTIFIER = "feed_identifier"; - public static final String KEY_REASON_DETAILED = "reason_detailed"; - public static final String KEY_DOWNLOADSTATUS_TITLE = "title"; - public static final String KEY_CHAPTER_TYPE = "type"; - public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date"; - public static final String KEY_AUTO_DOWNLOAD_ATTEMPTS = "auto_download"; - public static final String KEY_AUTO_DOWNLOAD_ENABLED = "auto_download"; // Both tables use the same key - public static final String KEY_KEEP_UPDATED = "keep_updated"; - public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action"; - public static final String KEY_FEED_VOLUME_ADAPTION = "feed_volume_adaption"; - public static final String KEY_PLAYED_DURATION = "played_duration"; - public static final String KEY_USERNAME = "username"; - public static final String KEY_PASSWORD = "password"; - public static final String KEY_IS_PAGED = "is_paged"; - public static final String KEY_NEXT_PAGE_LINK = "next_page_link"; - public static final String KEY_HIDE = "hide"; - public static final String KEY_SORT_ORDER = "sort_order"; - public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed"; - public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture"; - public static final String KEY_LAST_PLAYED_TIME = "last_played_time"; - public static final String KEY_INCLUDE_FILTER = "include_filter"; - public static final String KEY_EXCLUDE_FILTER = "exclude_filter"; - public static final String KEY_MINIMAL_DURATION_FILTER = "minimal_duration_filter"; - public static final String KEY_FEED_PLAYBACK_SPEED = "feed_playback_speed"; - public static final String KEY_FEED_SKIP_INTRO = "feed_skip_intro"; - public static final String KEY_FEED_SKIP_ENDING = "feed_skip_ending"; - public static final String KEY_FEED_TAGS = "tags"; - public static final String KEY_EPISODE_NOTIFICATION = "episode_notification"; - - // Table names - public static final String TABLE_NAME_FEEDS = "Feeds"; - public static final String TABLE_NAME_FEED_ITEMS = "FeedItems"; - public static final String TABLE_NAME_FEED_IMAGES = "FeedImages"; - public static final String TABLE_NAME_FEED_MEDIA = "FeedMedia"; - public static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog"; - public static final String TABLE_NAME_QUEUE = "Queue"; - public static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters"; - public static final String TABLE_NAME_FAVORITES = "Favorites"; - - // SQL Statements for creating new tables - private static final String TABLE_PRIMARY_KEY = KEY_ID - + " INTEGER PRIMARY KEY AUTOINCREMENT ,"; - - private static final String CREATE_TABLE_FEEDS = "CREATE TABLE " - + TABLE_NAME_FEEDS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE - + " TEXT," + KEY_CUSTOM_TITLE + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT," - + KEY_DOWNLOADED + " INTEGER," + KEY_LINK + " TEXT," - + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT," - + KEY_LASTUPDATE + " TEXT," + KEY_LANGUAGE + " TEXT," + KEY_AUTHOR - + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_TYPE + " TEXT," - + KEY_FEED_IDENTIFIER + " TEXT," + KEY_AUTO_DOWNLOAD_ENABLED + " INTEGER DEFAULT 1," - + KEY_USERNAME + " TEXT," - + KEY_PASSWORD + " TEXT," - + KEY_INCLUDE_FILTER + " TEXT DEFAULT ''," - + KEY_EXCLUDE_FILTER + " TEXT DEFAULT ''," - + KEY_MINIMAL_DURATION_FILTER + " INTEGER DEFAULT -1," - + KEY_KEEP_UPDATED + " INTEGER DEFAULT 1," - + KEY_IS_PAGED + " INTEGER DEFAULT 0," - + KEY_NEXT_PAGE_LINK + " TEXT," - + KEY_HIDE + " TEXT," - + KEY_SORT_ORDER + " TEXT," - + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0," - + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0," - + KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + "," - + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0," - + KEY_FEED_TAGS + " TEXT," - + KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0," - + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0," - + KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0)"; - - private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE " - + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY - + KEY_TITLE + " TEXT," + KEY_PUBDATE + " INTEGER," - + KEY_READ + " INTEGER," + KEY_LINK + " TEXT," - + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT," - + KEY_MEDIA + " INTEGER," + KEY_FEED + " INTEGER," - + KEY_HAS_CHAPTERS + " INTEGER," + KEY_ITEM_IDENTIFIER + " TEXT," - + KEY_IMAGE_URL + " TEXT," - + KEY_AUTO_DOWNLOAD_ATTEMPTS + " INTEGER)"; - - private static final String CREATE_TABLE_FEED_MEDIA = "CREATE TABLE " - + TABLE_NAME_FEED_MEDIA + " (" + TABLE_PRIMARY_KEY + KEY_DURATION - + " INTEGER," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL - + " TEXT," + KEY_DOWNLOADED + " INTEGER," + KEY_POSITION - + " INTEGER," + KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT," - + KEY_PLAYBACK_COMPLETION_DATE + " INTEGER," - + KEY_FEEDITEM + " INTEGER," - + KEY_PLAYED_DURATION + " INTEGER," - + KEY_HAS_EMBEDDED_PICTURE + " INTEGER," - + KEY_LAST_PLAYED_TIME + " INTEGER" + ")"; - - private static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE " - + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE - + " INTEGER," + KEY_FEEDFILETYPE + " INTEGER," + KEY_REASON - + " INTEGER," + KEY_SUCCESSFUL + " INTEGER," + KEY_COMPLETION_DATE - + " INTEGER," + KEY_REASON_DETAILED + " TEXT," - + KEY_DOWNLOADSTATUS_TITLE + " TEXT)"; - - private static final String CREATE_TABLE_QUEUE = "CREATE TABLE " - + TABLE_NAME_QUEUE + "(" + KEY_ID + " INTEGER PRIMARY KEY," - + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)"; - - private static final String CREATE_TABLE_SIMPLECHAPTERS = "CREATE TABLE " - + TABLE_NAME_SIMPLECHAPTERS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE - + " TEXT," + KEY_START + " INTEGER," + KEY_FEEDITEM + " INTEGER," - + KEY_LINK + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)"; - - // SQL Statements for creating indexes - static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX " - + TABLE_NAME_FEED_ITEMS + "_" + KEY_FEED + " ON " + TABLE_NAME_FEED_ITEMS + " (" - + KEY_FEED + ")"; - - static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX " - + TABLE_NAME_FEED_ITEMS + "_" + KEY_PUBDATE + " ON " + TABLE_NAME_FEED_ITEMS + " (" - + KEY_PUBDATE + ")"; - - static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX " - + TABLE_NAME_FEED_ITEMS + "_" + KEY_READ + " ON " + TABLE_NAME_FEED_ITEMS + " (" - + KEY_READ + ")"; - - static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX " - + TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " (" - + KEY_FEEDITEM + ")"; - - static final String CREATE_INDEX_FEEDMEDIA_FEEDITEM = "CREATE INDEX " - + TABLE_NAME_FEED_MEDIA + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_FEED_MEDIA + " (" - + KEY_FEEDITEM + ")"; - - static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX " - + TABLE_NAME_SIMPLECHAPTERS + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_SIMPLECHAPTERS + " (" - + KEY_FEEDITEM + ")"; - - static final String CREATE_TABLE_FAVORITES = "CREATE TABLE " - + TABLE_NAME_FAVORITES + "(" + KEY_ID + " INTEGER PRIMARY KEY," - + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)"; - - /** - * Select all columns from the feed-table - */ - private static final String[] FEED_SEL_STD = { - TABLE_NAME_FEEDS + "." + KEY_ID, - TABLE_NAME_FEEDS + "." + KEY_TITLE, - TABLE_NAME_FEEDS + "." + KEY_CUSTOM_TITLE, - TABLE_NAME_FEEDS + "." + KEY_FILE_URL, - TABLE_NAME_FEEDS + "." + KEY_DOWNLOAD_URL, - TABLE_NAME_FEEDS + "." + KEY_DOWNLOADED, - TABLE_NAME_FEEDS + "." + KEY_LINK, - TABLE_NAME_FEEDS + "." + KEY_DESCRIPTION, - TABLE_NAME_FEEDS + "." + KEY_PAYMENT_LINK, - TABLE_NAME_FEEDS + "." + KEY_LASTUPDATE, - TABLE_NAME_FEEDS + "." + KEY_LANGUAGE, - TABLE_NAME_FEEDS + "." + KEY_AUTHOR, - TABLE_NAME_FEEDS + "." + KEY_IMAGE_URL, - TABLE_NAME_FEEDS + "." + KEY_TYPE, - TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER, - TABLE_NAME_FEEDS + "." + KEY_AUTO_DOWNLOAD_ENABLED, - TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED, - TABLE_NAME_FEEDS + "." + KEY_IS_PAGED, - TABLE_NAME_FEEDS + "." + KEY_NEXT_PAGE_LINK, - TABLE_NAME_FEEDS + "." + KEY_USERNAME, - TABLE_NAME_FEEDS + "." + KEY_PASSWORD, - TABLE_NAME_FEEDS + "." + KEY_HIDE, - TABLE_NAME_FEEDS + "." + KEY_SORT_ORDER, - TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED, - TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION, - TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_ADAPTION, - TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER, - TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER, - TABLE_NAME_FEEDS + "." + KEY_MINIMAL_DURATION_FILTER, - TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED, - TABLE_NAME_FEEDS + "." + KEY_FEED_TAGS, - TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO, - TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING, - TABLE_NAME_FEEDS + "." + KEY_EPISODE_NOTIFICATION - }; - - /** - * All the tables in the database - */ - private static final String[] ALL_TABLES = { - TABLE_NAME_FEEDS, - TABLE_NAME_FEED_ITEMS, - TABLE_NAME_FEED_MEDIA, - TABLE_NAME_DOWNLOAD_LOG, - TABLE_NAME_QUEUE, - TABLE_NAME_SIMPLECHAPTERS, - TABLE_NAME_FAVORITES - }; - - public static final String SELECT_KEY_ITEM_ID = "item_id"; - public static final String SELECT_KEY_MEDIA_ID = "media_id"; - - private static final String KEYS_FEED_ITEM_WITHOUT_DESCRIPTION = - TABLE_NAME_FEED_ITEMS + "." + KEY_ID + " AS " + SELECT_KEY_ITEM_ID + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_LINK + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_PAYMENT_LINK + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_MEDIA + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE_URL + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_AUTO_DOWNLOAD_ATTEMPTS; - - private static final String KEYS_FEED_MEDIA = - TABLE_NAME_FEED_MEDIA + "." + KEY_ID + " AS " + SELECT_KEY_MEDIA_ID + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_DURATION + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_FILE_URL + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOAD_URL + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_SIZE + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_MIME_TYPE + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYBACK_COMPLETION_DATE + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_HAS_EMBEDDED_PICTURE + ", " - + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME; - - private static final String JOIN_FEED_ITEM_AND_MEDIA = " LEFT JOIN " + TABLE_NAME_FEED_MEDIA - + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " "; - - private static final String SELECT_FEED_ITEMS_AND_MEDIA_WITH_DESCRIPTION = - "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA + ", " - + TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION - + " FROM " + TABLE_NAME_FEED_ITEMS - + JOIN_FEED_ITEM_AND_MEDIA; - private static final String SELECT_FEED_ITEMS_AND_MEDIA = - "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA - + " FROM " + TABLE_NAME_FEED_ITEMS - + JOIN_FEED_ITEM_AND_MEDIA; - - private static Context context; - private static PodDBAdapter instance; - - private final SQLiteDatabase db; - private final PodDBHelper dbHelper; - - public static void init(Context context) { - PodDBAdapter.context = context.getApplicationContext(); - } - - public static synchronized PodDBAdapter getInstance() { - if (instance == null) { - instance = new PodDBAdapter(); - } - return instance; - } - - private PodDBAdapter() { - dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null); - db = openDb(); - } - - private SQLiteDatabase openDb() { - SQLiteDatabase newDb; - try { - newDb = dbHelper.getWritableDatabase(); - newDb.disableWriteAheadLogging(); - } catch (SQLException ex) { - Log.e(TAG, Log.getStackTraceString(ex)); - newDb = dbHelper.getReadableDatabase(); - } - return newDb; - } - - public synchronized PodDBAdapter open() { - // do nothing - return this; - } - - public synchronized void close() { - // do nothing - } - - /** - * <p>Resets all database connections to ensure new database connections for - * the next test case. Call method only for unit tests.</p> - * - * <p>That's a workaround for a Robolectric issue in ShadowSQLiteConnection - * that leads to an error <tt>IllegalStateException: Illegal connection - * pointer</tt> if several threads try to use the same database connection. - * For more information see - * <a href="https://github.com/robolectric/robolectric/issues/1890">robolectric/robolectric#1890</a>.</p> - */ - @VisibleForTesting(otherwise = VisibleForTesting.NONE) - public static void tearDownTests() { - getInstance().dbHelper.close(); - instance = null; - } - - public static boolean deleteDatabase() { - PodDBAdapter adapter = getInstance(); - adapter.open(); - try { - for (String tableName : ALL_TABLES) { - adapter.db.delete(tableName, "1", null); - } - return true; - } finally { - adapter.close(); - } - } - - /** - * Inserts or updates a feed entry - * - * @return the id of the entry - */ - private long setFeed(Feed feed) { - ContentValues values = new ContentValues(); - values.put(KEY_TITLE, feed.getFeedTitle()); - values.put(KEY_LINK, feed.getLink()); - values.put(KEY_DESCRIPTION, feed.getDescription()); - values.put(KEY_PAYMENT_LINK, FeedFunding.getPaymentLinksAsString(feed.getPaymentLinks())); - values.put(KEY_AUTHOR, feed.getAuthor()); - values.put(KEY_LANGUAGE, feed.getLanguage()); - values.put(KEY_IMAGE_URL, feed.getImageUrl()); - - values.put(KEY_FILE_URL, feed.getFile_url()); - values.put(KEY_DOWNLOAD_URL, feed.getDownload_url()); - values.put(KEY_DOWNLOADED, feed.isDownloaded()); - values.put(KEY_LASTUPDATE, feed.getLastUpdate()); - values.put(KEY_TYPE, feed.getType()); - values.put(KEY_FEED_IDENTIFIER, feed.getFeedIdentifier()); - - values.put(KEY_IS_PAGED, feed.isPaged()); - values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink()); - if (feed.getItemFilter() != null && feed.getItemFilter().getValues().length > 0) { - values.put(KEY_HIDE, TextUtils.join(",", feed.getItemFilter().getValues())); - } else { - values.put(KEY_HIDE, ""); - } - values.put(KEY_SORT_ORDER, toCodeString(feed.getSortOrder())); - values.put(KEY_LAST_UPDATE_FAILED, feed.hasLastUpdateFailed()); - if (feed.getId() == 0) { - // Create new entry - Log.d(this.toString(), "Inserting new Feed into db"); - feed.setId(db.insert(TABLE_NAME_FEEDS, null, values)); - } else { - Log.d(this.toString(), "Updating existing Feed in db"); - db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", - new String[]{String.valueOf(feed.getId())}); - } - return feed.getId(); - } - - public void setFeedPreferences(FeedPreferences prefs) { - if (prefs.getFeedID() == 0) { - throw new IllegalArgumentException("Feed ID of preference must not be null"); - } - ContentValues values = new ContentValues(); - values.put(KEY_AUTO_DOWNLOAD_ENABLED, prefs.getAutoDownload()); - values.put(KEY_KEEP_UPDATED, prefs.getKeepUpdated()); - values.put(KEY_AUTO_DELETE_ACTION, prefs.getAutoDeleteAction().ordinal()); - values.put(KEY_FEED_VOLUME_ADAPTION, prefs.getVolumeAdaptionSetting().toInteger()); - values.put(KEY_USERNAME, prefs.getUsername()); - values.put(KEY_PASSWORD, prefs.getPassword()); - values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter()); - values.put(KEY_EXCLUDE_FILTER, prefs.getFilter().getExcludeFilter()); - values.put(KEY_MINIMAL_DURATION_FILTER, prefs.getFilter().getMinimalDurationFilter()); - values.put(KEY_FEED_PLAYBACK_SPEED, prefs.getFeedPlaybackSpeed()); - values.put(KEY_FEED_TAGS, prefs.getTagsAsString()); - values.put(KEY_FEED_SKIP_INTRO, prefs.getFeedSkipIntro()); - values.put(KEY_FEED_SKIP_ENDING, prefs.getFeedSkipEnding()); - values.put(KEY_EPISODE_NOTIFICATION, prefs.getShowEpisodeNotification()); - db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())}); - } - - public void setFeedItemFilter(long feedId, Set<String> filterValues) { - String valuesList = TextUtils.join(",", filterValues); - Log.d(TAG, String.format(Locale.US, - "setFeedItemFilter() called with: feedId = [%d], filterValues = [%s]", feedId, valuesList)); - ContentValues values = new ContentValues(); - values.put(KEY_HIDE, valuesList); - db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); - } - - public void setFeedItemSortOrder(long feedId, @Nullable SortOrder sortOrder) { - ContentValues values = new ContentValues(); - values.put(KEY_SORT_ORDER, toCodeString(sortOrder)); - db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); - } - - /** - * Inserts or updates a media entry - * - * @return the id of the entry - */ - public long setMedia(FeedMedia media) { - ContentValues values = new ContentValues(); - values.put(KEY_DURATION, media.getDuration()); - values.put(KEY_POSITION, media.getPosition()); - values.put(KEY_SIZE, media.getSize()); - values.put(KEY_MIME_TYPE, media.getMime_type()); - values.put(KEY_DOWNLOAD_URL, media.getDownload_url()); - values.put(KEY_DOWNLOADED, media.isDownloaded()); - values.put(KEY_FILE_URL, media.getFile_url()); - values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); - values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); - - if (media.getPlaybackCompletionDate() != null) { - values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); - } else { - values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); - } - if (media.getItem() != null) { - values.put(KEY_FEEDITEM, media.getItem().getId()); - } - if (media.getId() == 0) { - media.setId(db.insert(TABLE_NAME_FEED_MEDIA, null, values)); - } else { - db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", - new String[]{String.valueOf(media.getId())}); - } - return media.getId(); - } - - public void setFeedMediaPlaybackInformation(FeedMedia media) { - if (media.getId() != 0) { - ContentValues values = new ContentValues(); - values.put(KEY_POSITION, media.getPosition()); - values.put(KEY_DURATION, media.getDuration()); - values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); - values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); - db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", - new String[]{String.valueOf(media.getId())}); - } else { - Log.e(TAG, "setFeedMediaPlaybackInformation: ID of media was 0"); - } - } - - public void setFeedMediaPlaybackCompletionDate(FeedMedia media) { - if (media.getId() != 0) { - ContentValues values = new ContentValues(); - values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); - values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); - db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", - new String[]{String.valueOf(media.getId())}); - } else { - Log.e(TAG, "setFeedMediaPlaybackCompletionDate: ID of media was 0"); - } - } - - public void resetAllMediaPlayedDuration() { - try { - db.beginTransactionNonExclusive(); - ContentValues values = new ContentValues(); - values.put(KEY_PLAYED_DURATION, 0); - db.update(TABLE_NAME_FEED_MEDIA, values, null, new String[0]); - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - /** - * Insert all FeedItems of a feed and the feed object itself in a single - * transaction - */ - public void setCompleteFeed(Feed... feeds) { - try { - db.beginTransactionNonExclusive(); - for (Feed feed : feeds) { - setFeed(feed); - if (feed.getItems() != null) { - for (FeedItem item : feed.getItems()) { - updateOrInsertFeedItem(item, false); - } - } - if (feed.getPreferences() != null) { - setFeedPreferences(feed.getPreferences()); - } - } - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - /** - * Updates the download URL of a Feed. - */ - public void setFeedDownloadUrl(String original, String updated) { - ContentValues values = new ContentValues(); - values.put(KEY_DOWNLOAD_URL, updated); - db.update(TABLE_NAME_FEEDS, values, KEY_DOWNLOAD_URL + "=?", new String[]{original}); - } - - public void storeFeedItemlist(List<FeedItem> items) { - try { - db.beginTransactionNonExclusive(); - for (FeedItem item : items) { - updateOrInsertFeedItem(item, true); - } - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - public long setSingleFeedItem(FeedItem item) { - long result = 0; - try { - db.beginTransactionNonExclusive(); - result = updateOrInsertFeedItem(item, true); - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - return result; - } - - /** - * Inserts or updates a feeditem entry - * - * @param item The FeedItem - * @param saveFeed true if the Feed of the item should also be saved. This should be set to - * false if the method is executed on a list of FeedItems of the same Feed. - * @return the id of the entry - */ - private long updateOrInsertFeedItem(FeedItem item, boolean saveFeed) { - if (item.getId() == 0 && item.getPubDate() == null) { - Log.e(TAG, "Newly saved item has no pubDate. Using current date as pubDate"); - item.setPubDate(new Date()); - } - - ContentValues values = new ContentValues(); - values.put(KEY_TITLE, item.getTitle()); - values.put(KEY_LINK, item.getLink()); - if (item.getDescription() != null) { - values.put(KEY_DESCRIPTION, item.getDescription()); - } - values.put(KEY_PUBDATE, item.getPubDate().getTime()); - values.put(KEY_PAYMENT_LINK, item.getPaymentLink()); - if (saveFeed && item.getFeed() != null) { - setFeed(item.getFeed()); - } - values.put(KEY_FEED, item.getFeed().getId()); - if (item.isNew()) { - values.put(KEY_READ, FeedItem.NEW); - } else if (item.isPlayed()) { - values.put(KEY_READ, FeedItem.PLAYED); - } else { - values.put(KEY_READ, FeedItem.UNPLAYED); - } - values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters()); - values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier()); - values.put(KEY_AUTO_DOWNLOAD_ATTEMPTS, item.getAutoDownloadAttemptsAndTime()); - values.put(KEY_IMAGE_URL, item.getImageUrl()); - - if (item.getId() == 0) { - item.setId(db.insert(TABLE_NAME_FEED_ITEMS, null, values)); - } else { - db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", - new String[]{String.valueOf(item.getId())}); - } - if (item.getMedia() != null) { - setMedia(item.getMedia()); - } - if (item.getChapters() != null) { - setChapters(item); - } - return item.getId(); - } - - public void setFeedItemRead(int played, long itemId, long mediaId, - boolean resetMediaPosition) { - try { - db.beginTransactionNonExclusive(); - ContentValues values = new ContentValues(); - - values.put(KEY_READ, played); - db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)}); - - if (resetMediaPosition) { - values.clear(); - values.put(KEY_POSITION, 0); - db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", new String[]{String.valueOf(mediaId)}); - } - - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - /** - * Sets the 'read' attribute of the item. - * - * @param read must be one of FeedItem.PLAYED, FeedItem.NEW, FeedItem.UNPLAYED - * @param itemIds items to change the value of - */ - public void setFeedItemRead(int read, long... itemIds) { - try { - db.beginTransactionNonExclusive(); - ContentValues values = new ContentValues(); - for (long id : itemIds) { - values.clear(); - values.put(KEY_READ, read); - db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(id)}); - } - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - private void setChapters(FeedItem item) { - ContentValues values = new ContentValues(); - for (Chapter chapter : item.getChapters()) { - values.put(KEY_TITLE, chapter.getTitle()); - values.put(KEY_START, chapter.getStart()); - values.put(KEY_FEEDITEM, item.getId()); - values.put(KEY_LINK, chapter.getLink()); - values.put(KEY_IMAGE_URL, chapter.getImageUrl()); - values.put(KEY_CHAPTER_TYPE, chapter.getChapterType()); - if (chapter.getId() == 0) { - chapter.setId(db.insert(TABLE_NAME_SIMPLECHAPTERS, null, values)); - } else { - db.update(TABLE_NAME_SIMPLECHAPTERS, values, KEY_ID + "=?", - new String[]{String.valueOf(chapter.getId())}); - } - } - } - - public void setFeedLastUpdateFailed(long feedId, boolean failed) { - final String sql = "UPDATE " + TABLE_NAME_FEEDS - + " SET " + KEY_LAST_UPDATE_FAILED + "=" + (failed ? "1" : "0") - + " WHERE " + KEY_ID + "=" + feedId; - db.execSQL(sql); - } - - void setFeedCustomTitle(long feedId, String customTitle) { - ContentValues values = new ContentValues(); - values.put(KEY_CUSTOM_TITLE, customTitle); - db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); - } - - /** - * Inserts or updates a download status. - */ - public long setDownloadStatus(DownloadStatus status) { - ContentValues values = new ContentValues(); - values.put(KEY_FEEDFILE, status.getFeedfileId()); - values.put(KEY_FEEDFILETYPE, status.getFeedfileType()); - values.put(KEY_REASON, status.getReason().getCode()); - values.put(KEY_SUCCESSFUL, status.isSuccessful()); - values.put(KEY_COMPLETION_DATE, status.getCompletionDate().getTime()); - values.put(KEY_REASON_DETAILED, status.getReasonDetailed()); - values.put(KEY_DOWNLOADSTATUS_TITLE, status.getTitle()); - if (status.getId() == 0) { - status.setId(db.insert(TABLE_NAME_DOWNLOAD_LOG, null, values)); - } else { - db.update(TABLE_NAME_DOWNLOAD_LOG, values, KEY_ID + "=?", - new String[]{String.valueOf(status.getId())}); - } - return status.getId(); - } - - public void setFavorites(List<FeedItem> favorites) { - ContentValues values = new ContentValues(); - try { - db.beginTransactionNonExclusive(); - db.delete(TABLE_NAME_FAVORITES, null, null); - for (int i = 0; i < favorites.size(); i++) { - FeedItem item = favorites.get(i); - values.put(KEY_ID, i); - values.put(KEY_FEEDITEM, item.getId()); - values.put(KEY_FEED, item.getFeed().getId()); - db.insertWithOnConflict(TABLE_NAME_FAVORITES, null, values, SQLiteDatabase.CONFLICT_REPLACE); - } - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - /** - * Adds the item to favorites - */ - public void addFavoriteItem(FeedItem item) { - // don't add an item that's already there... - if (isItemInFavorites(item)) { - Log.d(TAG, "item already in favorites"); - return; - } - ContentValues values = new ContentValues(); - values.put(KEY_FEEDITEM, item.getId()); - values.put(KEY_FEED, item.getFeedId()); - db.insert(TABLE_NAME_FAVORITES, null, values); - } - - public void removeFavoriteItem(FeedItem item) { - String deleteClause = String.format("DELETE FROM %s WHERE %s=%s AND %s=%s", - TABLE_NAME_FAVORITES, - KEY_FEEDITEM, item.getId(), - KEY_FEED, item.getFeedId()); - db.execSQL(deleteClause); - } - - private boolean isItemInFavorites(FeedItem item) { - String query = String.format(Locale.US, "SELECT %s from %s WHERE %s=%d", - KEY_ID, TABLE_NAME_FAVORITES, KEY_FEEDITEM, item.getId()); - Cursor c = db.rawQuery(query, null); - int count = c.getCount(); - c.close(); - return count > 0; - } - - public void setQueue(List<FeedItem> queue) { - ContentValues values = new ContentValues(); - try { - db.beginTransactionNonExclusive(); - db.delete(TABLE_NAME_QUEUE, null, null); - for (int i = 0; i < queue.size(); i++) { - FeedItem item = queue.get(i); - values.put(KEY_ID, i); - values.put(KEY_FEEDITEM, item.getId()); - values.put(KEY_FEED, item.getFeed().getId()); - db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, SQLiteDatabase.CONFLICT_REPLACE); - } - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - public void clearQueue() { - db.delete(TABLE_NAME_QUEUE, null, null); - } - - /** - * Remove the listed items and their FeedMedia entries. - */ - public void removeFeedItems(@NonNull List<FeedItem> items) { - try { - StringBuilder mediaIds = new StringBuilder(); - StringBuilder itemIds = new StringBuilder(); - for (FeedItem item : items) { - if (item.getMedia() != null) { - if (mediaIds.length() != 0) { - mediaIds.append(","); - } - mediaIds.append(item.getMedia().getId()); - } - if (itemIds.length() != 0) { - itemIds.append(","); - } - itemIds.append(item.getId()); - } - - db.beginTransactionNonExclusive(); - db.delete(TABLE_NAME_SIMPLECHAPTERS, KEY_FEEDITEM + " IN (" + itemIds + ")", null); - db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILETYPE + "=" + FeedMedia.FEEDFILETYPE_FEEDMEDIA - + " AND " + KEY_FEEDFILE + " IN (" + mediaIds + ")", null); - db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + " IN (" + mediaIds + ")", null); - db.delete(TABLE_NAME_FEED_ITEMS, KEY_ID + " IN (" + itemIds + ")", null); - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - /** - * Remove a feed with all its FeedItems and Media entries. - */ - public void removeFeed(Feed feed) { - try { - db.beginTransactionNonExclusive(); - if (feed.getItems() != null) { - removeFeedItems(feed.getItems()); - } - // delete download log entries for feed - db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE + "=?", - new String[]{String.valueOf(feed.getId()), String.valueOf(Feed.FEEDFILETYPE_FEED)}); - - db.delete(TABLE_NAME_FEEDS, KEY_ID + "=?", - new String[]{String.valueOf(feed.getId())}); - db.setTransactionSuccessful(); - } catch (SQLException e) { - Log.e(TAG, Log.getStackTraceString(e)); - } finally { - db.endTransaction(); - } - } - - public void clearPlaybackHistory() { - ContentValues values = new ContentValues(); - values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); - db.update(TABLE_NAME_FEED_MEDIA, values, null, null); - } - - public void clearDownloadLog() { - db.delete(TABLE_NAME_DOWNLOAD_LOG, null, null); - } - - /** - * Get all Feeds from the Feed Table. - * - * @return The cursor of the query - */ - public final Cursor getAllFeedsCursor() { - return db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, null, null, null, null, - KEY_TITLE + " COLLATE NOCASE ASC"); - } - - public final Cursor getFeedCursorDownloadUrls() { - return db.query(TABLE_NAME_FEEDS, new String[]{KEY_ID, KEY_DOWNLOAD_URL}, null, null, null, null, null); - } - - /** - * Returns a cursor with all FeedItems of a Feed. Uses FEEDITEM_SEL_FI_SMALL - * - * @param feed The feed you want to get the FeedItems from. - * @return The cursor of the query - */ - public final Cursor getItemsOfFeedCursor(final Feed feed, FeedItemFilter filter) { - String filterQuery = FeedItemFilterQuery.generateFrom(filter); - String whereClauseAnd = "".equals(filterQuery) ? "" : " AND " + filterQuery; - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + feed.getId() - + whereClauseAnd; - return db.rawQuery(query, null); - } - - /** - * Return the description and content_encoded of item - */ - public final Cursor getDescriptionOfItem(final FeedItem item) { - final String query = "SELECT " + KEY_DESCRIPTION - + " FROM " + TABLE_NAME_FEED_ITEMS - + " WHERE " + KEY_ID + "=" + item.getId(); - return db.rawQuery(query, null); - } - - public final Cursor getSimpleChaptersOfFeedItemCursor(final FeedItem item) { - return db.query(TABLE_NAME_SIMPLECHAPTERS, null, KEY_FEEDITEM - + "=?", new String[]{String.valueOf(item.getId())}, null, - null, null - ); - } - - public final Cursor getDownloadLog(final int feedFileType, final long feedFileId) { - final String query = "SELECT * FROM " + TABLE_NAME_DOWNLOAD_LOG + - " WHERE " + KEY_FEEDFILE + "=" + feedFileId + " AND " + KEY_FEEDFILETYPE + "=" + feedFileType - + " ORDER BY " + KEY_ID + " DESC"; - return db.rawQuery(query, null); - } - - public final Cursor getDownloadLogCursor(final int limit) { - return db.query(TABLE_NAME_DOWNLOAD_LOG, null, null, null, null, - null, KEY_COMPLETION_DATE + " DESC LIMIT " + limit); - } - - /** - * Returns a cursor which contains all feed items in the queue. The returned - * cursor uses the FEEDITEM_SEL_FI_SMALL selection. - * cursor uses the FEEDITEM_SEL_FI_SMALL selection. - */ - public final Cursor getQueueCursor() { - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + " INNER JOIN " + TABLE_NAME_QUEUE - + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " ORDER BY " + TABLE_NAME_QUEUE + "." + KEY_ID; - return db.rawQuery(query, null); - } - - public Cursor getQueueIDCursor() { - return db.query(TABLE_NAME_QUEUE, new String[]{KEY_FEEDITEM}, null, null, null, null, KEY_ID + " ASC", null); - } - - public Cursor getNextInQueue(final FeedItem item) { - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + "INNER JOIN " + TABLE_NAME_QUEUE - + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE Queue.ID > (SELECT Queue.ID FROM Queue WHERE Queue.FeedItem = " - + item.getId() - + ")" - + " ORDER BY Queue.ID" - + " LIMIT 1"; - return db.rawQuery(query, null); - } - - public final Cursor getFavoritesCursor(int offset, int limit) { - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + " INNER JOIN " + TABLE_NAME_FAVORITES - + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_FAVORITES + "." + KEY_FEEDITEM - + " ORDER BY " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC" - + " LIMIT " + offset + ", " + limit; - return db.rawQuery(query, null); - } - - public void setFeedItems(int state) { - setFeedItems(Integer.MIN_VALUE, state, 0); - } - - public void setFeedItems(int oldState, int newState) { - setFeedItems(oldState, newState, 0); - } - - public void setFeedItems(int state, long feedId) { - setFeedItems(Integer.MIN_VALUE, state, feedId); - } - - public void setFeedItems(int oldState, int newState, long feedId) { - String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS + " SET " + KEY_READ + "=" + newState; - if (feedId > 0) { - sql += " WHERE " + KEY_FEED + "=" + feedId; - } - if (FeedItem.NEW <= oldState && oldState <= FeedItem.PLAYED) { - sql += feedId > 0 ? " AND " : " WHERE "; - sql += KEY_READ + "=" + oldState; - } - db.execSQL(sql); - } - - /** - * Returns a cursor which contains all feed items that are considered new. - * Excludes those feeds that do not have 'Keep Updated' enabled. - * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. - */ - public final Cursor getNewItemsCursor(int offset, int limit) { - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + " INNER JOIN " + TABLE_NAME_FEEDS - + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID - + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.NEW - + " AND " + TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED + " > 0" - + " ORDER BY " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC" - + " LIMIT " + offset + ", " + limit; - return db.rawQuery(query, null); - } - - public final Cursor getRecentlyPublishedItemsCursor(int offset, int limit, FeedItemFilter filter) { - String filterQuery = FeedItemFilterQuery.generateFrom(filter); - String whereClause = "".equals(filterQuery) ? "" : " WHERE " + filterQuery; - final String query = SELECT_FEED_ITEMS_AND_MEDIA + whereClause - + " ORDER BY " + KEY_PUBDATE + " DESC LIMIT " + offset + ", " + limit; - return db.rawQuery(query, null); - } - - public Cursor getDownloadedItemsCursor() { - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + "WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " > 0"; - return db.rawQuery(query, null); - } - - public Cursor getPlayedItemsCursor() { - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + "WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.PLAYED; - return db.rawQuery(query, null); - } - - /** - * Returns a cursor which contains feed media objects with a playback - * completion date in ascending order. - * - * @param limit The maximum row count of the returned cursor. Must be an - * integer >= 0. - * @throws IllegalArgumentException if limit < 0 - */ - public final Cursor getCompletedMediaCursor(int limit) { - if (limit < 0) { - throw new IllegalArgumentException("Limit must be >= 0"); - } - - return db.query(TABLE_NAME_FEED_MEDIA, null, - KEY_PLAYBACK_COMPLETION_DATE + " > 0", null, null, - null, String.format(Locale.US, "%s DESC LIMIT %d", KEY_PLAYBACK_COMPLETION_DATE, limit)); - } - - public final Cursor getSingleFeedMediaCursor(long id) { - final String query = "SELECT " + KEYS_FEED_MEDIA + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_ID + "=" + id; - return db.rawQuery(query, null); - } - - public final Cursor getFeedCursor(final long id) { - return db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_ID + "=" + id, null, - null, null, null); - } - - public final Cursor getFeedItemCursor(final String id) { - return getFeedItemCursor(new String[]{id}); - } - - public final Cursor getFeedItemCursor(final String[] ids) { - if (ids.length > IN_OPERATOR_MAXIMUM) { - throw new IllegalArgumentException("number of IDs must not be larger than " + IN_OPERATOR_MAXIMUM); - } - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + " WHERE " + SELECT_KEY_ITEM_ID + " IN (" + TextUtils.join(",", ids) + ")"; - return db.rawQuery(query, null); - } - - public final Cursor getFeedItemCursor(final String guid, final String episodeUrl) { - String escapedEpisodeUrl = DatabaseUtils.sqlEscapeString(episodeUrl); - String whereClauseCondition = TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOAD_URL + "=" + escapedEpisodeUrl; - - if (guid != null) { - String escapedGuid = DatabaseUtils.sqlEscapeString(guid); - whereClauseCondition = TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER + "=" + escapedGuid; - } - - final String query = SELECT_FEED_ITEMS_AND_MEDIA - + " INNER JOIN " + TABLE_NAME_FEEDS - + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID - + " WHERE " + whereClauseCondition; - return db.rawQuery(query, null); - } - - public Cursor getImageAuthenticationCursor(final String imageUrl) { - String downloadUrl = DatabaseUtils.sqlEscapeString(imageUrl); - final String query = "" - + "SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEEDS - + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + " = " + TABLE_NAME_FEEDS + "." + KEY_ID - + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE_URL + "=" + downloadUrl - + " UNION SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEEDS - + " WHERE " + TABLE_NAME_FEEDS + "." + KEY_IMAGE_URL + "=" + downloadUrl; - return db.rawQuery(query, null); - } - - public final Cursor getMonthlyStatisticsCursor() { - final String query = "SELECT SUM(" + KEY_PLAYED_DURATION + ") AS total_duration" - + ", strftime('%m', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS month" - + ", strftime('%Y', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS year" - + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_LAST_PLAYED_TIME + " > 0 AND " + KEY_PLAYED_DURATION + " > 0" - + " GROUP BY year, month" - + " ORDER BY year, month"; - return db.rawQuery(query, null); - } - - public int getQueueSize() { - final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_QUEUE); - Cursor c = db.rawQuery(query, null); - int result = 0; - if (c.moveToFirst()) { - result = c.getInt(0); - } - c.close(); - return result; - } - - public final int getNumberOfNewItems() { - Object[] args = new String[]{ - TABLE_NAME_FEED_ITEMS + "." + KEY_ID, - TABLE_NAME_FEED_ITEMS, - TABLE_NAME_FEEDS, - TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID, - TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.NEW - + " AND " + TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED + " > 0" - }; - final String query = String.format("SELECT COUNT(%s) FROM %s INNER JOIN %s ON %s WHERE %s", args); - Cursor c = db.rawQuery(query, null); - int result = 0; - if (c.moveToFirst()) { - result = c.getInt(0); - } - c.close(); - return result; - } - - public final LongIntMap getFeedCounters(long... feedIds) { - int setting = UserPreferences.getFeedCounterSetting(); - - return getFeedCounters(setting, feedIds); - } - - public final LongIntMap getFeedCounters(int setting, long... feedIds) { - String whereRead; - switch (setting) { - case UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM: - whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + - " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; - break; - case UserPreferences.FEED_COUNTER_SHOW_NEW: - whereRead = KEY_READ + "=" + FeedItem.NEW; - break; - case UserPreferences.FEED_COUNTER_SHOW_UNPLAYED: - whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; - break; - case UserPreferences.FEED_COUNTER_SHOW_DOWNLOADED: - whereRead = KEY_DOWNLOADED + "=1"; - break; - case UserPreferences.FEED_COUNTER_SHOW_NONE: - // deliberate fall-through - default: // NONE - return new LongIntMap(0); - } - return conditionalFeedCounterRead(whereRead, feedIds); - } - - private LongIntMap conditionalFeedCounterRead(String whereRead, long... feedIds) { - String limitFeeds = ""; - if (feedIds.length > 0) { - // work around TextUtils.join wanting only boxed items - // and StringUtils.join() causing NoSuchMethodErrors on MIUI - StringBuilder builder = new StringBuilder(); - for (long id : feedIds) { - builder.append(id); - builder.append(','); - } - // there's an extra ',', get rid of it - builder.deleteCharAt(builder.length() - 1); - limitFeeds = KEY_FEED + " IN (" + builder.toString() + ") AND "; - } - - final String query = "SELECT " + KEY_FEED + ", COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ") AS count " - + " FROM " + TABLE_NAME_FEED_ITEMS - + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " WHERE " + limitFeeds + " " - + whereRead + " GROUP BY " + KEY_FEED; - - Cursor c = db.rawQuery(query, null); - LongIntMap result = new LongIntMap(c.getCount()); - if (c.moveToFirst()) { - do { - long feedId = c.getLong(0); - int count = c.getInt(1); - result.put(feedId, count); - } while (c.moveToNext()); - } - c.close(); - return result; - } - - public final LongIntMap getPlayedEpisodesCounters(long... feedIds) { - String whereRead = KEY_READ + "=" + FeedItem.PLAYED; - return conditionalFeedCounterRead(whereRead, feedIds); - } - - public final Map<Long, Long> getMostRecentItemDates() { - final String query = "SELECT " + KEY_FEED + "," - + " MAX(" + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + ") AS most_recent_pubdate" - + " FROM " + TABLE_NAME_FEED_ITEMS - + " GROUP BY " + KEY_FEED; - - Cursor c = db.rawQuery(query, null); - Map<Long, Long> result = new HashMap<>(); - if (c.moveToFirst()) { - do { - long feedId = c.getLong(0); - long date = c.getLong(1); - result.put(feedId, date); - } while (c.moveToNext()); - } - c.close(); - return result; - } - - public final int getNumberOfDownloadedEpisodes() { - final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_MEDIA + - " WHERE " + KEY_DOWNLOADED + " > 0"; - - Cursor c = db.rawQuery(query, null); - int result = 0; - if (c.moveToFirst()) { - result = c.getInt(0); - } - c.close(); - return result; - } - - /** - * Uses DatabaseUtils to escape a search query and removes ' at the - * beginning and the end of the string returned by the escape method. - */ - private String[] prepareSearchQuery(String query) { - String[] queryWords = query.split("\\s+"); - for (int i = 0; i < queryWords.length; ++i) { - StringBuilder builder = new StringBuilder(); - DatabaseUtils.appendEscapedSQLString(builder, queryWords[i]); - builder.deleteCharAt(0); - builder.deleteCharAt(builder.length() - 1); - queryWords[i] = builder.toString(); - } - - return queryWords; - } - - /** - * Searches for the given query in various values of all items or the items - * of a specified feed. - * - * @return A cursor with all search results in SEL_FI_EXTRA selection. - */ - public Cursor searchItems(long feedID, String searchQuery) { - String[] queryWords = prepareSearchQuery(searchQuery); - - String queryFeedId; - if (feedID != 0) { - // search items in specific feed - queryFeedId = KEY_FEED + " = " + feedID; - } else { - // search through all items - queryFeedId = "1 = 1"; - } - - String queryStart = SELECT_FEED_ITEMS_AND_MEDIA_WITH_DESCRIPTION - + " WHERE " + queryFeedId + " AND ("; - StringBuilder sb = new StringBuilder(queryStart); - - for (int i = 0; i < queryWords.length; i++) { - sb - .append("(") - .append(KEY_DESCRIPTION + " LIKE '%").append(queryWords[i]) - .append("%' OR ") - .append(KEY_TITLE).append(" LIKE '%").append(queryWords[i]) - .append("%') "); - - if (i != queryWords.length - 1) { - sb.append("AND "); - } - } - - sb.append(") ORDER BY " + KEY_PUBDATE + " DESC LIMIT 300"); - - return db.rawQuery(sb.toString(), null); - } - - /** - * Searches for the given query in various values of all feeds. - * - * @return A cursor with all search results in SEL_FI_EXTRA selection. - */ - public Cursor searchFeeds(String searchQuery) { - String[] queryWords = prepareSearchQuery(searchQuery); - - String queryStart = "SELECT * FROM " + TABLE_NAME_FEEDS + " WHERE "; - StringBuilder sb = new StringBuilder(queryStart); - - for (int i = 0; i < queryWords.length; i++) { - sb - .append("(") - .append(KEY_TITLE).append(" LIKE '%").append(queryWords[i]) - .append("%' OR ") - .append(KEY_CUSTOM_TITLE).append(" LIKE '%").append(queryWords[i]) - .append("%' OR ") - .append(KEY_AUTHOR).append(" LIKE '%").append(queryWords[i]) - .append("%' OR ") - .append(KEY_DESCRIPTION).append(" LIKE '%").append(queryWords[i]) - .append("%') "); - - if (i != queryWords.length - 1) { - sb.append("AND "); - } - } - - sb.append("ORDER BY " + KEY_TITLE + " ASC LIMIT 300"); - - return db.rawQuery(sb.toString(), null); - } - - /** - * Insert raw data to the database. - * Call method only for unit tests. - */ - @VisibleForTesting(otherwise = VisibleForTesting.NONE) - public void insertTestData(@NonNull String table, @NonNull ContentValues values) { - db.insert(table, null, values); - } - - /** - * Called when a database corruption happens. - */ - public static class PodDbErrorHandler implements DatabaseErrorHandler { - @Override - public void onCorruption(SQLiteDatabase db) { - Log.e(TAG, "Database corrupted: " + db.getPath()); - - File dbPath = new File(db.getPath()); - File backupFolder = PodDBAdapter.context.getExternalFilesDir(null); - File backupFile = new File(backupFolder, "CorruptedDatabaseBackup.db"); - try { - FileUtils.copyFile(dbPath, backupFile); - Log.d(TAG, "Dumped database to " + backupFile.getPath()); - } catch (IOException e) { - Log.d(TAG, Log.getStackTraceString(e)); - } - - new DefaultDatabaseErrorHandler().onCorruption(db); // This deletes the database - } - } - - /** - * Helper class for opening the Antennapod database. - */ - private static class PodDBHelper extends SQLiteOpenHelper { - /** - * Constructor. - * - * @param context Context to use - * @param name Name of the database - * @param factory to use for creating cursor objects - */ - public PodDBHelper(final Context context, final String name, final CursorFactory factory) { - super(context, name, factory, VERSION, new PodDbErrorHandler()); - } - - @Override - public void onCreate(final SQLiteDatabase db) { - db.execSQL(CREATE_TABLE_FEEDS); - db.execSQL(CREATE_TABLE_FEED_ITEMS); - db.execSQL(CREATE_TABLE_FEED_MEDIA); - db.execSQL(CREATE_TABLE_DOWNLOAD_LOG); - db.execSQL(CREATE_TABLE_QUEUE); - db.execSQL(CREATE_TABLE_SIMPLECHAPTERS); - db.execSQL(CREATE_TABLE_FAVORITES); - - db.execSQL(CREATE_INDEX_FEEDITEMS_FEED); - db.execSQL(CREATE_INDEX_FEEDITEMS_PUBDATE); - db.execSQL(CREATE_INDEX_FEEDITEMS_READ); - db.execSQL(CREATE_INDEX_FEEDMEDIA_FEEDITEM); - db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM); - db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); - } - - @Override - public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { - Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + "."); - DBUpgrader.upgrade(db, oldVersion, newVersion); - } - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java deleted file mode 100644 index 5fa376129..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import android.database.Cursor; -import androidx.annotation.NonNull; -import de.danoeh.antennapod.model.feed.Chapter; -import de.danoeh.antennapod.parser.feed.element.SimpleChapter; -import de.danoeh.antennapod.core.storage.PodDBAdapter; -import de.danoeh.antennapod.parser.media.id3.ID3Chapter; -import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentChapter; - -/** - * Converts a {@link Cursor} to a {@link Chapter} object. - */ -public abstract class ChapterCursorMapper { - /** - * Create a {@link Chapter} instance from a database row (cursor). - */ - @NonNull - public static Chapter convert(@NonNull Cursor cursor) { - int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); - int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); - int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START); - int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); - int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL); - int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); - - long id = cursor.getLong(indexId); - String title = cursor.getString(indexTitle); - long start = cursor.getLong(indexStart); - String link = cursor.getString(indexLink); - String imageUrl = cursor.getString(indexImage); - int chapterType = cursor.getInt(indexChapterType); - - Chapter chapter; - switch (chapterType) { - case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: - chapter = new SimpleChapter(start, title, link, imageUrl); - break; - case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: - chapter = new ID3Chapter(start, title, link, imageUrl); - break; - case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: - chapter = new VorbisCommentChapter(start, title, link, imageUrl); - break; - default: - throw new IllegalArgumentException("Unknown chapter type"); - } - chapter.setId(id); - return chapter; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java deleted file mode 100644 index f8b57b819..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import android.database.Cursor; -import androidx.annotation.NonNull; -import de.danoeh.antennapod.core.service.download.DownloadStatus; -import de.danoeh.antennapod.core.storage.PodDBAdapter; -import de.danoeh.antennapod.core.util.DownloadError; - -import java.util.Date; - -/** - * Converts a {@link Cursor} to a {@link DownloadStatus} object. - */ -public abstract class DownloadStatusCursorMapper { - /** - * Create a {@link DownloadStatus} instance from a database row (cursor). - */ - @NonNull - public static DownloadStatus convert(@NonNull Cursor cursor) { - int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); - int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE); - int indexFeedFile = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDFILE); - int indexFileFileType = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDFILETYPE); - int indexSuccessful = cursor.getColumnIndex(PodDBAdapter.KEY_SUCCESSFUL); - int indexReason = cursor.getColumnIndex(PodDBAdapter.KEY_REASON); - int indexCompletionDate = cursor.getColumnIndex(PodDBAdapter.KEY_COMPLETION_DATE); - int indexReasonDetailed = cursor.getColumnIndex(PodDBAdapter.KEY_REASON_DETAILED); - - return new DownloadStatus(cursor.getLong(indexId), cursor.getString(indexTitle), cursor.getLong(indexFeedFile), - cursor.getInt(indexFileFileType), cursor.getInt(indexSuccessful) > 0, false, true, - DownloadError.fromCode(cursor.getInt(indexReason)), - new Date(cursor.getLong(indexCompletionDate)), - cursor.getString(indexReasonDetailed), false); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java deleted file mode 100644 index a2a180735..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java +++ /dev/null @@ -1,70 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import android.database.Cursor; - -import androidx.annotation.NonNull; - -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedPreferences; -import de.danoeh.antennapod.core.storage.PodDBAdapter; -import de.danoeh.antennapod.model.feed.SortOrder; - -/** - * Converts a {@link Cursor} to a {@link Feed} object. - */ -public abstract class FeedCursorMapper { - - /** - * Create a {@link Feed} instance from a database row (cursor). - */ - @NonNull - public static Feed convert(@NonNull Cursor cursor) { - int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); - int indexLastUpdate = cursor.getColumnIndex(PodDBAdapter.KEY_LASTUPDATE); - int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); - int indexCustomTitle = cursor.getColumnIndex(PodDBAdapter.KEY_CUSTOM_TITLE); - int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); - int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); - int indexPaymentLink = cursor.getColumnIndex(PodDBAdapter.KEY_PAYMENT_LINK); - int indexAuthor = cursor.getColumnIndex(PodDBAdapter.KEY_AUTHOR); - int indexLanguage = cursor.getColumnIndex(PodDBAdapter.KEY_LANGUAGE); - int indexType = cursor.getColumnIndex(PodDBAdapter.KEY_TYPE); - int indexFeedIdentifier = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_IDENTIFIER); - int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL); - int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL); - int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED); - int indexIsPaged = cursor.getColumnIndex(PodDBAdapter.KEY_IS_PAGED); - int indexNextPageLink = cursor.getColumnIndex(PodDBAdapter.KEY_NEXT_PAGE_LINK); - int indexHide = cursor.getColumnIndex(PodDBAdapter.KEY_HIDE); - int indexSortOrder = cursor.getColumnIndex(PodDBAdapter.KEY_SORT_ORDER); - int indexLastUpdateFailed = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_UPDATE_FAILED); - int indexImageUrl = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL); - - Feed feed = new Feed( - cursor.getLong(indexId), - cursor.getString(indexLastUpdate), - cursor.getString(indexTitle), - cursor.getString(indexCustomTitle), - cursor.getString(indexLink), - cursor.getString(indexDescription), - cursor.getString(indexPaymentLink), - cursor.getString(indexAuthor), - cursor.getString(indexLanguage), - cursor.getString(indexType), - cursor.getString(indexFeedIdentifier), - cursor.getString(indexImageUrl), - cursor.getString(indexFileUrl), - cursor.getString(indexDownloadUrl), - cursor.getInt(indexDownloaded) > 0, - cursor.getInt(indexIsPaged) > 0, - cursor.getString(indexNextPageLink), - cursor.getString(indexHide), - SortOrder.fromCodeString(cursor.getString(indexSortOrder)), - cursor.getInt(indexLastUpdateFailed) > 0 - ); - - FeedPreferences preferences = FeedPreferencesCursorMapper.convert(cursor); - feed.setPreferences(preferences); - return feed; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java deleted file mode 100644 index ca0834339..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import android.database.Cursor; -import androidx.annotation.NonNull; -import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.core.storage.PodDBAdapter; - -import java.util.Date; - -/** - * Converts a {@link Cursor} to a {@link FeedItem} object. - */ -public abstract class FeedItemCursorMapper { - /** - * Create a {@link FeedItem} instance from a database row (cursor). - */ - @NonNull - public static FeedItem convert(@NonNull Cursor cursor) { - int indexId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_ITEM_ID); - int indexTitle = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_TITLE); - int indexLink = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LINK); - int indexPubDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PUBDATE); - int indexPaymentLink = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PAYMENT_LINK); - int indexFeedId = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FEED); - int indexHasChapters = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_HAS_CHAPTERS); - int indexRead = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_READ); - int indexItemIdentifier = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_ITEM_IDENTIFIER); - int indexAutoDownload = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_AUTO_DOWNLOAD_ATTEMPTS); - int indexImageUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_IMAGE_URL); - - long id = cursor.getInt(indexId); - String title = cursor.getString(indexTitle); - String link = cursor.getString(indexLink); - Date pubDate = new Date(cursor.getLong(indexPubDate)); - String paymentLink = cursor.getString(indexPaymentLink); - long feedId = cursor.getLong(indexFeedId); - boolean hasChapters = cursor.getInt(indexHasChapters) > 0; - int state = cursor.getInt(indexRead); - String itemIdentifier = cursor.getString(indexItemIdentifier); - long autoDownload = cursor.getLong(indexAutoDownload); - String imageUrl = cursor.getString(indexImageUrl); - - return new FeedItem(id, title, link, pubDate, paymentLink, feedId, - hasChapters, imageUrl, state, itemIdentifier, autoDownload); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java deleted file mode 100644 index 1d9c8a9e6..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java +++ /dev/null @@ -1,76 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import de.danoeh.antennapod.model.feed.FeedItemFilter; -import de.danoeh.antennapod.core.storage.PodDBAdapter; - -import java.util.ArrayList; -import java.util.List; - -public class FeedItemFilterQuery { - private FeedItemFilterQuery() { - // Must not be instantiated - } - - /** - * Express the filter using an SQL boolean statement that can be inserted into an SQL WHERE clause - * to yield output filtered according to the rules of this filter. - * - * @return An SQL boolean statement that matches the desired items, - * empty string if there is nothing to filter - */ - public static String generateFrom(FeedItemFilter filter) { - // The keys used within this method, but explicitly combined with their table - String keyRead = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ; - String keyPosition = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION; - String keyDownloaded = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOADED; - String keyMediaId = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_ID; - String keyItemId = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID; - String keyFeedItem = PodDBAdapter.KEY_FEEDITEM; - String tableQueue = PodDBAdapter.TABLE_NAME_QUEUE; - String tableFavorites = PodDBAdapter.TABLE_NAME_FAVORITES; - - List<String> statements = new ArrayList<>(); - if (filter.showPlayed) { - statements.add(keyRead + " = 1 "); - } else if (filter.showUnplayed) { - statements.add(" NOT " + keyRead + " = 1 "); // Match "New" items (read = -1) as well - } - if (filter.showPaused) { - statements.add(" (" + keyPosition + " NOT NULL AND " + keyPosition + " > 0 " + ") "); - } else if (filter.showNotPaused) { - statements.add(" (" + keyPosition + " IS NULL OR " + keyPosition + " = 0 " + ") "); - } - if (filter.showQueued) { - statements.add(keyItemId + " IN (SELECT " + keyFeedItem + " FROM " + tableQueue + ") "); - } else if (filter.showNotQueued) { - statements.add(keyItemId + " NOT IN (SELECT " + keyFeedItem + " FROM " + tableQueue + ") "); - } - if (filter.showDownloaded) { - statements.add(keyDownloaded + " = 1 "); - } else if (filter.showNotDownloaded) { - statements.add(keyDownloaded + " = 0 "); - } - if (filter.showHasMedia) { - statements.add(keyMediaId + " NOT NULL "); - } else if (filter.showNoMedia) { - statements.add(keyMediaId + " IS NULL "); - } - if (filter.showIsFavorite) { - statements.add(keyItemId + " IN (SELECT " + keyFeedItem + " FROM " + tableFavorites + ") "); - } else if (filter.showNotFavorite) { - statements.add(keyItemId + " NOT IN (SELECT " + keyFeedItem + " FROM " + tableFavorites + ") "); - } - - if (statements.isEmpty()) { - return ""; - } - - StringBuilder query = new StringBuilder(" (" + statements.get(0)); - for (String r : statements.subList(1, statements.size())) { - query.append(" AND "); - query.append(r); - } - query.append(") "); - return query.toString(); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java deleted file mode 100644 index 0dc3dc231..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java +++ /dev/null @@ -1,67 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import android.database.Cursor; -import androidx.annotation.NonNull; -import de.danoeh.antennapod.model.feed.FeedMedia; -import de.danoeh.antennapod.core.storage.PodDBAdapter; - -import java.util.Date; - -/** - * Converts a {@link Cursor} to a {@link FeedMedia} object. - */ -public abstract class FeedMediaCursorMapper { - /** - * Create a {@link FeedMedia} instance from a database row (cursor). - */ - @NonNull - public static FeedMedia convert(@NonNull Cursor cursor) { - int indexId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_MEDIA_ID); - int indexPlaybackCompletionDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE); - int indexDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DURATION); - int indexPosition = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_POSITION); - int indexSize = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_SIZE); - int indexMimeType = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_MIME_TYPE); - int indexFileUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FILE_URL); - int indexDownloadUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOAD_URL); - int indexDownloaded = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOADED); - int indexPlayedDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYED_DURATION); - int indexLastPlayedTime = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LAST_PLAYED_TIME); - - long mediaId = cursor.getLong(indexId); - Date playbackCompletionDate = null; - long playbackCompletionTime = cursor.getLong(indexPlaybackCompletionDate); - if (playbackCompletionTime > 0) { - playbackCompletionDate = new Date(playbackCompletionTime); - } - - Boolean hasEmbeddedPicture; - switch (cursor.getInt(cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) { - case 1: - hasEmbeddedPicture = Boolean.TRUE; - break; - case 0: - hasEmbeddedPicture = Boolean.FALSE; - break; - default: - hasEmbeddedPicture = null; - break; - } - - return new FeedMedia( - mediaId, - null, - cursor.getInt(indexDuration), - cursor.getInt(indexPosition), - cursor.getLong(indexSize), - cursor.getString(indexMimeType), - cursor.getString(indexFileUrl), - cursor.getString(indexDownloadUrl), - cursor.getInt(indexDownloaded) > 0, - playbackCompletionDate, - cursor.getInt(indexPlayedDuration), - hasEmbeddedPicture, - cursor.getLong(indexLastPlayedTime) - ); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java deleted file mode 100644 index f062609b6..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java +++ /dev/null @@ -1,74 +0,0 @@ -package de.danoeh.antennapod.core.storage.mapper; - -import android.database.Cursor; -import android.text.TextUtils; -import androidx.annotation.NonNull; -import de.danoeh.antennapod.model.feed.FeedFilter; -import de.danoeh.antennapod.model.feed.FeedPreferences; -import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting; -import de.danoeh.antennapod.core.storage.PodDBAdapter; - -import java.util.Arrays; -import java.util.HashSet; - -/** - * Converts a {@link Cursor} to a {@link FeedPreferences} object. - */ -public abstract class FeedPreferencesCursorMapper { - /** - * Create a {@link FeedPreferences} instance from a database row (cursor). - */ - @NonNull - public static FeedPreferences convert(@NonNull Cursor cursor) { - int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); - int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD_ENABLED); - int indexAutoRefresh = cursor.getColumnIndex(PodDBAdapter.KEY_KEEP_UPDATED); - int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION); - int indexVolumeAdaption = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_VOLUME_ADAPTION); - int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME); - int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD); - int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER); - int indexExcludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_EXCLUDE_FILTER); - int indexMinimalDurationFilter = cursor.getColumnIndex(PodDBAdapter.KEY_MINIMAL_DURATION_FILTER); - int indexFeedPlaybackSpeed = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_PLAYBACK_SPEED); - int indexAutoSkipIntro = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_INTRO); - int indexAutoSkipEnding = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_ENDING); - int indexEpisodeNotification = cursor.getColumnIndex(PodDBAdapter.KEY_EPISODE_NOTIFICATION); - int indexTags = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_TAGS); - - long feedId = cursor.getLong(indexId); - boolean autoDownload = cursor.getInt(indexAutoDownload) > 0; - boolean autoRefresh = cursor.getInt(indexAutoRefresh) > 0; - int autoDeleteActionIndex = cursor.getInt(indexAutoDeleteAction); - FeedPreferences.AutoDeleteAction autoDeleteAction = - FeedPreferences.AutoDeleteAction.values()[autoDeleteActionIndex]; - int volumeAdaptionValue = cursor.getInt(indexVolumeAdaption); - VolumeAdaptionSetting volumeAdaptionSetting = VolumeAdaptionSetting.fromInteger(volumeAdaptionValue); - String username = cursor.getString(indexUsername); - String password = cursor.getString(indexPassword); - String includeFilter = cursor.getString(indexIncludeFilter); - String excludeFilter = cursor.getString(indexExcludeFilter); - int minimalDurationFilter = cursor.getInt(indexMinimalDurationFilter); - float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed); - int feedAutoSkipIntro = cursor.getInt(indexAutoSkipIntro); - int feedAutoSkipEnding = cursor.getInt(indexAutoSkipEnding); - boolean showNotification = cursor.getInt(indexEpisodeNotification) > 0; - String tagsString = cursor.getString(indexTags); - if (TextUtils.isEmpty(tagsString)) { - tagsString = FeedPreferences.TAG_ROOT; - } - return new FeedPreferences(feedId, - autoDownload, - autoRefresh, - autoDeleteAction, - volumeAdaptionSetting, - username, - password, - new FeedFilter(includeFilter, excludeFilter, minimalDurationFilter), - feedPlaybackSpeed, - feedAutoSkipIntro, - feedAutoSkipEnding, - showNotification, - new HashSet<>(Arrays.asList(tagsString.split(FeedPreferences.TAG_SEPARATOR)))); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java deleted file mode 100644 index 06ec8396f..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java +++ /dev/null @@ -1,49 +0,0 @@ -package de.danoeh.antennapod.core.util; - -/** Utility class for Download Errors. */ -public enum DownloadError { - SUCCESS(0), - ERROR_PARSER_EXCEPTION(1), - ERROR_UNSUPPORTED_TYPE(2), - ERROR_CONNECTION_ERROR(3), - ERROR_MALFORMED_URL(4), - ERROR_IO_ERROR(5), - ERROR_FILE_EXISTS(6), - ERROR_DOWNLOAD_CANCELLED(7), - ERROR_DEVICE_NOT_FOUND(8), - ERROR_HTTP_DATA_ERROR(9), - ERROR_NOT_ENOUGH_SPACE(10), - ERROR_UNKNOWN_HOST(11), - ERROR_REQUEST_ERROR(12), - ERROR_DB_ACCESS_ERROR(13), - ERROR_UNAUTHORIZED(14), - ERROR_FILE_TYPE(15), - ERROR_FORBIDDEN(16), - ERROR_IO_WRONG_SIZE(17), - ERROR_IO_BLOCKED(18), - ERROR_UNSUPPORTED_TYPE_HTML(19), - ERROR_NOT_FOUND(20), - ERROR_CERTIFICATE(21), - ERROR_PARSER_EXCEPTION_DUPLICATE(22); - - private final int code; - - DownloadError(int code) { - this.code = code; - } - - /** Return DownloadError from its associated code. */ - public static DownloadError fromCode(int code) { - for (DownloadError reason : values()) { - if (reason.getCode() == code) { - return reason; - } - } - throw new IllegalArgumentException("unknown code: " + code); - } - - /** Get machine-readable code. */ - public int getCode() { - return code; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java index 8834350d1..3d2558a9f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.util; import androidx.annotation.StringRes; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.model.download.DownloadError; /** * Provides user-visible labels for download errors. diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java b/core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java deleted file mode 100644 index 78ed002ac..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java +++ /dev/null @@ -1,263 +0,0 @@ -package de.danoeh.antennapod.core.util; - - -import java.util.Arrays; - -/** - * Fast and memory efficient long to long map - */ -public class LongIntMap { - - private long[] keys; - private int[] values; - private int size; - - /** - * Creates a new LongLongMap containing no mappings. - */ - public LongIntMap() { - this(10); - } - - /** - * Creates a new SparseLongArray containing no mappings that will not - * require any additional memory allocation to store the specified - * number of mappings. If you supply an initial capacity of 0, the - * sparse array will be initialized with a light-weight representation - * not requiring any additional array allocations. - */ - public LongIntMap(int initialCapacity) { - if(initialCapacity < 0) { - throw new IllegalArgumentException("initial capacity must be 0 or higher"); - } - keys = new long[initialCapacity]; - values = new int[initialCapacity]; - size = 0; - } - - /** - * Increases size of array if needed - */ - private void growIfNeeded() { - if (size == keys.length) { - // Resize. - long[] newKeysArray = new long[size * 3 / 2 + 10]; - int[] newValuesArray = new int[size * 3 / 2 + 10]; - System.arraycopy(keys, 0, newKeysArray, 0, size); - System.arraycopy(values, 0, newValuesArray, 0, size); - keys = newKeysArray; - values = newValuesArray; - } - } - - /** - * Gets the long mapped from the specified key, or <code>0</code> - * if no such mapping has been made. - */ - public int get(long key) { - return get(key, 0); - } - - /** - * Gets the long mapped from the specified key, or the specified value - * if no such mapping has been made. - */ - public int get(long key, int valueIfKeyNotFound) { - int index = indexOfKey(key); - if(index >= 0) { - return values[index]; - } else { - return valueIfKeyNotFound; - } - } - - /** - * Removes the mapping from the specified key, if there was any. - */ - public boolean delete(long key) { - int index = indexOfKey(key); - - if (index >= 0) { - removeAt(index); - return true; - } else { - return false; - } - } - - /** - * Removes the mapping at the given index. - */ - private void removeAt(int index) { - System.arraycopy(keys, index + 1, keys, index, size - (index + 1)); - System.arraycopy(values, index + 1, values, index, size - (index + 1)); - size--; - } - - /** - * Adds a mapping from the specified key to the specified value, - * replacing the previous mapping from the specified key if there - * was one. - */ - public void put(long key, int value) { - int index = indexOfKey(key); - - if (index >= 0) { - values[index] = value; - } else { - growIfNeeded(); - keys[size] = key; - values[size] = value; - size++; - } - } - - /** - * Returns the number of key-value mappings that this SparseIntArray - * currently stores. - */ - public int size() { - return size; - } - - /** - * Given an index in the range <code>0...size()-1</code>, returns - * the key from the <code>index</code>th key-value mapping that this - * SparseLongArray stores. - * - * <p>The keys corresponding to indices in ascending order are guaranteed to - * be in ascending order, e.g., <code>keyAt(0)</code> will return the - * smallest key and <code>keyAt(size()-1)</code> will return the largest - * key.</p> - */ - private long keyAt(int index) { - if (index >= size) { - throw new IndexOutOfBoundsException("n >= size()"); - } else if(index < 0) { - throw new IndexOutOfBoundsException("n < 0"); - } - return keys[index]; - } - - /** - * Given an index in the range <code>0...size()-1</code>, returns - * the value from the <code>index</code>th key-value mapping that this - * SparseLongArray stores. - * - * <p>The values corresponding to indices in ascending order are guaranteed - * to be associated with keys in ascending order, e.g., - * <code>valueAt(0)</code> will return the value associated with the - * smallest key and <code>valueAt(size()-1)</code> will return the value - * associated with the largest key.</p> - */ - private int valueAt(int index) { - if (index >= size) { - throw new IndexOutOfBoundsException("n >= size()"); - } else if(index < 0) { - throw new IndexOutOfBoundsException("n < 0"); - } - return values[index]; - } - - /** - * Returns the index for which {@link #keyAt} would return the - * specified key, or a negative number if the specified - * key is not mapped. - */ - public int indexOfKey(long key) { - for(int i=0; i < size; i++) { - if(keys[i] == key) { - return i; - } - } - return -1; - } - - /** - * Returns an index for which {@link #valueAt} would return the - * specified key, or a negative number if no keys map to the - * specified value. - * Beware that this is a linear search, unlike lookups by key, - * and that multiple keys can map to the same value and this will - * find only one of them. - */ - public int indexOfValue(long value) { - for (int i = 0; i < size; i++) { - if (values[i] == value) { - return i; - } - } - return -1; - } - - /** - * Removes all key-value mappings from this SparseIntArray. - */ - public void clear() { - keys = new long[10]; - values = new int[10]; - size = 0; - } - - /** - * Returns a copy of the values contained in this map. - * - * @return a copy of the values contained in this map - */ - public int[] values() { - return Arrays.copyOf(values, size); - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if (! (other instanceof LongIntMap)) { - return false; - } - LongIntMap otherMap = (LongIntMap) other; - if (size != otherMap.size) { - return false; - } - for (int i = 0; i < size; i++) { - if (keys[i] != otherMap.keys[i] || - values[i] != otherMap.values[i]) { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - int hashCode = 1; - for (int i = 0; i < size; i++) { - long value = values[i]; - hashCode = 31 * hashCode + (int)(value ^ (value >>> 32)); - } - return hashCode; - } - - @Override - public String toString() { - if (size() <= 0) { - return "LongLongMap{}"; - } - - StringBuilder buffer = new StringBuilder(size * 28); - buffer.append("LongLongMap{"); - for (int i=0; i < size; i++) { - if (i > 0) { - buffer.append(", "); - } - long key = keyAt(i); - buffer.append(key); - buffer.append('='); - long value = valueAt(i); - buffer.append(value); - } - buffer.append('}'); - return buffer.toString(); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java index 868f3b835..68b38ec7f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java @@ -2,7 +2,7 @@ package de.danoeh.antennapod.core.util.comparator; import java.util.Comparator; -import de.danoeh.antennapod.core.service.download.DownloadStatus; +import de.danoeh.antennapod.model.download.DownloadStatus; /** Compares the completion date of two Downloadstatus objects. */ public class DownloadStatusComparator implements Comparator<DownloadStatus> { diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java index 37d525670..bafee7293 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java @@ -14,6 +14,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -34,7 +35,6 @@ import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.storage.PodDBAdapter; import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.is; diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java index b5c2e5c73..5aa670736 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java @@ -21,6 +21,7 @@ import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java index 6485c9515..09a2580b1 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java @@ -15,6 +15,7 @@ import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java index c9be06afd..834442fdd 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java @@ -13,6 +13,7 @@ import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.LongList; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java index 0d98ba294..0779c6ae3 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java @@ -5,6 +5,7 @@ import android.content.Context; import androidx.test.platform.app.InstrumentationRegistry; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java index 413243d1d..3a3213a37 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java @@ -9,8 +9,8 @@ import de.danoeh.antennapod.model.feed.Chapter; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; -import de.danoeh.antennapod.parser.feed.element.SimpleChapter; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import static org.junit.Assert.assertTrue; @@ -56,7 +56,7 @@ abstract class DbTestUtils { List<Chapter> chapters = new ArrayList<>(); item.setChapters(chapters); for (int k = 0; k < numChapters; k++) { - chapters.add(new SimpleChapter(k, "item " + j + " chapter " + k, + chapters.add(new Chapter(k, "item " + j + " chapter " + k, "http://example.com", "http://example.com/image.png")); } } diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java index 5e73773db..de1e78408 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java @@ -10,6 +10,7 @@ import androidx.core.util.Consumer; import androidx.preference.PreferenceManager; import androidx.test.platform.app.InstrumentationRegistry; +import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.awaitility.Awaitility; import org.junit.After; import org.junit.Before; diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java index 8695f98b1..486aa82a8 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java @@ -6,6 +6,8 @@ import android.database.Cursor; import androidx.test.platform.app.InstrumentationRegistry; +import de.danoeh.antennapod.storage.database.PodDBAdapter; +import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -13,7 +15,6 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.core.storage.PodDBAdapter; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java index 21df71bec..03326d3b1 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.util; +import de.danoeh.antennapod.storage.database.LongIntMap; import org.junit.Test; import static org.junit.Assert.assertEquals; |