Skip to content

Commit

Permalink
Merge pull request #140 from w3stling/support-for-multiple-enclosures
Browse files Browse the repository at this point in the history
Support for multiple enclosures
  • Loading branch information
w3stling authored Feb 2, 2024
2 parents 16bf235 + d76e48a commit 3bf20e3
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public abstract class AbstractRssReader<C extends Channel, I extends Item> {
private final Map<String, String> headers = new HashMap<>();
private final HashMap<String, BiConsumer<C, String>> channelTags = new HashMap<>();
private final HashMap<String, Map<String, BiConsumer<C, String>>> channelAttributes = new HashMap<>();
private final HashMap<String, Consumer<I>> onItemTags = new HashMap<>();
private final HashMap<String, BiConsumer<I, String>> itemTags = new HashMap<>();
private final HashMap<String, Map<String, BiConsumer<I, String>>> itemAttributes = new HashMap<>();
private final Set<String> collectChildNodesForTag = Set.of("content", "summary");
Expand Down Expand Up @@ -204,6 +205,8 @@ protected void registerItemTags() {
itemTags.putIfAbsent("comments", Item::setComments);
itemTags.putIfAbsent("dc:creator", (i, v) -> Mapper.mapIfEmpty(v, i::getAuthor, i::setAuthor));
itemTags.putIfAbsent("dc:date", (i, v) -> Mapper.mapIfEmpty(v, i::getPubDate, i::setPubDate));

onItemTags.put("enclosure", (i) -> i.addEnclosure(new Enclosure()));
}

/**
Expand All @@ -214,9 +217,9 @@ protected void registerItemAttributes() {
itemAttributes.computeIfAbsent("guid", k -> new HashMap<>()).putIfAbsent("isPermaLink", (i, v) -> i.setIsPermaLink(Boolean.parseBoolean(v)) );

var enclosureAttributes = itemAttributes.computeIfAbsent("enclosure", k -> new HashMap<>());
enclosureAttributes.putIfAbsent("url", (i, v) -> createIfNull(i::getEnclosure, i::setEnclosure, Enclosure::new).setUrl(v));
enclosureAttributes.putIfAbsent("type", (i, v) -> createIfNull(i::getEnclosure, i::setEnclosure, Enclosure::new).setType(v));
enclosureAttributes.putIfAbsent("length", (i, v) -> createIfNullOptional(i::getEnclosure, i::setEnclosure, Enclosure::new).ifPresent(e -> mapLong(v, e::setLength)));
enclosureAttributes.putIfAbsent("url", (i, v) -> i.getEnclosure().ifPresent(a -> a.setUrl(v)));
enclosureAttributes.putIfAbsent("type", (i, v) -> i.getEnclosure().ifPresent(a -> a.setType(v)));
enclosureAttributes.putIfAbsent("length", (i, v) -> i.getEnclosure().ifPresent(e -> mapLong(v, e::setLength)));
}

/**
Expand Down Expand Up @@ -671,6 +674,8 @@ void parseAttributes() {
mapChannelAttributes(elementFullPath);
}
else if (isItemPart) {
onItemTags.computeIfPresent(nsTagName, (k, f) -> { f.accept(item); return f; });
onItemTags.computeIfPresent(getElementFullPath(), (k, f) -> { f.accept(item); return f; });
// Map item attributes
mapItemAttributes(nsTagName);
mapItemAttributes(elementFullPath);
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/com/apptasticsoftware/rssreader/Item.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class Item implements Comparable<Item> {
private String pubDate;
private String comments;
private Enclosure enclosure;
private final List<Enclosure> enclosures = new ArrayList<>();
private Channel channel;
private final DateTimeParser dateTimeParser;

Expand Down Expand Up @@ -288,7 +289,25 @@ public Optional<Enclosure> getEnclosure() {
* @param enclosure enclosure
*/
public void setEnclosure(Enclosure enclosure) {
addEnclosure(enclosure);
}

/**
* Get enclosures for item.
* Use this method if multiple enclosures exist per item.
* @return list of enclosures
*/
public List<Enclosure> getEnclosures() {
return Collections.unmodifiableList(enclosures);
}

/**
* Add enclosure for item.
* @param enclosure enclosure
*/
public void addEnclosure(Enclosure enclosure) {
this.enclosure = enclosure;
enclosures.add(enclosure);
}

/**
Expand Down Expand Up @@ -323,14 +342,14 @@ public boolean equals(Object o) {
Objects.equals(getIsPermaLink(), item.getIsPermaLink()) &&
Objects.equals(getPubDate(), item.getPubDate()) &&
Objects.equals(getComments(), item.getComments()) &&
Objects.equals(getEnclosure(), item.getEnclosure()) &&
getEnclosures().equals(item.getEnclosures()) &&
Objects.equals(getChannel(), item.getChannel());
}

@Override
public int hashCode() {
return Objects.hash(getTitle(), getDescription(), getLink(), getAuthor(), getCategories(),
getGuid(), getIsPermaLink(), getPubDate(), getComments(), getEnclosure(), getChannel());
getGuid(), getIsPermaLink(), getPubDate(), getComments(), getEnclosures(), getChannel());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,33 @@ void testMultipleCategories() {
assertTrue(item.getCategory().isPresent());
}

@Test
void testMultipleEnclosures() {
var list = new RssReader().read(fromFile("multiple-enclosures.xml")).collect(Collectors.toList());

assertEquals(2, list.size());
var item = list.get(0);
assertEquals(3, item.getEnclosures().size());
assertEquals("https://url1", item.getEnclosures().get(0).getUrl());
assertEquals("image/jpeg", item.getEnclosures().get(0).getType());
assertEquals(1L, item.getEnclosures().get(0).getLength().orElse(-1L));
assertEquals("https://url2", item.getEnclosures().get(1).getUrl());
assertEquals("image/png", item.getEnclosures().get(1).getType());
assertEquals(2L, item.getEnclosures().get(1).getLength().orElse(-1L));
assertEquals("https://url3", item.getEnclosures().get(2).getUrl());
assertEquals("image/gif", item.getEnclosures().get(2).getType());
assertEquals(3L, item.getEnclosures().get(2).getLength().orElse(-1L));

item = list.get(1);
assertEquals(2, item.getEnclosures().size());
assertEquals("https://url4", item.getEnclosures().get(0).getUrl());
assertEquals("image/svg", item.getEnclosures().get(0).getType());
assertEquals(4L, item.getEnclosures().get(0).getLength().orElse(-1L));
assertEquals("https://url5", item.getEnclosures().get(1).getUrl());
assertEquals("image/webp", item.getEnclosures().get(1).getType());
assertEquals(5L, item.getEnclosures().get(1).getLength().orElse(-1L));
}

@Test
void testImageBadWidthHeight() {
var list = new RssReader().read(fromFile("bad-image-width-height.xml")).collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ void enclosureEqualsTest() {
@Test
void equalsContract() {
EqualsVerifier.simple().forClass(Channel.class).withIgnoredFields("dateTimeParser").withIgnoredFields("category").withNonnullFields("categories").verify();
EqualsVerifier.simple().forClass(Item.class).withIgnoredFields("defaultComparator").withIgnoredFields("dateTimeParser").withIgnoredFields("category").withNonnullFields("categories").verify();
EqualsVerifier.simple().forClass(Item.class).withIgnoredFields("defaultComparator").withIgnoredFields("dateTimeParser").withIgnoredFields("category").withNonnullFields("categories").withIgnoredFields("enclosure").withNonnullFields("enclosures").verify();
EqualsVerifier.simple().forClass(Enclosure.class).verify();
EqualsVerifier.simple().forClass(Image.class).verify();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void readItunesPodcastFeed2() throws IOException {
@Test
void equalsContract() {
EqualsVerifier.simple().forClass(ItunesChannel.class).withIgnoredFields("dateTimeParser").withIgnoredFields("category").withNonnullFields("categories").withNonnullFields("itunesCategories").verify();
EqualsVerifier.simple().forClass(ItunesItem.class).withIgnoredFields("defaultComparator").withIgnoredFields("dateTimeParser").withIgnoredFields("category").withNonnullFields("categories").verify();
EqualsVerifier.simple().forClass(ItunesItem.class).withIgnoredFields("defaultComparator").withIgnoredFields("dateTimeParser").withIgnoredFields("category").withNonnullFields("categories").withIgnoredFields("enclosure").withNonnullFields("enclosures").verify();
EqualsVerifier.simple().forClass(ItunesOwner.class).verify();
}

Expand Down
39 changes: 39 additions & 0 deletions src/test/resources/multiple-enclosures.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://worldoftanks.eu/static/5.132.2_d0fd33/portalnews/css/rss.xsl" media="screen"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="https://worldoftanks.eu/en/news/" rel="self" type="application/rss+xml" />
<title>World of Tanks News | World of Tanks</title>
<link>https://worldoftanks.eu/en/news/</link>
<description>The latest news, updates, specials, and events for World of Tanks, the team-based, MMO tank battle game from Wargaming. Everything about WoT in one place.</description>
<language>en</language>
<pubDate>Fri, 02 Feb 2024 11:05:26 GMT</pubDate>
<image>
<url>https://worldoftanks.eu/static/5.132.2_d0fd33/portalnews/img/news.png</url>
<title>World of Tanks News | World of Tanks</title>
<link>https://worldoftanks.eu/en/news/</link>
</image>
<item>
<title>A Warrior&#39;s Path: Unleash the Power of Japanese Tanks With Special Bundles!</title>
<link>https://worldoftanks.eu/en/news/specials/a-warriors-path-sale-feb-2024/</link>
<description>Embark on an epic journey with the A Warrior's Path event, featuring exclusive bundle sales for the newly introduced Japanese heavy tanks.</description>
<guid isPermaLink="true">https://worldoftanks.eu/en/news/specials/a-warriors-path-sale-feb-2024/</guid>
<pubDate>Thu, 01 Feb 2024 09:00:00 GMT</pubDate>
<category>Specials</category>
<enclosure url="https://url1" length="1" type="image/jpeg" />
<enclosure url="https://url2" length="2" type="image/png" />
<enclosure url="https://url3" length="3" type="image/gif" />
</item>
<item>
<title>WoT Monthly: Valentine&#39;s Day and More in February 2024</title>
<link>https://worldoftanks.eu/en/news/general-news/wot-monthly-february-2024/</link>
<description>A quick look at World of Tanks events during the month of love!</description>
<guid isPermaLink="true">https://worldoftanks.eu/en/news/general-news/wot-monthly-february-2024/</guid>
<pubDate>Wed, 31 Jan 2024 14:00:00 GMT</pubDate>
<category>General News</category>
<enclosure url="https://url4" length="4" type="image/svg" />
<enclosure url="https://url5" length="5" type="image/webp" />
</item>

</channel>
</rss>

0 comments on commit 3bf20e3

Please sign in to comment.