summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorByteHamster <ByteHamster@users.noreply.github.com>2021-04-22 22:04:20 +0200
committerGitHub <noreply@github.com>2021-04-22 22:04:20 +0200
commit0081d232d0853166db7e88b5b4d192d0bf13f582 (patch)
treeba2b4e801bfeeef18befb71463700247e8a44824
parent76e42a78bba672ee773b7a3128cc841fb31cca88 (diff)
downloadAntennaPod-0081d232d0853166db7e88b5b4d192d0bf13f582.zip
Moved cursor related code out of model (#5126)
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java37
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java33
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java55
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java56
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java14
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java51
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java46
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java67
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java72
10 files changed, 248 insertions, 185 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java
index 1c13471a5..41b56277e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java
@@ -1,9 +1,5 @@
package de.danoeh.antennapod.core.feed;
-import android.database.Cursor;
-
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
public abstract class Chapter extends FeedComponent {
/** Defines starting point in milliseconds. */
@@ -28,39 +24,6 @@ public abstract class Chapter extends FeedComponent {
this.imageUrl = imageUrl;
}
- public static Chapter fromCursor(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;
- }
-
public abstract int getChapterType();
public long getStart() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
index 25857dad2..aaa24c695 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
@@ -1,7 +1,5 @@
package de.danoeh.antennapod.core.feed;
-import android.database.Cursor;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -15,8 +13,6 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
/**
* Item (episode) within a feed.
*
@@ -133,35 +129,6 @@ public class FeedItem extends FeedComponent implements Serializable {
this.hasChapters = hasChapters;
}
- public static FeedItem fromCursor(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);
- 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);
- }
-
public void updateFromOther(FeedItem other) {
super.updateFromOther(other);
if (other.imageUrl != null) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
index 33480c3a0..6bde08f36 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.core.feed;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
-import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Parcel;
@@ -19,7 +18,6 @@ import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.sync.SyncService;
import de.danoeh.antennapod.core.sync.model.EpisodeAction;
@@ -86,7 +84,7 @@ public class FeedMedia extends FeedFile implements Playable {
this.lastPlayedTime = lastPlayedTime;
}
- private FeedMedia(long id, FeedItem item, int duration, int position,
+ public FeedMedia(long id, FeedItem item, int duration, int position,
long size, String mime_type, String file_url, String download_url,
boolean downloaded, Date playbackCompletionDate, int played_duration,
Boolean hasEmbeddedPicture, long lastPlayedTime) {
@@ -95,57 +93,6 @@ public class FeedMedia extends FeedFile implements Playable {
this.hasEmbeddedPicture = hasEmbeddedPicture;
}
- public static FeedMedia fromCursor(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.getColumnIndex(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)
- );
- }
-
-
@Override
public String getHumanReadableIdentifier() {
if (item != null && item.getTitle() != null) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
index 55b34cbc3..8288280bd 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
@@ -1,13 +1,9 @@
package de.danoeh.antennapod.core.feed;
-import android.database.Cursor;
import androidx.annotation.NonNull;
import android.text.TextUtils;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
import java.io.Serializable;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -47,7 +43,7 @@ public class FeedPreferences implements Serializable {
username, password, new FeedFilter(), SPEED_USE_GLOBAL, 0, 0, false, new HashSet<>());
}
- private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated,
+ public FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated,
AutoDeleteAction autoDeleteAction, VolumeAdaptionSetting volumeAdaptionSetting,
String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed,
int feedSkipIntro, int feedSkipEnding, boolean showEpisodeNotification,
@@ -67,56 +63,6 @@ public class FeedPreferences implements Serializable {
this.tags.addAll(tags);
}
- public static FeedPreferences fromCursor(Cursor cursor) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD);
- 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 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);
- AutoDeleteAction autoDeleteAction = 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);
- 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 = TAG_ROOT;
- }
- return new FeedPreferences(feedId,
- autoDownload,
- autoRefresh,
- autoDeleteAction,
- volumeAdaptionSetting,
- username,
- password,
- new FeedFilter(includeFilter, excludeFilter),
- feedPlaybackSpeed,
- feedAutoSkipIntro,
- feedAutoSkipEnding,
- showNotification,
- new HashSet<>(Arrays.asList(tagsString.split(TAG_SEPARATOR))));
- }
-
/**
* @return the filter for this feed
*/
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 96e418ef6..827dc5f7e 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
@@ -24,7 +24,11 @@ import de.danoeh.antennapod.core.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.core.util.LongList;
import de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator;
@@ -199,10 +203,10 @@ public final class DBReader {
if (cursor.moveToFirst()) {
int indexMediaId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_MEDIA_ID);
do {
- FeedItem item = FeedItem.fromCursor(cursor);
+ FeedItem item = FeedItemCursorMapper.convert(cursor);
result.add(item);
if (!cursor.isNull(indexMediaId)) {
- item.setMedia(FeedMedia.fromCursor(cursor));
+ item.setMedia(FeedMediaCursorMapper.convert(cursor));
}
} while (cursor.moveToNext());
}
@@ -211,7 +215,7 @@ public final class DBReader {
private static Feed extractFeedFromCursorRow(Cursor cursor) {
Feed feed = FeedCursorMapper.convert(cursor);
- FeedPreferences preferences = FeedPreferences.fromCursor(cursor);
+ FeedPreferences preferences = FeedPreferencesCursorMapper.convert(cursor);
feed.setPreferences(preferences);
return feed;
}
@@ -687,7 +691,7 @@ public final class DBReader {
}
ArrayList<Chapter> chapters = new ArrayList<>();
while (cursor.moveToNext()) {
- chapters.add(Chapter.fromCursor(cursor));
+ chapters.add(ChapterCursorMapper.convert(cursor));
}
return chapters;
}
@@ -729,7 +733,7 @@ public final class DBReader {
int indexFeedItem = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM);
long itemId = mediaCursor.getLong(indexFeedItem);
- FeedMedia media = FeedMedia.fromCursor(mediaCursor);
+ FeedMedia media = FeedMediaCursorMapper.convert(mediaCursor);
FeedItem item = getFeedItem(itemId);
if (item != null) {
media.setItem(item);
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
new file mode 100644
index 000000000..def426bd0
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java
@@ -0,0 +1,51 @@
+package de.danoeh.antennapod.core.storage.mapper;
+
+import android.database.Cursor;
+import androidx.annotation.NonNull;
+import de.danoeh.antennapod.core.feed.Chapter;
+import de.danoeh.antennapod.core.feed.ID3Chapter;
+import de.danoeh.antennapod.core.feed.SimpleChapter;
+import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+
+/**
+ * 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/FeedCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java
index 783fba596..6f48eadad 100644
--- 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
@@ -63,7 +63,7 @@ public abstract class FeedCursorMapper {
cursor.getInt(indexLastUpdateFailed) > 0
);
- FeedPreferences preferences = FeedPreferences.fromCursor(cursor);
+ 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
new file mode 100644
index 000000000..aa2c78e03
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java
@@ -0,0 +1,46 @@
+package de.danoeh.antennapod.core.storage.mapper;
+
+import android.database.Cursor;
+import androidx.annotation.NonNull;
+import de.danoeh.antennapod.core.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);
+ 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/FeedMediaCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java
new file mode 100644
index 000000000..44617cffa
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java
@@ -0,0 +1,67 @@
+package de.danoeh.antennapod.core.storage.mapper;
+
+import android.database.Cursor;
+import androidx.annotation.NonNull;
+import de.danoeh.antennapod.core.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.getColumnIndex(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
new file mode 100644
index 000000000..1115d8161
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java
@@ -0,0 +1,72 @@
+package de.danoeh.antennapod.core.storage.mapper;
+
+import android.database.Cursor;
+import android.text.TextUtils;
+import androidx.annotation.NonNull;
+import de.danoeh.antennapod.core.feed.FeedFilter;
+import de.danoeh.antennapod.core.feed.FeedPreferences;
+import de.danoeh.antennapod.core.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);
+ 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 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);
+ 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),
+ feedPlaybackSpeed,
+ feedAutoSkipIntro,
+ feedAutoSkipEnding,
+ showNotification,
+ new HashSet<>(Arrays.asList(tagsString.split(FeedPreferences.TAG_SEPARATOR))));
+ }
+}