Line data Source code
1 : #include "BatchNewsParser.h"
2 : #include "NewsParser.h"
3 : #include "../utilities/FangLogging.h"
4 :
5 82 : BatchNewsParser::BatchNewsParser(QObject *parent)
6 82 : : FangObject{parent}
7 82 : {}
8 :
9 13 : void BatchNewsParser::parse(const QList<QUrl> &urls)
10 : {
11 : // Clear any existing parsers and results, in case this object is being reused.
12 13 : parsers.clear();
13 13 : results.clear();
14 :
15 : // Clear feed map as the pointers are no longer valid (they were owned by parsers.)
16 13 : feeds.clear();
17 :
18 : // Set up parsers.
19 33 : for (const QUrl& url : urls) {
20 : // Skip this URL if we've already seen it.
21 20 : if (parsers.count(url) > 0) {
22 2 : continue;
23 : }
24 :
25 18 : auto parser = createParser();
26 18 : connect(parser.get(), &ParserInterface::done, this, &BatchNewsParser::onParserDone);
27 18 : parser->parse(url);
28 18 : parsers[url] = std::move(parser);
29 18 : }
30 13 : }
31 :
32 0 : std::unique_ptr<ParserInterface> BatchNewsParser::createParser()
33 : {
34 0 : return std::make_unique<NewsParser>();
35 : }
36 :
37 18 : void BatchNewsParser::onParserDone()
38 : {
39 18 : ParserInterface* parser = qobject_cast<ParserInterface*>(sender());
40 18 : if (!parser) {
41 0 : qCWarning(logParser) << "BatchNewsParser: onParserDone called but sender is not a ParserInterface";
42 0 : return;
43 : }
44 :
45 : // Find the original request URL by matching the parser pointer, since
46 : // parser->getURL() may differ from the request URL after redirects.
47 18 : QUrl requestUrl;
48 28 : for (auto it = parsers.cbegin(); it != parsers.cend(); ++it) {
49 28 : if (it->second.get() == parser) {
50 18 : requestUrl = it->first;
51 18 : break;
52 : }
53 : }
54 :
55 18 : if (requestUrl.isEmpty()) {
56 0 : qCWarning(logParser) << "BatchNewsParser: parser finished but not found in map:" << parser->getURL();
57 0 : return;
58 : }
59 :
60 : // Store result under the original request URL.
61 18 : results[requestUrl] = parser->getResult();
62 :
63 : // Store feed if parser succeeded.
64 18 : if (parser->getResult() == ParserInterface::OK) {
65 12 : RawFeed* feed = parser->getFeed();
66 12 : if (feed) {
67 : // Store reference to the feed (owned by the parser)
68 12 : feeds[requestUrl] = feed;
69 : }
70 : }
71 :
72 : // Check if we're done.
73 56 : for (auto it = parsers.cbegin(); it != parsers.cend(); ++it) {
74 38 : if (it->second->getResult() == ParserInterface::IN_PROGRESS) {
75 : // Not done yet!
76 0 : return;
77 : }
78 : }
79 :
80 : // We're done!
81 18 : emit ready();
82 18 : }
83 :
84 15 : RawFeed* BatchNewsParser::getFeed(const QUrl& url)
85 : {
86 15 : return feeds.value(url, nullptr);
87 : }
|