scala-news-reader
rss/atom news reader in scala
git clone https://9o.is/git/scala-news-reader.git
Feed.scala
(2803B)
1 package com.joereader.lib.rss
2
3 import com.sun.syndication.feed.synd._
4 import scala.collection.JavaConversions._
5 import scala.collection.SortedSet
6
7 /* An RSS Feed. */
8 case class Feed(name: String,
9 description: String,
10 imageUrl: Option[String],
11 writers: List[FeedAuthor],
12 entries: List[FeedEntry],
13 links: List[String])
14
15 object Feed {
16
17 def build(feed: SyndFeed, links: List[String]) = {
18
19 val entries = FeedEntry.build(feed.getEntries.
20 asInstanceOf[java.util.List[SyndEntry]].toList)
21
22 def image =
23 if (feed.getImage != null)
24 Some(feed.getImage.getUrl)
25 else None
26
27 Feed(
28 feed.getTitle,
29 feed.getDescription,
30 image,
31 entries.map(_.author).distinct,
32 entries,
33 links)
34 }
35
36 def empty = Feed("", "", None, Nil, Nil, Nil)
37
38 /**
39 * Merges multiple feeds into one. If any feed contains one entry with same
40 * title and date from an entry of another feed, the second feed will be
41 * ignored.
42 * @param feeds the feeds to merge
43 * @return one merged feed
44 */
45 def merge(feeds: List[Feed]): Feed =
46 if (feeds.nonEmpty) {
47
48 def name(feeds: List[Feed]): String = {
49 if (feeds.isEmpty) ""
50 else if (!feeds.head.name.isEmpty) feeds.head.name
51 else name(feeds.tail)
52 }
53
54 def description(feeds: List[Feed]): String = {
55 if (feeds.isEmpty) ""
56 else if (!feeds.head.description.isEmpty) feeds.head.description
57 else description(feeds.tail)
58 }
59
60 def imageUrl(feeds: List[Feed]): Option[String] = {
61 if (feeds.isEmpty) None
62 else if (feeds.head.imageUrl.isDefined) feeds.head.imageUrl
63 else imageUrl(feeds.tail)
64 }
65
66 var _writers = feeds.head.writers
67 var _entries: List[FeedEntry] = Nil
68 var _links: List[String] = Nil
69
70 for (f <- 0 until feeds.size) {
71 var repeat = false
72 for (entry1 <- feeds(f).entries)
73 for (entry2 <- _entries)
74 if (entry1.title == entry2.title &&
75 entry1.date.compareTo(entry2.date) == 0) repeat = true
76
77 if (!repeat) {
78 _writers = _writers ::: feeds(f).writers
79 _entries = _entries ::: feeds(f).entries
80 _links = _links ::: feeds(f).links
81 }
82 }
83
84 // remove any repeated values
85 _links = SortedSet(_links: _*).toList
86 _writers = SortedSet(_writers: _*)(FeedAuthorOrdering).toList
87
88 Feed(
89 name(feeds),
90 description(feeds),
91 imageUrl(feeds),
92 _writers,
93 _entries,
94 _links)
95
96 } else Feed.empty
97 }
98
99 case class FeedImage(src: String)
100
101 case class FeedAuthor(name: String, imgUrl: Option[String] = None)
102
103 private object FeedAuthorOrdering extends Ordering[FeedAuthor] {
104 def compare(a: FeedAuthor, b: FeedAuthor) = a.name compare b.name
105 }