summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorByteHamster <ByteHamster@users.noreply.github.com>2021-08-28 10:54:17 +0200
committerGitHub <noreply@github.com>2021-08-28 10:54:17 +0200
commite75d8db2981ffe9abbb9b0e9395862e83dda34df (patch)
treee903d0beb123802bfec0367f772d66b1cb7c3c30
parent87c50ac7a03169b5213b2dce37ac3f8415f6e0cb (diff)
parent24389d42e89037b205fff2bc681e4ad998895286 (diff)
downloadAntennaPod-e75d8db2981ffe9abbb9b0e9395862e83dda34df.zip
Merge pull request #5360 from ByteHamster/parser
Moved feed parser to its own module
-rw-r--r--app/build.gradle1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java6
-rw-r--r--core/build.gradle1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java138
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java120
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/Namespace.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/SyndElement.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DateFormatter.java46
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java2
-rw-r--r--parser/README.md3
-rw-r--r--parser/feed/README.md3
-rw-r--r--parser/feed/build.gradle23
-rw-r--r--parser/feed/src/main/AndroidManifest.xml1
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/FeedHandler.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/handler/FeedHandler.java)3
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/FeedHandlerResult.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/handler/FeedHandlerResult.java)2
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/HandlerState.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java)19
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/SyndHandler.java139
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/UnsupportedFeedtypeException.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java)5
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/AtomText.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java)6
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SimpleChapter.java (renamed from core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java)2
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SyndElement.java22
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Atom.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java)30
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Content.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSContent.java)9
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/DublinCore.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSDublinCore.java)9
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Itunes.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java)11
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Media.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java)11
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Namespace.java19
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/PodcastIndex.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/PodcastIndex.java)5
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Rss20.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java)23
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/SimpleChapters.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java)11
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/DateUtils.java (renamed from core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java)51
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/DurationParser.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java)2
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/SyndStringUtils.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndStringUtils.java)2
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/SyndTypeUtils.java (renamed from core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java)2
-rw-r--r--parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/TypeGetter.java121
-rw-r--r--parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/element/AtomTextTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomTextTest.java)6
-rw-r--r--parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/AtomParserTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/syndication/handler/AtomParserTest.java)4
-rw-r--r--parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/FeedParserTestHelper.java (renamed from core/src/test/java/de/danoeh/antennapod/core/syndication/handler/FeedParserTestHelper.java)3
-rw-r--r--parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/RssParserTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/syndication/handler/RssParserTest.java)2
-rw-r--r--parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/util/DateUtilsTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/util/DateUtilsTest.java)3
-rw-r--r--parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/util/DurationParserTest.java (renamed from core/src/test/java/de/danoeh/antennapod/core/syndication/parsers/DurationParserTest.java)3
-rw-r--r--parser/feed/src/test/resources/feed-atom-testAtomBasic.xml (renamed from core/src/test/resources/feed-atom-testAtomBasic.xml)0
-rw-r--r--parser/feed/src/test/resources/feed-atom-testEmptyRelLinks.xml (renamed from core/src/test/resources/feed-atom-testEmptyRelLinks.xml)0
-rw-r--r--parser/feed/src/test/resources/feed-atom-testLogoWithWhitespace.xml (renamed from core/src/test/resources/feed-atom-testLogoWithWhitespace.xml)0
-rw-r--r--parser/feed/src/test/resources/feed-rss-testImageWithWhitespace.xml (renamed from core/src/test/resources/feed-rss-testImageWithWhitespace.xml)0
-rw-r--r--parser/feed/src/test/resources/feed-rss-testMediaContentMime.xml (renamed from core/src/test/resources/feed-rss-testMediaContentMime.xml)0
-rw-r--r--parser/feed/src/test/resources/feed-rss-testMultipleFundingTags.xml (renamed from core/src/test/resources/feed-rss-testMultipleFundingTags.xml)0
-rw-r--r--parser/feed/src/test/resources/feed-rss-testRss2Basic.xml (renamed from core/src/test/resources/feed-rss-testRss2Basic.xml)0
-rw-r--r--settings.gradle2
61 files changed, 506 insertions, 456 deletions
diff --git a/app/build.gradle b/app/build.gradle
index b2d6a5600..0d710c4cf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -114,6 +114,7 @@ dependencies {
implementation project(':model')
implementation project(':net:sync:gpoddernet')
implementation project(':net:sync:model')
+ implementation project(':parser:feed')
implementation project(':ui:app-start-intent')
implementation project(':ui:common')
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java
index 9361c23df..6b294244a 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/Rss2Generator.java
@@ -11,8 +11,8 @@ import java.util.ArrayList;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedFunding;
import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.core.syndication.namespace.PodcastIndex;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.parser.feed.namespace.PodcastIndex;
+import de.danoeh.antennapod.core.util.DateFormatter;
/**
* Creates RSS 2.0 feeds. See FeedGenerator for more information.
@@ -98,7 +98,7 @@ public class Rss2Generator implements FeedGenerator {
}
if (item.getPubDate() != null) {
xml.startTag(null, "pubDate");
- xml.text(DateUtils.formatRFC822Date(item.getPubDate()));
+ xml.text(DateFormatter.formatRfc822Date(item.getPubDate()));
xml.endTag(null, "pubDate");
}
if ((flags & FEATURE_WRITE_GUID) != 0) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
index 575e94f8c..ec9e20dea 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -46,9 +46,8 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult;
-import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
+import de.danoeh.antennapod.parser.feed.FeedHandler;
+import de.danoeh.antennapod.parser.feed.FeedHandlerResult;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.FileNameGenerator;
import de.danoeh.antennapod.core.util.IntentUtils;
@@ -63,6 +62,7 @@ import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting;
import de.danoeh.antennapod.model.playback.RemoteMedia;
+import de.danoeh.antennapod.parser.feed.UnsupportedFeedtypeException;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
index 62a97e849..2ab96e84d 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistDescriptionAdapter.java
@@ -17,7 +17,7 @@ import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.model.playback.RemoteMedia;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.DateFormatter;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
@@ -58,7 +58,7 @@ public class FeedItemlistDescriptionAdapter extends ArrayAdapter<FeedItem> {
}
holder.title.setText(item.getTitle());
- holder.pubDate.setText(DateUtils.formatAbbrev(getContext(), item.getPubDate()));
+ holder.pubDate.setText(DateFormatter.formatAbbrev(getContext(), item.getPubDate()));
if (item.getDescription() != null) {
String description = HtmlToPlainText.getPlainText(item.getDescription())
.replaceAll("\n", " ")
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java
index a71595c55..5fec5f063 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java
@@ -7,7 +7,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.StatisticsItem;
import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.DateFormatter;
import de.danoeh.antennapod.view.PieChartView;
import java.util.Date;
@@ -32,7 +32,7 @@ public class PlaybackStatisticsListAdapter extends StatisticsListAdapter {
String getHeaderCaption() {
long usageCounting = UserPreferences.getUsageCountingDateMillis();
if (usageCounting > 0) {
- String date = DateUtils.formatAbbrev(context, new Date(usageCounting));
+ String date = DateFormatter.formatAbbrev(context, new Date(usageCounting));
return context.getString(R.string.statistics_counting_since, date);
} else {
return context.getString(R.string.total_time_listened_to_podcasts);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
index 5dbadaefa..67d1757ac 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
@@ -50,7 +50,7 @@ import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.util.ChapterUtils;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.DateFormatter;
import de.danoeh.antennapod.core.util.EmbeddedChapterImage;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.model.feed.Chapter;
@@ -150,7 +150,7 @@ public class CoverFragment extends Fragment {
}
private void displayMediaInfo(@NonNull Playable media) {
- String pubDateStr = DateUtils.formatAbbrev(getActivity(), media.getPubDate());
+ String pubDateStr = DateFormatter.formatAbbrev(getActivity(), media.getPubDate());
txtvPodcastTitle.setText(StringUtils.stripToEmpty(media.getFeedTitle())
+ "\u00A0"
+ "・"
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
index 5a2061a5f..31c6da8cd 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -55,7 +55,7 @@ import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.core.util.DateFormatter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.ui.common.ThemeUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
@@ -291,9 +291,9 @@ public class ItemFragment extends Fragment {
txtvTitle.setText(item.getTitle());
if (item.getPubDate() != null) {
- String pubDateStr = DateUtils.formatAbbrev(getActivity(), item.getPubDate());
+ String pubDateStr = DateFormatter.formatAbbrev(getActivity(), item.getPubDate());
txtvPublished.setText(pubDateStr);
- txtvPublished.setContentDescription(DateUtils.formatForAccessibility(getContext(), item.getPubDate()));
+ txtvPublished.setContentDescription(DateFormatter.formatForAccessibility(getContext(), item.getPubDate()));
}
RequestOptions options = new RequestOptions()
diff --git a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
index 02d45b2a0..cd3af5003 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/viewholder/EpisodeItemViewHolder.java
@@ -22,6 +22,7 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.CoverLoader;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
+import de.danoeh.antennapod.core.util.DateFormatter;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.MediaType;
@@ -31,7 +32,6 @@ import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.ui.common.CircularProgressBar;
@@ -103,8 +103,8 @@ public class EpisodeItemViewHolder extends RecyclerView.ViewHolder {
placeholder.setText(item.getFeed().getTitle());
title.setText(item.getTitle());
leftPadding.setContentDescription(item.getTitle());
- pubDate.setText(DateUtils.formatAbbrev(activity, item.getPubDate()));
- pubDate.setContentDescription(DateUtils.formatForAccessibility(activity, item.getPubDate()));
+ pubDate.setText(DateFormatter.formatAbbrev(activity, item.getPubDate()));
+ pubDate.setContentDescription(DateFormatter.formatForAccessibility(activity, item.getPubDate()));
isNew.setVisibility(item.isNew() ? View.VISIBLE : View.GONE);
isFavorite.setVisibility(item.isTagged(FeedItem.TAG_FAVORITE) ? View.VISIBLE : View.GONE);
isInQueue.setVisibility(item.isTagged(FeedItem.TAG_QUEUE) ? View.VISIBLE : View.GONE);
diff --git a/core/build.gradle b/core/build.gradle
index 44d53ecac..121b4311e 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -24,6 +24,7 @@ dependencies {
implementation project(':net:ssl')
implementation project(':net:sync:gpoddernet')
implementation project(':net:sync:model')
+ implementation project(':parser:feed')
implementation project(':ui:app-start-intent')
implementation project(':ui:common')
implementation project(':ui:png-icons')
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java
index e2205471c..a44d90557 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.util.Log;
import android.util.Xml;
+import de.danoeh.antennapod.core.util.DateFormatter;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
@@ -13,7 +14,6 @@ import java.util.List;
import de.danoeh.antennapod.core.export.ExportWriter;
import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.core.util.DateUtils;
/** Writes OPML documents. */
public class OpmlWriter implements ExportWriter {
@@ -44,7 +44,7 @@ public class OpmlWriter implements ExportWriter {
xs.text(OPML_TITLE);
xs.endTag(null, OpmlSymbols.TITLE);
xs.startTag(null, OpmlSymbols.DATE_CREATED);
- xs.text(DateUtils.formatRFC822Date(new Date()));
+ xs.text(DateFormatter.formatRfc822Date(new Date()));
xs.endTag(null, OpmlSymbols.DATE_CREATED);
xs.endTag(null, OpmlSymbols.HEAD);
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 7a8c4969b..82583b7b5 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
@@ -27,7 +27,7 @@ import de.danoeh.antennapod.core.service.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.core.util.DateUtils;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
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 1320b7052..781110f82 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
@@ -24,7 +24,7 @@ import java.util.regex.Pattern;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.URIUtil;
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 3e3da00e7..9a0916109 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
@@ -8,9 +8,9 @@ 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.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult;
-import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
+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.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 1ca4d1194..dcc1c8fdb 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
@@ -9,7 +9,7 @@ import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult;
+import de.danoeh.antennapod.parser.feed.FeedHandlerResult;
public class FeedSyncTask {
private static final String TAG = "FeedParserTask";
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
index b171f2bcc..61613a25a 100644
--- 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
@@ -4,7 +4,7 @@ import android.database.Cursor;
import androidx.annotation.NonNull;
import de.danoeh.antennapod.model.feed.Chapter;
import de.danoeh.antennapod.core.feed.ID3Chapter;
-import de.danoeh.antennapod.core.feed.SimpleChapter;
+import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
import de.danoeh.antennapod.core.feed.VorbisCommentChapter;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java
deleted file mode 100644
index 9c09be714..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/SyndHandler.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package de.danoeh.antennapod.core.syndication.handler;
-
-import android.util.Log;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.core.syndication.namespace.NSContent;
-import de.danoeh.antennapod.core.syndication.namespace.NSDublinCore;
-import de.danoeh.antennapod.core.syndication.namespace.NSITunes;
-import de.danoeh.antennapod.core.syndication.namespace.NSMedia;
-import de.danoeh.antennapod.core.syndication.namespace.NSRSS20;
-import de.danoeh.antennapod.core.syndication.namespace.NSSimpleChapters;
-import de.danoeh.antennapod.core.syndication.namespace.Namespace;
-import de.danoeh.antennapod.core.syndication.namespace.PodcastIndex;
-import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
-import de.danoeh.antennapod.core.syndication.namespace.atom.NSAtom;
-
-/** Superclass for all SAX Handlers which process Syndication formats */
-class SyndHandler extends DefaultHandler {
- private static final String TAG = "SyndHandler";
- private static final String DEFAULT_PREFIX = "";
- final HandlerState state;
-
- public SyndHandler(Feed feed, TypeGetter.Type type) {
- state = new HandlerState(feed);
- if (type == TypeGetter.Type.RSS20 || type == TypeGetter.Type.RSS091) {
- state.defaultNamespaces.push(new NSRSS20());
- }
- }
-
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
- state.contentBuf = new StringBuilder();
- Namespace handler = getHandlingNamespace(uri, qName);
- if (handler != null) {
- SyndElement element = handler.handleElementStart(localName, state,
- attributes);
- state.tagstack.push(element);
-
- }
- }
-
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- if (!state.tagstack.empty()) {
- if (state.getTagstack().size() >= 2) {
- if (state.contentBuf != null) {
- state.contentBuf.append(ch, start, length);
- }
- }
- }
- }
-
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- Namespace handler = getHandlingNamespace(uri, qName);
- if (handler != null) {
- handler.handleElementEnd(localName, state);
- state.tagstack.pop();
-
- }
- state.contentBuf = null;
-
- }
-
- @Override
- public void endPrefixMapping(String prefix) throws SAXException {
- if (state.defaultNamespaces.size() > 1 && prefix.equals(DEFAULT_PREFIX)) {
- state.defaultNamespaces.pop();
- }
- }
-
- @Override
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException {
- // Find the right namespace
- if (!state.namespaces.containsKey(uri)) {
- if (uri.equals(NSAtom.NSURI)) {
- if (prefix.equals(DEFAULT_PREFIX)) {
- state.defaultNamespaces.push(new NSAtom());
- } else if (prefix.equals(NSAtom.NSTAG)) {
- state.namespaces.put(uri, new NSAtom());
- Log.d(TAG, "Recognized Atom namespace");
- }
- } else if (uri.equals(NSContent.NSURI)
- && prefix.equals(NSContent.NSTAG)) {
- state.namespaces.put(uri, new NSContent());
- Log.d(TAG, "Recognized Content namespace");
- } else if (uri.equals(NSITunes.NSURI)
- && prefix.equals(NSITunes.NSTAG)) {
- state.namespaces.put(uri, new NSITunes());
- Log.d(TAG, "Recognized ITunes namespace");
- } else if (uri.equals(NSSimpleChapters.NSURI)
- && prefix.matches(NSSimpleChapters.NSTAG)) {
- state.namespaces.put(uri, new NSSimpleChapters());
- Log.d(TAG, "Recognized SimpleChapters namespace");
- } else if (uri.equals(NSMedia.NSURI)
- && prefix.equals(NSMedia.NSTAG)) {
- state.namespaces.put(uri, new NSMedia());
- Log.d(TAG, "Recognized media namespace");
- } else if (uri.equals(NSDublinCore.NSURI)
- && prefix.equals(NSDublinCore.NSTAG)) {
- state.namespaces.put(uri, new NSDublinCore());
- Log.d(TAG, "Recognized DublinCore namespace");
- } else if (uri.equals(PodcastIndex.NSURI) || uri.equals(PodcastIndex.NSURI2)
- && prefix.equals(PodcastIndex.NSTAG)) {
- state.namespaces.put(uri, new PodcastIndex());
- Log.d(TAG, "Recognized PodcastIndex namespace");
- }
- }
- }
-
- private Namespace getHandlingNamespace(String uri, String qName) {
- Namespace handler = state.namespaces.get(uri);
- if (handler == null && !state.defaultNamespaces.empty()
- && !qName.contains(":")) {
- handler = state.defaultNamespaces.peek();
- }
- return handler;
- }
-
- @Override
- public void endDocument() throws SAXException {
- super.endDocument();
- state.getFeed().setItems(state.getItems());
- }
-
- public HandlerState getState() {
- return state;
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java
deleted file mode 100644
index e6011e3fa..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package de.danoeh.antennapod.core.syndication.handler;
-
-import android.util.Log;
-
-import org.apache.commons.io.input.XmlStreamReader;
-import org.jsoup.Jsoup;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.Reader;
-
-import de.danoeh.antennapod.model.feed.Feed;
-
-/** Gets the type of a specific feed by reading the root element. */
-public class TypeGetter {
- private static final String TAG = "TypeGetter";
-
- public enum Type {
- RSS20, RSS091, ATOM, INVALID
- }
-
- private static final String ATOM_ROOT = "feed";
- private static final String RSS_ROOT = "rss";
-
- public Type getType(Feed feed) throws UnsupportedFeedtypeException {
- XmlPullParserFactory factory;
- if (feed.getFile_url() != null) {
- Reader reader = null;
- try {
- factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
- XmlPullParser xpp = factory.newPullParser();
- reader = createReader(feed);
- xpp.setInput(reader);
- int eventType = xpp.getEventType();
-
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlPullParser.START_TAG) {
- String tag = xpp.getName();
- switch (tag) {
- case ATOM_ROOT:
- feed.setType(Feed.TYPE_ATOM1);
- Log.d(TAG, "Recognized type Atom");
-
- String strLang = xpp.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang");
- if (strLang != null) {
- feed.setLanguage(strLang);
- }
-
- return Type.ATOM;
- case RSS_ROOT:
- String strVersion = xpp.getAttributeValue(null, "version");
- if (strVersion == null) {
- feed.setType(Feed.TYPE_RSS2);
- Log.d(TAG, "Assuming type RSS 2.0");
- return Type.RSS20;
- } else if (strVersion.equals("2.0")) {
- feed.setType(Feed.TYPE_RSS2);
- Log.d(TAG, "Recognized type RSS 2.0");
- return Type.RSS20;
- } else if (strVersion.equals("0.91") || strVersion.equals("0.92")) {
- Log.d(TAG, "Recognized type RSS 0.91/0.92");
- return Type.RSS091;
- }
- throw new UnsupportedFeedtypeException("Unsupported rss version");
- default:
- Log.d(TAG, "Type is invalid");
- throw new UnsupportedFeedtypeException(Type.INVALID, tag);
- }
- } else {
- eventType = xpp.next();
- }
- }
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- // XML document might actually be a HTML document -> try to parse as HTML
- String rootElement = null;
- try {
- if (Jsoup.parse(new File(feed.getFile_url()), null) != null) {
- rootElement = "html";
- }
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- throw new UnsupportedFeedtypeException(Type.INVALID, rootElement);
-
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if(reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- Log.d(TAG, "Type is invalid");
- throw new UnsupportedFeedtypeException(Type.INVALID);
- }
-
- private Reader createReader(Feed feed) {
- Reader reader;
- try {
- reader = new XmlStreamReader(new File(feed.getFile_url()));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- return null;
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- return reader;
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/Namespace.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/Namespace.java
deleted file mode 100644
index e5fbdb9bb..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/Namespace.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package de.danoeh.antennapod.core.syndication.namespace;
-
-import org.xml.sax.Attributes;
-
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-
-
-public abstract class Namespace {
- public static final String NSTAG = null;
- public static final String NSURI = null;
-
- /** Called by a Feedhandler when in startElement and it detects a namespace element
- * @return The SyndElement to push onto the stack
- * */
- public abstract SyndElement handleElementStart(String localName, HandlerState state, Attributes attributes);
-
- /** Called by a Feedhandler when in endElement and it detects a namespace element
- * */
- public abstract void handleElementEnd(String localName, HandlerState state);
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/SyndElement.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/SyndElement.java
deleted file mode 100644
index ba1b8ba5c..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/SyndElement.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.danoeh.antennapod.core.syndication.namespace;
-
-/** Defines a XML Element that is pushed on the tagstack */
-public class SyndElement {
- private final String name;
- private final Namespace namespace;
-
- public SyndElement(String name, Namespace namespace) {
- this.name = name;
- this.namespace = namespace;
- }
-
- public Namespace getNamespace() {
- return namespace;
- }
-
- public String getName() {
- return name;
- }
-
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateFormatter.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateFormatter.java
new file mode 100644
index 000000000..99628dfcc
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateFormatter.java
@@ -0,0 +1,46 @@
+package de.danoeh.antennapod.core.util;
+
+import android.content.Context;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+/**
+ * Formats dates.
+ */
+public class DateFormatter {
+ private DateFormatter() {
+
+ }
+
+ public static String formatRfc822Date(Date date) {
+ SimpleDateFormat format = new SimpleDateFormat("dd MMM yy HH:mm:ss Z", Locale.US);
+ return format.format(date);
+ }
+
+ public static String formatAbbrev(final Context context, final Date date) {
+ if (date == null) {
+ return "";
+ }
+ GregorianCalendar now = new GregorianCalendar();
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(date);
+ boolean withinLastYear = now.get(Calendar.YEAR) == cal.get(Calendar.YEAR);
+ int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL;
+ if (withinLastYear) {
+ format |= android.text.format.DateUtils.FORMAT_NO_YEAR;
+ }
+ return android.text.format.DateUtils.formatDateTime(context, date.getTime(), format);
+ }
+
+ public static String formatForAccessibility(final Context context, final Date date) {
+ if (date == null) {
+ return "";
+ }
+ return DateFormat.getDateInstance(DateFormat.LONG).format(date);
+ }
+}
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 6c1e8d4f9..413243d1d 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,7 +9,7 @@ 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.core.feed.SimpleChapter;
+import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
import static org.junit.Assert.assertTrue;
diff --git a/parser/README.md b/parser/README.md
new file mode 100644
index 000000000..c4fe1a933
--- /dev/null
+++ b/parser/README.md
@@ -0,0 +1,3 @@
+# :parser
+
+This folder contains modules that parse data, for example XML or media files.
diff --git a/parser/feed/README.md b/parser/feed/README.md
new file mode 100644
index 000000000..cfda75a4c
--- /dev/null
+++ b/parser/feed/README.md
@@ -0,0 +1,3 @@
+# :parser:feed
+
+This module provides the XML feed parser.
diff --git a/parser/feed/build.gradle b/parser/feed/build.gradle
new file mode 100644
index 000000000..3f6ea4aa3
--- /dev/null
+++ b/parser/feed/build.gradle
@@ -0,0 +1,23 @@
+apply plugin: "com.android.library"
+apply from: "../../common.gradle"
+
+android {
+ lintOptions {
+ disable "TrustAllX509TrustManager"
+ }
+}
+
+dependencies {
+ implementation project(':model')
+
+ annotationProcessor "androidx.annotation:annotation:$annotationVersion"
+
+ implementation "androidx.core:core:$appcompatVersion"
+
+ implementation "org.apache.commons:commons-lang3:$commonslangVersion"
+ implementation "commons-io:commons-io:$commonsioVersion"
+ implementation "org.jsoup:jsoup:$jsoupVersion"
+
+ testImplementation 'junit:junit:4.13'
+ testImplementation 'org.robolectric:robolectric:4.5-alpha-1'
+}
diff --git a/parser/feed/src/main/AndroidManifest.xml b/parser/feed/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..44b10f29a
--- /dev/null
+++ b/parser/feed/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+<manifest package="de.danoeh.antennapod.parser.feed" />
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/FeedHandler.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/FeedHandler.java
index 2928ba836..c7f5c4f21 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/FeedHandler.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/FeedHandler.java
@@ -1,8 +1,9 @@
-package de.danoeh.antennapod.core.syndication.handler;
+package de.danoeh.antennapod.parser.feed;
import android.text.TextUtils;
import android.util.Log;
+import de.danoeh.antennapod.parser.feed.util.TypeGetter;
import org.apache.commons.io.input.XmlStreamReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/FeedHandlerResult.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/FeedHandlerResult.java
index fb4bf4707..43b3387a0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/FeedHandlerResult.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/FeedHandlerResult.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.syndication.handler;
+package de.danoeh.antennapod.parser.feed;
import java.util.Map;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/HandlerState.java
index 2fecb0536..706a328e8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/HandlerState.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/HandlerState.java
@@ -1,16 +1,15 @@
-package de.danoeh.antennapod.core.syndication.handler;
-
-import androidx.collection.ArrayMap;
+package de.danoeh.antennapod.parser.feed;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedFunding;
import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.core.syndication.namespace.Namespace;
-import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
+import de.danoeh.antennapod.parser.feed.namespace.Namespace;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
/**
* Contains all relevant information to describe the current state of a
@@ -21,12 +20,12 @@ public class HandlerState {
/**
* Feed that the Handler is currently processing.
*/
- Feed feed;
+ public Feed feed;
/**
* Contains links to related feeds, e.g. feeds with enclosures in other formats. The key of the map is the
* URL of the feed, the value is the title
*/
- final Map<String, String> alternateUrls;
+ public final Map<String, String> alternateUrls;
private final ArrayList<FeedItem> items;
private FeedItem currentItem;
private FeedFunding currentFunding;
@@ -48,12 +47,12 @@ public class HandlerState {
public HandlerState(Feed feed) {
this.feed = feed;
- alternateUrls = new ArrayMap<>();
+ alternateUrls = new HashMap<>();
items = new ArrayList<>();
tagstack = new Stack<>();
- namespaces = new ArrayMap<>();
+ namespaces = new HashMap<>();
defaultNamespaces = new Stack<>();
- tempObjects = new ArrayMap<>();
+ tempObjects = new HashMap<>();
}
public Feed getFeed() {
diff --git a/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/SyndHandler.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/SyndHandler.java
new file mode 100644
index 000000000..16bbecbb8
--- /dev/null
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/SyndHandler.java
@@ -0,0 +1,139 @@
+package de.danoeh.antennapod.parser.feed;
+
+import android.util.Log;
+
+import de.danoeh.antennapod.parser.feed.util.TypeGetter;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.parser.feed.namespace.Content;
+import de.danoeh.antennapod.parser.feed.namespace.DublinCore;
+import de.danoeh.antennapod.parser.feed.namespace.Itunes;
+import de.danoeh.antennapod.parser.feed.namespace.Media;
+import de.danoeh.antennapod.parser.feed.namespace.Rss20;
+import de.danoeh.antennapod.parser.feed.namespace.SimpleChapters;
+import de.danoeh.antennapod.parser.feed.namespace.Namespace;
+import de.danoeh.antennapod.parser.feed.namespace.PodcastIndex;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import de.danoeh.antennapod.parser.feed.namespace.Atom;
+
+/** Superclass for all SAX Handlers which process Syndication formats */
+public class SyndHandler extends DefaultHandler {
+ private static final String TAG = "SyndHandler";
+ private static final String DEFAULT_PREFIX = "";
+ public final HandlerState state;
+
+ public SyndHandler(Feed feed, TypeGetter.Type type) {
+ state = new HandlerState(feed);
+ if (type == TypeGetter.Type.RSS20 || type == TypeGetter.Type.RSS091) {
+ state.defaultNamespaces.push(new Rss20());
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes) throws SAXException {
+ state.contentBuf = new StringBuilder();
+ Namespace handler = getHandlingNamespace(uri, qualifiedName);
+ if (handler != null) {
+ SyndElement element = handler.handleElementStart(localName, state,
+ attributes);
+ state.tagstack.push(element);
+
+ }
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+ if (!state.tagstack.empty()) {
+ if (state.getTagstack().size() >= 2) {
+ if (state.contentBuf != null) {
+ state.contentBuf.append(ch, start, length);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qualifiedName)
+ throws SAXException {
+ Namespace handler = getHandlingNamespace(uri, qualifiedName);
+ if (handler != null) {
+ handler.handleElementEnd(localName, state);
+ state.tagstack.pop();
+
+ }
+ state.contentBuf = null;
+
+ }
+
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+ if (state.defaultNamespaces.size() > 1 && prefix.equals(DEFAULT_PREFIX)) {
+ state.defaultNamespaces.pop();
+ }
+ }
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri)
+ throws SAXException {
+ // Find the right namespace
+ if (!state.namespaces.containsKey(uri)) {
+ if (uri.equals(Atom.NSURI)) {
+ if (prefix.equals(DEFAULT_PREFIX)) {
+ state.defaultNamespaces.push(new Atom());
+ } else if (prefix.equals(Atom.NSTAG)) {
+ state.namespaces.put(uri, new Atom());
+ Log.d(TAG, "Recognized Atom namespace");
+ }
+ } else if (uri.equals(Content.NSURI)
+ && prefix.equals(Content.NSTAG)) {
+ state.namespaces.put(uri, new Content());
+ Log.d(TAG, "Recognized Content namespace");
+ } else if (uri.equals(Itunes.NSURI)
+ && prefix.equals(Itunes.NSTAG)) {
+ state.namespaces.put(uri, new Itunes());
+ Log.d(TAG, "Recognized ITunes namespace");
+ } else if (uri.equals(SimpleChapters.NSURI)
+ && prefix.matches(SimpleChapters.NSTAG)) {
+ state.namespaces.put(uri, new SimpleChapters());
+ Log.d(TAG, "Recognized SimpleChapters namespace");
+ } else if (uri.equals(Media.NSURI)
+ && prefix.equals(Media.NSTAG)) {
+ state.namespaces.put(uri, new Media());
+ Log.d(TAG, "Recognized media namespace");
+ } else if (uri.equals(DublinCore.NSURI)
+ && prefix.equals(DublinCore.NSTAG)) {
+ state.namespaces.put(uri, new DublinCore());
+ Log.d(TAG, "Recognized DublinCore namespace");
+ } else if (uri.equals(PodcastIndex.NSURI) || uri.equals(PodcastIndex.NSURI2)
+ && prefix.equals(PodcastIndex.NSTAG)) {
+ state.namespaces.put(uri, new PodcastIndex());
+ Log.d(TAG, "Recognized PodcastIndex namespace");
+ }
+ }
+ }
+
+ private Namespace getHandlingNamespace(String uri, String qualifiedName) {
+ Namespace handler = state.namespaces.get(uri);
+ if (handler == null && !state.defaultNamespaces.empty()
+ && !qualifiedName.contains(":")) {
+ handler = state.defaultNamespaces.peek();
+ }
+ return handler;
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ super.endDocument();
+ state.getFeed().setItems(state.getItems());
+ }
+
+ public HandlerState getState() {
+ return state;
+ }
+
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/UnsupportedFeedtypeException.java
index c9f9f19c8..74c126a50 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/UnsupportedFeedtypeException.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/UnsupportedFeedtypeException.java
@@ -1,6 +1,7 @@
-package de.danoeh.antennapod.core.syndication.handler;
+package de.danoeh.antennapod.parser.feed;
-import de.danoeh.antennapod.core.syndication.handler.TypeGetter.Type;
+import de.danoeh.antennapod.parser.feed.util.TypeGetter;
+import de.danoeh.antennapod.parser.feed.util.TypeGetter.Type;
public class UnsupportedFeedtypeException extends Exception {
private static final long serialVersionUID = 9105878964928170669L;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/AtomText.java
index 0c0561279..8acd9cbb4 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/AtomText.java
@@ -1,13 +1,11 @@
-package de.danoeh.antennapod.core.syndication.namespace.atom;
+package de.danoeh.antennapod.parser.feed.element;
import androidx.core.text.HtmlCompat;
-import de.danoeh.antennapod.core.syndication.namespace.Namespace;
-import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
+import de.danoeh.antennapod.parser.feed.namespace.Namespace;
/** Represents Atom Element which contains text (content, title, summary). */
public class AtomText extends SyndElement {
- public static final String TYPE_TEXT = "text";
public static final String TYPE_HTML = "html";
private static final String TYPE_XHTML = "xhtml";
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SimpleChapter.java
index ca59f867b..069e49f09 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/SimpleChapter.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SimpleChapter.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.feed;
+package de.danoeh.antennapod.parser.feed.element;
import de.danoeh.antennapod.model.feed.Chapter;
diff --git a/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SyndElement.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SyndElement.java
new file mode 100644
index 000000000..98dbe2801
--- /dev/null
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/element/SyndElement.java
@@ -0,0 +1,22 @@
+package de.danoeh.antennapod.parser.feed.element;
+
+import de.danoeh.antennapod.parser.feed.namespace.Namespace;
+
+/** Defines a XML Element that is pushed on the tagstack */
+public class SyndElement {
+ private final String name;
+ private final Namespace namespace;
+
+ public SyndElement(String name, Namespace namespace) {
+ this.name = name;
+ this.namespace = namespace;
+ }
+
+ public Namespace getNamespace() {
+ return namespace;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Atom.java
index b93f41771..ef802c355 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Atom.java
@@ -1,23 +1,21 @@
-package de.danoeh.antennapod.core.syndication.namespace.atom;
+package de.danoeh.antennapod.parser.feed.namespace;
import android.text.TextUtils;
import android.util.Log;
import de.danoeh.antennapod.model.feed.FeedFunding;
-import de.danoeh.antennapod.core.syndication.util.SyndStringUtils;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.AtomText;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
+import de.danoeh.antennapod.parser.feed.util.SyndStringUtils;
import org.xml.sax.Attributes;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-import de.danoeh.antennapod.core.syndication.namespace.NSITunes;
-import de.danoeh.antennapod.core.syndication.namespace.NSRSS20;
-import de.danoeh.antennapod.core.syndication.namespace.Namespace;
-import de.danoeh.antennapod.core.syndication.namespace.SyndElement;
-import de.danoeh.antennapod.core.syndication.util.SyndTypeUtils;
-import de.danoeh.antennapod.core.util.DateUtils;
-
-public class NSAtom extends Namespace {
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import de.danoeh.antennapod.parser.feed.util.SyndTypeUtils;
+
+public class Atom extends Namespace {
private static final String TAG = "NSAtom";
public static final String NSTAG = "atom";
public static final String NSURI = "http://www.w3.org/2005/Atom";
@@ -63,8 +61,8 @@ public class NSAtom extends Namespace {
private static final String isText = TITLE + "|" + CONTENT + "|"
+ SUBTITLE + "|" + SUMMARY;
- private static final String isFeed = FEED + "|" + NSRSS20.CHANNEL;
- private static final String isFeedItem = ENTRY + "|" + NSRSS20.ITEM;
+ private static final String isFeed = FEED + "|" + Rss20.CHANNEL;
+ private static final String isFeedItem = ENTRY + "|" + Rss20.ITEM;
@Override
public SyndElement handleElementStart(String localName, HandlerState state,
@@ -152,13 +150,13 @@ public class NSAtom extends Namespace {
public void handleElementEnd(String localName, HandlerState state) {
if (ENTRY.equals(localName)) {
if (state.getCurrentItem() != null &&
- state.getTempObjects().containsKey(NSITunes.DURATION)) {
+ state.getTempObjects().containsKey(Itunes.DURATION)) {
FeedItem currentItem = state.getCurrentItem();
if (currentItem.hasMedia()) {
- Integer duration = (Integer) state.getTempObjects().get(NSITunes.DURATION);
+ Integer duration = (Integer) state.getTempObjects().get(Itunes.DURATION);
currentItem.getMedia().setDuration(duration);
}
- state.getTempObjects().remove(NSITunes.DURATION);
+ state.getTempObjects().remove(Itunes.DURATION);
}
state.setCurrentItem(null);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSContent.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Content.java
index bedf377aa..3a7d5ac3a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSContent.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Content.java
@@ -1,10 +1,10 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
import org.xml.sax.Attributes;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-
-public class NSContent extends Namespace {
+public class Content extends Namespace {
public static final String NSTAG = "content";
public static final String NSURI = "http://purl.org/rss/1.0/modules/content/";
@@ -21,5 +21,4 @@ public class NSContent extends Namespace {
state.getCurrentItem().setDescriptionIfLonger(state.getContentBuf().toString());
}
}
-
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSDublinCore.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/DublinCore.java
index 0394b754a..003f72e9b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSDublinCore.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/DublinCore.java
@@ -1,12 +1,13 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
import org.xml.sax.Attributes;
import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-import de.danoeh.antennapod.core.util.DateUtils;
-public class NSDublinCore extends Namespace {
+public class DublinCore extends Namespace {
private static final String TAG = "NSDublinCore";
public static final String NSTAG = "dc";
public static final String NSURI = "http://purl.org/dc/elements/1.1/";
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Itunes.java
index 1dc8d8af3..5f47f8377 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Itunes.java
@@ -1,16 +1,17 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
import android.text.TextUtils;
import android.util.Log;
import androidx.core.text.HtmlCompat;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import de.danoeh.antennapod.parser.feed.util.DurationParser;
import org.xml.sax.Attributes;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-import de.danoeh.antennapod.core.syndication.parsers.DurationParser;
-public class NSITunes extends Namespace {
+public class Itunes extends Namespace {
public static final String NSTAG = "itunes";
public static final String NSURI = "http://www.itunes.com/dtds/podcast-1.0.dtd";
@@ -106,7 +107,7 @@ public class NSITunes extends Namespace {
if (state.getCurrentItem() != null) {
state.getCurrentItem().setDescriptionIfLonger(summary);
- } else if (NSRSS20.CHANNEL.equals(secondElementName) && state.getFeed() != null) {
+ } else if (Rss20.CHANNEL.equals(secondElementName) && state.getFeed() != null) {
state.getFeed().setDescription(summary);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Media.java
index 3dba0735d..f480a0417 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Media.java
@@ -1,19 +1,20 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
import android.text.TextUtils;
import android.util.Log;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
import org.xml.sax.Attributes;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-import de.danoeh.antennapod.core.syndication.namespace.atom.AtomText;
-import de.danoeh.antennapod.core.syndication.util.SyndTypeUtils;
+import de.danoeh.antennapod.parser.feed.element.AtomText;
+import de.danoeh.antennapod.parser.feed.util.SyndTypeUtils;
/** Processes tags from the http://search.yahoo.com/mrss/ namespace. */
-public class NSMedia extends Namespace {
+public class Media extends Namespace {
private static final String TAG = "NSMedia";
public static final String NSTAG = "media";
diff --git a/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Namespace.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Namespace.java
new file mode 100644
index 000000000..5273c6731
--- /dev/null
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Namespace.java
@@ -0,0 +1,19 @@
+package de.danoeh.antennapod.parser.feed.namespace;
+
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import org.xml.sax.Attributes;
+
+public abstract class Namespace {
+ public static final String NSTAG = null;
+ public static final String NSURI = null;
+
+ /** Called by a Feedhandler when in startElement and it detects a namespace element
+ * @return The SyndElement to push onto the stack
+ * */
+ public abstract SyndElement handleElementStart(String localName, HandlerState state, Attributes attributes);
+
+ /** Called by a Feedhandler when in endElement and it detects a namespace element
+ * */
+ public abstract void handleElementEnd(String localName, HandlerState state);
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/PodcastIndex.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/PodcastIndex.java
index ee150f839..1d4a91192 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/PodcastIndex.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/PodcastIndex.java
@@ -1,9 +1,10 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
import org.jsoup.helper.StringUtil;
import org.xml.sax.Attributes;
import de.danoeh.antennapod.model.feed.FeedFunding;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
public class PodcastIndex extends Namespace {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Rss20.java
index 50c2dc118..a49cd16dd 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/Rss20.java
@@ -1,21 +1,24 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
import android.text.TextUtils;
import android.util.Log;
-import de.danoeh.antennapod.core.syndication.util.SyndStringUtils;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
+import de.danoeh.antennapod.parser.feed.util.SyndStringUtils;
import org.xml.sax.Attributes;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-import de.danoeh.antennapod.core.syndication.util.SyndTypeUtils;
-import de.danoeh.antennapod.core.util.DateUtils;
+import de.danoeh.antennapod.parser.feed.util.SyndTypeUtils;
+
+import java.util.Locale;
/**
* SAX-Parser for reading RSS-Feeds.
*/
-public class NSRSS20 extends Namespace {
+public class Rss20 extends Namespace {
private static final String TAG = "NSRSS20";
@@ -85,12 +88,12 @@ public class NSRSS20 extends Namespace {
currentItem.setTitle(currentItem.getDescription());
}
- if (state.getTempObjects().containsKey(NSITunes.DURATION)) {
+ if (state.getTempObjects().containsKey(Itunes.DURATION)) {
if (currentItem.hasMedia()) {
- Integer duration = (Integer) state.getTempObjects().get(NSITunes.DURATION);
+ Integer duration = (Integer) state.getTempObjects().get(Itunes.DURATION);
currentItem.getMedia().setDuration(duration);
}
- state.getTempObjects().remove(NSITunes.DURATION);
+ state.getTempObjects().remove(Itunes.DURATION);
}
}
state.setCurrentItem(null);
@@ -137,7 +140,7 @@ public class NSRSS20 extends Namespace {
state.getCurrentItem().setDescriptionIfLonger(content);
}
} else if (LANGUAGE.equals(localName) && state.getFeed() != null) {
- state.getFeed().setLanguage(content.toLowerCase());
+ state.getFeed().setLanguage(content.toLowerCase(Locale.US));
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/SimpleChapters.java
index 97d0ebb53..e1912ed45 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSSimpleChapters.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/namespace/SimpleChapters.java
@@ -1,17 +1,18 @@
-package de.danoeh.antennapod.core.syndication.namespace;
+package de.danoeh.antennapod.parser.feed.namespace;
import android.util.Log;
+import de.danoeh.antennapod.parser.feed.HandlerState;
+import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
+import de.danoeh.antennapod.parser.feed.element.SyndElement;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
import org.xml.sax.Attributes;
import java.util.ArrayList;
import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.SimpleChapter;
-import de.danoeh.antennapod.core.syndication.handler.HandlerState;
-import de.danoeh.antennapod.core.util.DateUtils;
-public class NSSimpleChapters extends Namespace {
+public class SimpleChapters extends Namespace {
private static final String TAG = "NSSimpleChapters";
public static final String NSTAG = "psc|sc";
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/DateUtils.java
index a0b9fbef9..9b7f48769 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/DateUtils.java
@@ -1,17 +1,13 @@
-package de.danoeh.antennapod.core.util;
+package de.danoeh.antennapod.parser.feed.util;
-import android.content.Context;
import android.util.Log;
import androidx.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
-import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
-import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
@@ -20,7 +16,9 @@ import java.util.TimeZone;
*/
public class DateUtils {
- private DateUtils(){}
+ private DateUtils() {
+
+ }
private static final String TAG = "DateUtils";
private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT");
@@ -58,7 +56,8 @@ public class DateUtils {
// less than 4 decimal places: pad to have a consistent format for the parser
} else if (current - start < 4) {
if (current < date.length() - 1) {
- date = date.substring(0, current) + StringUtils.repeat("0", 4 - (current - start)) + date.substring(current);
+ date = date.substring(0, current) + StringUtils.repeat("0", 4 - (current - start))
+ + date.substring(current);
} else {
date = date.substring(0, current) + StringUtils.repeat("0", 4 - (current - start));
}
@@ -161,42 +160,4 @@ public class DateUtils {
}
return result;
}
-
- public static String formatRFC822Date(Date date) {
- SimpleDateFormat format = new SimpleDateFormat("dd MMM yy HH:mm:ss Z", Locale.US);
- return format.format(date);
- }
-
- public static String formatRFC3339Local(Date date) {
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
- return format.format(date);
- }
-
- public static String formatRFC3339UTC(Date date) {
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
- format.setTimeZone(defaultTimezone);
- return format.format(date);
- }
-
- public static String formatAbbrev(final Context context, final Date date) {
- if (date == null) {
- return "";
- }
- GregorianCalendar now = new GregorianCalendar();
- GregorianCalendar cal = new GregorianCalendar();
- cal.setTime(date);
- boolean withinLastYear = now.get(Calendar.YEAR) == cal.get(Calendar.YEAR);
- int format = android.text.format.DateUtils.FORMAT_ABBREV_ALL;
- if (withinLastYear) {
- format |= android.text.format.DateUtils.FORMAT_NO_YEAR;
- }
- return android.text.format.DateUtils.formatDateTime(context, date.getTime(), format);
- }
-
- public static String formatForAccessibility(final Context context, final Date date) {
- if (date == null) {
- return "";
- }
- return DateFormat.getDateInstance(DateFormat.LONG).format(date);
- }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/DurationParser.java
index 8b036c6a9..af79f542a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/DurationParser.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.syndication.parsers;
+package de.danoeh.antennapod.parser.feed.util;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndStringUtils.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/SyndStringUtils.java
index addcdd4b7..403d1671f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndStringUtils.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/SyndStringUtils.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.syndication.util;
+package de.danoeh.antennapod.parser.feed.util;
public class SyndStringUtils {
private SyndStringUtils() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/SyndTypeUtils.java
index 155673296..2e6cf864f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/util/SyndTypeUtils.java
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/SyndTypeUtils.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.syndication.util;
+package de.danoeh.antennapod.parser.feed.util;
import android.webkit.MimeTypeMap;
import org.apache.commons.io.FilenameUtils;
diff --git a/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/TypeGetter.java b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/TypeGetter.java
new file mode 100644
index 000000000..12834f94f
--- /dev/null
+++ b/parser/feed/src/main/java/de/danoeh/antennapod/parser/feed/util/TypeGetter.java
@@ -0,0 +1,121 @@
+package de.danoeh.antennapod.parser.feed.util;
+
+import android.util.Log;
+
+import de.danoeh.antennapod.parser.feed.UnsupportedFeedtypeException;
+import org.apache.commons.io.input.XmlStreamReader;
+import org.jsoup.Jsoup;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Reader;
+
+import de.danoeh.antennapod.model.feed.Feed;
+
+/** Gets the type of a specific feed by reading the root element. */
+public class TypeGetter {
+ private static final String TAG = "TypeGetter";
+
+ public enum Type {
+ RSS20, RSS091, ATOM, INVALID
+ }
+
+ private static final String ATOM_ROOT = "feed";
+ private static final String RSS_ROOT = "rss";
+
+ public Type getType(Feed feed) throws UnsupportedFeedtypeException {
+ XmlPullParserFactory factory;
+ if (feed.getFile_url() != null) {
+ Reader reader = null;
+ try {
+ factory = XmlPullParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ XmlPullParser xpp = factory.newPullParser();
+ reader = createReader(feed);
+ xpp.setInput(reader);
+ int eventType = xpp.getEventType();
+
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tag = xpp.getName();
+ switch (tag) {
+ case ATOM_ROOT:
+ feed.setType(Feed.TYPE_ATOM1);
+ Log.d(TAG, "Recognized type Atom");
+
+ String strLang = xpp.getAttributeValue("http://www.w3.org/XML/1998/namespace", "lang");
+ if (strLang != null) {
+ feed.setLanguage(strLang);
+ }
+
+ return Type.ATOM;
+ case RSS_ROOT:
+ String strVersion = xpp.getAttributeValue(null, "version");
+ if (strVersion == null) {
+ feed.setType(Feed.TYPE_RSS2);
+ Log.d(TAG, "Assuming type RSS 2.0");
+ return Type.RSS20;
+ } else if (strVersion.equals("2.0")) {
+ feed.setType(Feed.TYPE_RSS2);
+ Log.d(TAG, "Recognized type RSS 2.0");
+ return Type.RSS20;
+ } else if (strVersion.equals("0.91") || strVersion.equals("0.92")) {
+ Log.d(TAG, "Recognized type RSS 0.91/0.92");
+ return Type.RSS091;
+ }
+ throw new UnsupportedFeedtypeException("Unsupported rss version");
+ default:
+ Log.d(TAG, "Type is invalid");
+ throw new UnsupportedFeedtypeException(Type.INVALID, tag);
+ }
+ } else {
+ eventType = xpp.next();
+ }
+ }
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ // XML document might actually be a HTML document -> try to parse as HTML
+ String rootElement = null;
+ try {
+ if (Jsoup.parse(new File(feed.getFile_url()), null) != null) {
+ rootElement = "html";
+ }
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+ throw new UnsupportedFeedtypeException(Type.INVALID, rootElement);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ Log.d(TAG, "Type is invalid");
+ throw new UnsupportedFeedtypeException(Type.INVALID);
+ }
+
+ private Reader createReader(Feed feed) {
+ Reader reader;
+ try {
+ reader = new XmlStreamReader(new File(feed.getFile_url()));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ return reader;
+ }
+}
diff --git a/core/src/test/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomTextTest.java b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/element/AtomTextTest.java
index 6bc614364..2ec91ab1d 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomTextTest.java
+++ b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/element/AtomTextTest.java
@@ -1,5 +1,7 @@
-package de.danoeh.antennapod.core.syndication.namespace.atom;
+package de.danoeh.antennapod.parser.feed.element.element;
+import de.danoeh.antennapod.parser.feed.element.AtomText;
+import de.danoeh.antennapod.parser.feed.namespace.Atom;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -27,7 +29,7 @@ public class AtomTextTest {
@Test
public void testProcessingHtml() {
for (String[] pair : TEST_DATA) {
- final AtomText atomText = new AtomText("", new NSAtom(), AtomText.TYPE_HTML);
+ final AtomText atomText = new AtomText("", new Atom(), AtomText.TYPE_HTML);
atomText.setContent(pair[0]);
assertEquals(pair[1], atomText.getProcessedContent());
}
diff --git a/core/src/test/java/de/danoeh/antennapod/core/syndication/handler/AtomParserTest.java b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/AtomParserTest.java
index 36ca7f0d8..ba8aaf4f0 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/syndication/handler/AtomParserTest.java
+++ b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/AtomParserTest.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.syndication.handler;
+package de.danoeh.antennapod.parser.feed.element.namespace;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -12,9 +12,9 @@ import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
/**
* Tests for Atom feeds in FeedHandler.
diff --git a/core/src/test/java/de/danoeh/antennapod/core/syndication/handler/FeedParserTestHelper.java b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/FeedParserTestHelper.java
index b9318b377..5cc52d8cb 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/syndication/handler/FeedParserTestHelper.java
+++ b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/FeedParserTestHelper.java
@@ -1,10 +1,11 @@
-package de.danoeh.antennapod.core.syndication.handler;
+package de.danoeh.antennapod.parser.feed.element.namespace;
import androidx.annotation.NonNull;
import java.io.File;
import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.parser.feed.FeedHandler;
/**
* Tests for FeedHandler.
diff --git a/core/src/test/java/de/danoeh/antennapod/core/syndication/handler/RssParserTest.java b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/RssParserTest.java
index d95c8b3ab..8f8942d7b 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/syndication/handler/RssParserTest.java
+++ b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/namespace/RssParserTest.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.syndication.handler;
+package de.danoeh.antennapod.parser.feed.element.namespace;
import android.text.TextUtils;
import org.junit.Test;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/DateUtilsTest.java b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/util/DateUtilsTest.java
index 92888ae8b..1f039d703 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/util/DateUtilsTest.java
+++ b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/util/DateUtilsTest.java
@@ -1,5 +1,6 @@
-package de.danoeh.antennapod.core.util;
+package de.danoeh.antennapod.parser.feed.element.util;
+import de.danoeh.antennapod.parser.feed.util.DateUtils;
import org.junit.Test;
import java.util.Calendar;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/syndication/parsers/DurationParserTest.java b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/util/DurationParserTest.java
index e7c861969..91d9ea5ed 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/syndication/parsers/DurationParserTest.java
+++ b/parser/feed/src/test/java/de/danoeh/antennapod/parser/feed/element/util/DurationParserTest.java
@@ -1,5 +1,6 @@
-package de.danoeh.antennapod.core.syndication.parsers;
+package de.danoeh.antennapod.parser.feed.element.util;
+import de.danoeh.antennapod.parser.feed.util.DurationParser;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
diff --git a/core/src/test/resources/feed-atom-testAtomBasic.xml b/parser/feed/src/test/resources/feed-atom-testAtomBasic.xml
index cefc4f979..cefc4f979 100644
--- a/core/src/test/resources/feed-atom-testAtomBasic.xml
+++ b/parser/feed/src/test/resources/feed-atom-testAtomBasic.xml
diff --git a/core/src/test/resources/feed-atom-testEmptyRelLinks.xml b/parser/feed/src/test/resources/feed-atom-testEmptyRelLinks.xml
index 04c28ef67..04c28ef67 100644
--- a/core/src/test/resources/feed-atom-testEmptyRelLinks.xml
+++ b/parser/feed/src/test/resources/feed-atom-testEmptyRelLinks.xml
diff --git a/core/src/test/resources/feed-atom-testLogoWithWhitespace.xml b/parser/feed/src/test/resources/feed-atom-testLogoWithWhitespace.xml
index f4886d56a..f4886d56a 100644
--- a/core/src/test/resources/feed-atom-testLogoWithWhitespace.xml
+++ b/parser/feed/src/test/resources/feed-atom-testLogoWithWhitespace.xml
diff --git a/core/src/test/resources/feed-rss-testImageWithWhitespace.xml b/parser/feed/src/test/resources/feed-rss-testImageWithWhitespace.xml
index 2be9401d2..2be9401d2 100644
--- a/core/src/test/resources/feed-rss-testImageWithWhitespace.xml
+++ b/parser/feed/src/test/resources/feed-rss-testImageWithWhitespace.xml
diff --git a/core/src/test/resources/feed-rss-testMediaContentMime.xml b/parser/feed/src/test/resources/feed-rss-testMediaContentMime.xml
index a715abb37..a715abb37 100644
--- a/core/src/test/resources/feed-rss-testMediaContentMime.xml
+++ b/parser/feed/src/test/resources/feed-rss-testMediaContentMime.xml
diff --git a/core/src/test/resources/feed-rss-testMultipleFundingTags.xml b/parser/feed/src/test/resources/feed-rss-testMultipleFundingTags.xml
index 2535bda32..2535bda32 100644
--- a/core/src/test/resources/feed-rss-testMultipleFundingTags.xml
+++ b/parser/feed/src/test/resources/feed-rss-testMultipleFundingTags.xml
diff --git a/core/src/test/resources/feed-rss-testRss2Basic.xml b/parser/feed/src/test/resources/feed-rss-testRss2Basic.xml
index dd771b61a..dd771b61a 100644
--- a/core/src/test/resources/feed-rss-testRss2Basic.xml
+++ b/parser/feed/src/test/resources/feed-rss-testRss2Basic.xml
diff --git a/settings.gradle b/settings.gradle
index 27cc1a863..edf55858e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -6,6 +6,8 @@ include ':net:ssl'
include ':net:sync:gpoddernet'
include ':net:sync:model'
+include ':parser:feed'
+
include ':ui:app-start-intent'
include ':ui:common'
include ':ui:png-icons'