File indexing completed on 2024-12-01 03:45:40
0001 /* 0002 This file is part of the syndication library 0003 SPDX-FileCopyrightText: 2006 Frank Osterfeld <osterfeld@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "document.h" 0009 #include "atomtools.h" 0010 #include "category.h" 0011 #include "constants.h" 0012 #include "entry.h" 0013 #include "generator.h" 0014 #include "link.h" 0015 #include "person.h" 0016 0017 #include <documentvisitor.h> 0018 #include <tools.h> 0019 0020 #include <QDomElement> 0021 #include <QList> 0022 #include <QString> 0023 0024 #include <vector> 0025 0026 namespace Syndication 0027 { 0028 namespace Atom 0029 { 0030 FeedDocument::FeedDocument() 0031 : ElementWrapper() 0032 { 0033 } 0034 0035 FeedDocument::FeedDocument(const QDomElement &element) 0036 : ElementWrapper(element) 0037 { 0038 } 0039 0040 bool FeedDocument::accept(DocumentVisitor *visitor) 0041 { 0042 return visitor->visitAtomFeedDocument(this); 0043 } 0044 0045 QList<Person> FeedDocument::authors() const 0046 { 0047 const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("author")); 0048 QList<Person> list; 0049 list.reserve(a.count()); 0050 0051 std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) { 0052 return Person(element); 0053 }); 0054 0055 return list; 0056 } 0057 0058 QList<Person> FeedDocument::contributors() const 0059 { 0060 const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("contributor")); 0061 QList<Person> list; 0062 list.reserve(a.count()); 0063 0064 std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) { 0065 return Person(element); 0066 }); 0067 0068 return list; 0069 } 0070 0071 QList<Category> FeedDocument::categories() const 0072 { 0073 const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("category")); 0074 QList<Category> list; 0075 list.reserve(a.count()); 0076 0077 std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) { 0078 return Category(element); 0079 }); 0080 0081 return list; 0082 } 0083 0084 Generator FeedDocument::generator() const 0085 { 0086 return Generator(firstElementByTagNameNS(atom1Namespace(), QStringLiteral("generator"))); 0087 } 0088 0089 QString FeedDocument::icon() const 0090 { 0091 const QString iconPath = extractElementTextNS(atom1Namespace(), QStringLiteral("icon")); 0092 if (iconPath.isEmpty()) { 0093 return {}; 0094 } 0095 return completeURI(iconPath); 0096 } 0097 0098 QString FeedDocument::logo() const 0099 { 0100 return completeURI(extractElementTextNS(atom1Namespace(), QStringLiteral("logo"))); 0101 } 0102 0103 QString FeedDocument::id() const 0104 { 0105 return extractElementTextNS(atom1Namespace(), QStringLiteral("id")); 0106 } 0107 0108 QString FeedDocument::rights() const 0109 { 0110 return extractAtomText(*this, QStringLiteral("rights")); 0111 } 0112 0113 QString FeedDocument::title() const 0114 { 0115 return extractAtomText(*this, QStringLiteral("title")); 0116 } 0117 0118 QString FeedDocument::subtitle() const 0119 { 0120 return extractAtomText(*this, QStringLiteral("subtitle")); 0121 } 0122 0123 time_t FeedDocument::updated() const 0124 { 0125 QString upd = extractElementTextNS(atom1Namespace(), QStringLiteral("updated")); 0126 return parseDate(upd, ISODate); 0127 } 0128 0129 QList<Link> FeedDocument::links() const 0130 { 0131 const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("link")); 0132 QList<Link> list; 0133 list.reserve(a.count()); 0134 0135 std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) { 0136 return Link(element); 0137 }); 0138 0139 return list; 0140 } 0141 0142 QList<Entry> FeedDocument::entries() const 0143 { 0144 const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("entry")); 0145 QList<Entry> list; 0146 list.reserve(a.count()); 0147 0148 const QList<Person> feedAuthors = authors(); 0149 0150 std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [&feedAuthors](const QDomElement &element) { 0151 Entry entry(element); 0152 entry.setFeedAuthors(feedAuthors); 0153 return entry; 0154 }); 0155 0156 return list; 0157 } 0158 0159 QList<QDomElement> FeedDocument::unhandledElements() const 0160 { 0161 // TODO: do not hardcode this list here 0162 static std::vector<ElementType> handled; // QVector would require a default ctor, and ElementType is too big for QList 0163 if (handled.empty()) { 0164 handled.reserve(13); 0165 handled.push_back(ElementType(QStringLiteral("author"), atom1Namespace())); 0166 handled.push_back(ElementType(QStringLiteral("contributor"), atom1Namespace())); 0167 handled.push_back(ElementType(QStringLiteral("category"), atom1Namespace())); 0168 handled.push_back(ElementType(QStringLiteral("generator"), atom1Namespace())); 0169 handled.push_back(ElementType(QStringLiteral("icon"), atom1Namespace())); 0170 handled.push_back(ElementType(QStringLiteral("logo"), atom1Namespace())); 0171 handled.push_back(ElementType(QStringLiteral("id"), atom1Namespace())); 0172 handled.push_back(ElementType(QStringLiteral("rights"), atom1Namespace())); 0173 handled.push_back(ElementType(QStringLiteral("title"), atom1Namespace())); 0174 handled.push_back(ElementType(QStringLiteral("subtitle"), atom1Namespace())); 0175 handled.push_back(ElementType(QStringLiteral("updated"), atom1Namespace())); 0176 handled.push_back(ElementType(QStringLiteral("link"), atom1Namespace())); 0177 handled.push_back(ElementType(QStringLiteral("entry"), atom1Namespace())); 0178 } 0179 0180 QList<QDomElement> notHandled; 0181 0182 QDomNodeList children = element().childNodes(); 0183 const int numChildren = children.size(); 0184 for (int i = 0; i < numChildren; ++i) { 0185 QDomElement el = children.at(i).toElement(); 0186 if (!el.isNull() // 0187 && std::find(handled.cbegin(), handled.cend(), ElementType(el.localName(), el.namespaceURI())) == handled.cend()) { 0188 notHandled.append(el); 0189 } 0190 } 0191 0192 return notHandled; 0193 } 0194 0195 bool FeedDocument::isValid() const 0196 { 0197 return !isNull(); 0198 } 0199 0200 QString FeedDocument::debugInfo() const 0201 { 0202 QString info = QLatin1String("### FeedDocument: ###################\n"); 0203 if (!title().isEmpty()) { 0204 info += QLatin1String("title: #") + title() + QLatin1String("#\n"); 0205 } 0206 if (!subtitle().isEmpty()) { 0207 info += QLatin1String("subtitle: #") + subtitle() + QLatin1String("#\n"); 0208 } 0209 if (!id().isEmpty()) { 0210 info += QLatin1String("id: #") + id() + QLatin1String("#\n"); 0211 } 0212 0213 if (!rights().isEmpty()) { 0214 info += QLatin1String("rights: #") + rights() + QLatin1String("#\n"); 0215 } 0216 if (!icon().isEmpty()) { 0217 info += QLatin1String("icon: #") + icon() + QLatin1String("#\n"); 0218 } 0219 if (!logo().isEmpty()) { 0220 info += QLatin1String("logo: #") + logo() + QLatin1String("#\n"); 0221 } 0222 if (!generator().isNull()) { 0223 info += generator().debugInfo(); 0224 } 0225 0226 QString dupdated = dateTimeToString(updated()); 0227 if (!dupdated.isNull()) { 0228 info += QLatin1String("updated: #") + dupdated + QLatin1String("#\n"); 0229 } 0230 0231 const QList<Link> dlinks = links(); 0232 for (const auto &link : dlinks) { 0233 info += link.debugInfo(); 0234 } 0235 0236 const QList<Category> dcats = categories(); 0237 for (const auto &cat : dcats) { 0238 info += cat.debugInfo(); 0239 } 0240 0241 info += QLatin1String("### Authors: ###################\n"); 0242 0243 const QList<Person> dauthors = authors(); 0244 for (const auto &author : dauthors) { 0245 info += author.debugInfo(); 0246 } 0247 0248 info += QLatin1String("### Contributors: ###################\n"); 0249 0250 const QList<Person> dcontri = contributors(); 0251 for (const auto &person : dcontri) { 0252 info += person.debugInfo(); 0253 } 0254 0255 const QList<Entry> dentries = entries(); 0256 for (const auto &entry : dentries) { 0257 info += entry.debugInfo(); 0258 } 0259 0260 info += QLatin1String("### FeedDocument end ################\n"); 0261 0262 return info; 0263 } 0264 0265 EntryDocument::EntryDocument() 0266 : ElementWrapper() 0267 { 0268 } 0269 0270 EntryDocument::EntryDocument(const QDomElement &element) 0271 : ElementWrapper(element) 0272 { 0273 } 0274 0275 bool EntryDocument::accept(DocumentVisitor *visitor) 0276 { 0277 return visitor->visitAtomEntryDocument(this); 0278 } 0279 0280 Entry EntryDocument::entry() const 0281 { 0282 return Entry(element()); 0283 } 0284 0285 bool EntryDocument::isValid() const 0286 { 0287 return !isNull(); 0288 } 0289 0290 QString EntryDocument::debugInfo() const 0291 { 0292 QString info; 0293 info += QLatin1String("### EntryDocument: ##################\n"); 0294 0295 Entry dentry = entry(); 0296 if (!dentry.isNull()) { 0297 info += dentry.debugInfo(); 0298 } 0299 0300 info += QLatin1String("### EntryDocument end ###############\n"); 0301 return info; 0302 } 0303 0304 } // namespace Atom 0305 } // namespace Syndication