1 | /* |
2 | This file is part of the syndication library |
3 | SPDX-FileCopyrightText: 2006 Frank Osterfeld <osterfeld@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "entry.h" |
9 | #include "atomtools.h" |
10 | #include "category.h" |
11 | #include "constants.h" |
12 | #include "content.h" |
13 | #include "link.h" |
14 | #include "person.h" |
15 | #include "source.h" |
16 | |
17 | #include <specificitemvisitor.h> |
18 | #include <tools.h> |
19 | |
20 | #include <QDomElement> |
21 | #include <QString> |
22 | |
23 | #include <vector> |
24 | |
25 | namespace Syndication |
26 | { |
27 | namespace Atom |
28 | { |
29 | Entry::Entry() |
30 | : ElementWrapper() |
31 | { |
32 | } |
33 | |
34 | Entry::Entry(const QDomElement &element) |
35 | : ElementWrapper(element) |
36 | { |
37 | } |
38 | |
39 | void Entry::setFeedAuthors(const QList<Person> &feedAuthors) |
40 | { |
41 | m_feedAuthors = feedAuthors; |
42 | } |
43 | |
44 | QList<Person> Entry::authors() const |
45 | { |
46 | const QList<QDomElement> a = elementsByTagNameNS(nsURI: atom1Namespace(), QStringLiteral("author" )); |
47 | QList<Person> list; |
48 | |
49 | if (!a.isEmpty()) { |
50 | list.reserve(asize: a.count()); |
51 | |
52 | std::transform(first: a.cbegin(), last: a.cend(), result: std::back_inserter(x&: list), unary_op: [](const QDomElement &element) { |
53 | return Person(element); |
54 | }); |
55 | } else { |
56 | list = source().authors(); |
57 | } |
58 | |
59 | return !list.isEmpty() ? list : m_feedAuthors; |
60 | } |
61 | |
62 | QList<Person> Entry::contributors() const |
63 | { |
64 | const QList<QDomElement> a = elementsByTagNameNS(nsURI: atom1Namespace(), QStringLiteral("contributor" )); |
65 | QList<Person> list; |
66 | list.reserve(asize: a.count()); |
67 | |
68 | std::transform(first: a.cbegin(), last: a.cend(), result: std::back_inserter(x&: list), unary_op: [](const QDomElement &element) { |
69 | return Person(element); |
70 | }); |
71 | |
72 | return list; |
73 | } |
74 | |
75 | QList<Category> Entry::categories() const |
76 | { |
77 | const QList<QDomElement> a = elementsByTagNameNS(nsURI: atom1Namespace(), QStringLiteral("category" )); |
78 | QList<Category> list; |
79 | list.reserve(asize: a.count()); |
80 | |
81 | std::transform(first: a.cbegin(), last: a.cend(), result: std::back_inserter(x&: list), unary_op: [](const QDomElement &element) { |
82 | return Category(element); |
83 | }); |
84 | |
85 | return list; |
86 | } |
87 | |
88 | QString Entry::id() const |
89 | { |
90 | return extractElementTextNS(namespaceURI: atom1Namespace(), QStringLiteral("id" )); |
91 | } |
92 | |
93 | QList<Link> Entry::links() const |
94 | { |
95 | const QList<QDomElement> a = elementsByTagNameNS(nsURI: atom1Namespace(), QStringLiteral("link" )); |
96 | QList<Link> list; |
97 | list.reserve(asize: a.count()); |
98 | |
99 | std::transform(first: a.cbegin(), last: a.cend(), result: std::back_inserter(x&: list), unary_op: [](const QDomElement &element) { |
100 | return Link(element); |
101 | }); |
102 | |
103 | return list; |
104 | } |
105 | |
106 | QString Entry::rights() const |
107 | { |
108 | return extractAtomText(parent: *this, QStringLiteral("rights" )); |
109 | } |
110 | |
111 | Source Entry::source() const |
112 | { |
113 | return Source(firstElementByTagNameNS(nsURI: atom1Namespace(), QStringLiteral("source" ))); |
114 | } |
115 | |
116 | time_t Entry::published() const |
117 | { |
118 | QString pub = extractElementTextNS(namespaceURI: atom1Namespace(), QStringLiteral("published" )); |
119 | return parseDate(str: pub, hint: ISODate); |
120 | } |
121 | |
122 | time_t Entry::updated() const |
123 | { |
124 | QString upd = extractElementTextNS(namespaceURI: atom1Namespace(), QStringLiteral("updated" )); |
125 | return parseDate(str: upd, hint: ISODate); |
126 | } |
127 | |
128 | QString Entry::summary() const |
129 | { |
130 | return extractAtomText(parent: *this, QStringLiteral("summary" )); |
131 | } |
132 | |
133 | QString Entry::title() const |
134 | { |
135 | return extractAtomText(parent: *this, QStringLiteral("title" )); |
136 | } |
137 | |
138 | Content Entry::content() const |
139 | { |
140 | return Content(firstElementByTagNameNS(nsURI: atom1Namespace(), QStringLiteral("content" ))); |
141 | } |
142 | |
143 | QList<QDomElement> Entry::unhandledElements() const |
144 | { |
145 | // TODO: do not hardcode this list here |
146 | static std::vector<ElementType> handled; // QVector would require a default ctor, and ElementType is too big for QList |
147 | if (handled.empty()) { |
148 | handled.reserve(n: 12); |
149 | handled.push_back(x: ElementType(QStringLiteral("author" ), atom1Namespace())); |
150 | handled.push_back(x: ElementType(QStringLiteral("contributor" ), atom1Namespace())); |
151 | handled.push_back(x: ElementType(QStringLiteral("category" ), atom1Namespace())); |
152 | handled.push_back(x: ElementType(QStringLiteral("id" ), atom1Namespace())); |
153 | handled.push_back(x: ElementType(QStringLiteral("link" ), atom1Namespace())); |
154 | handled.push_back(x: ElementType(QStringLiteral("rights" ), atom1Namespace())); |
155 | handled.push_back(x: ElementType(QStringLiteral("source" ), atom1Namespace())); |
156 | handled.push_back(x: ElementType(QStringLiteral("published" ), atom1Namespace())); |
157 | handled.push_back(x: ElementType(QStringLiteral("updated" ), atom1Namespace())); |
158 | handled.push_back(x: ElementType(QStringLiteral("summary" ), atom1Namespace())); |
159 | handled.push_back(x: ElementType(QStringLiteral("title" ), atom1Namespace())); |
160 | handled.push_back(x: ElementType(QStringLiteral("content" ), atom1Namespace())); |
161 | } |
162 | |
163 | QList<QDomElement> notHandled; |
164 | |
165 | QDomNodeList children = element().childNodes(); |
166 | const int numChildren = children.size(); |
167 | for (int i = 0; i < numChildren; ++i) { |
168 | QDomElement el = children.at(index: i).toElement(); |
169 | if (!el.isNull() // |
170 | && std::find(first: handled.cbegin(), last: handled.cend(), val: ElementType(el.localName(), el.namespaceURI())) == handled.cend()) { |
171 | notHandled.append(t: el); |
172 | } |
173 | } |
174 | |
175 | return notHandled; |
176 | } |
177 | |
178 | QString Entry::debugInfo() const |
179 | { |
180 | QString info; |
181 | info += QLatin1String("### Entry: ###################\n" ); |
182 | if (!title().isEmpty()) { |
183 | info += QLatin1String("title: #" ) + title() + QLatin1String("#\n" ); |
184 | } |
185 | if (!summary().isEmpty()) { |
186 | info += QLatin1String("summary: #" ) + summary() + QLatin1String("#\n" ); |
187 | } |
188 | if (!id().isEmpty()) { |
189 | info += QLatin1String("id: #" ) + id() + QLatin1String("#\n" ); |
190 | } |
191 | if (!content().isNull()) { |
192 | info += content().debugInfo(); |
193 | } |
194 | |
195 | if (!rights().isEmpty()) { |
196 | info += QLatin1String("rights: #" ) + rights() + QLatin1String("#\n" ); |
197 | } |
198 | |
199 | QString dupdated = dateTimeToString(date: updated()); |
200 | if (!dupdated.isNull()) { |
201 | info += QLatin1String("updated: #" ) + dupdated + QLatin1String("#\n" ); |
202 | } |
203 | |
204 | QString dpublished = dateTimeToString(date: published()); |
205 | if (!dpublished.isNull()) { |
206 | info += QLatin1String("published: #" ) + dpublished + QLatin1String("#\n" ); |
207 | } |
208 | |
209 | const QList<Link> dlinks = links(); |
210 | for (const auto &link : dlinks) { |
211 | info += link.debugInfo(); |
212 | } |
213 | |
214 | const QList<Category> dcats = categories(); |
215 | for (const auto &cat : dcats) { |
216 | info += cat.debugInfo(); |
217 | } |
218 | |
219 | info += QLatin1String("### Authors: ###################\n" ); |
220 | |
221 | const QList<Person> dauthors = authors(); |
222 | for (const auto &author : dauthors) { |
223 | info += author.debugInfo(); |
224 | } |
225 | |
226 | info += QLatin1String("### Contributors: ###################\n" ); |
227 | |
228 | const QList<Person> dcontri = contributors(); |
229 | for (const auto &person : dcontri) { |
230 | info += person.debugInfo(); |
231 | } |
232 | |
233 | if (!source().isNull()) { |
234 | info += source().debugInfo(); |
235 | } |
236 | |
237 | info += QLatin1String("### Entry end ################\n" ); |
238 | |
239 | return info; |
240 | } |
241 | |
242 | bool Entry::accept(SpecificItemVisitor *visitor) |
243 | { |
244 | return visitor->visitAtomEntry(item: this); |
245 | } |
246 | |
247 | } // namespace Atom |
248 | } // namespace Syndication |
249 | |