File indexing completed on 2024-04-14 03:58:25

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 "entry.h"
0009 #include "atomtools.h"
0010 #include "category.h"
0011 #include "constants.h"
0012 #include "content.h"
0013 #include "link.h"
0014 #include "person.h"
0015 #include "source.h"
0016 
0017 #include <specificitemvisitor.h>
0018 #include <tools.h>
0019 
0020 #include <QDomElement>
0021 #include <QString>
0022 
0023 #include <vector>
0024 
0025 namespace Syndication
0026 {
0027 namespace Atom
0028 {
0029 Entry::Entry()
0030     : ElementWrapper()
0031 {
0032 }
0033 
0034 Entry::Entry(const QDomElement &element)
0035     : ElementWrapper(element)
0036 {
0037 }
0038 
0039 void Entry::setFeedAuthors(const QList<Person> &feedAuthors)
0040 {
0041     m_feedAuthors = feedAuthors;
0042 }
0043 
0044 QList<Person> Entry::authors() const
0045 {
0046     const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("author"));
0047     QList<Person> list;
0048 
0049     if (!a.isEmpty()) {
0050         list.reserve(a.count());
0051 
0052         std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) {
0053             return Person(element);
0054         });
0055     } else {
0056         list = source().authors();
0057     }
0058 
0059     return !list.isEmpty() ? list : m_feedAuthors;
0060 }
0061 
0062 QList<Person> Entry::contributors() const
0063 {
0064     const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("contributor"));
0065     QList<Person> list;
0066     list.reserve(a.count());
0067 
0068     std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) {
0069         return Person(element);
0070     });
0071 
0072     return list;
0073 }
0074 
0075 QList<Category> Entry::categories() const
0076 {
0077     const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("category"));
0078     QList<Category> list;
0079     list.reserve(a.count());
0080 
0081     std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) {
0082         return Category(element);
0083     });
0084 
0085     return list;
0086 }
0087 
0088 QString Entry::id() const
0089 {
0090     return extractElementTextNS(atom1Namespace(), QStringLiteral("id"));
0091 }
0092 
0093 QList<Link> Entry::links() const
0094 {
0095     const QList<QDomElement> a = elementsByTagNameNS(atom1Namespace(), QStringLiteral("link"));
0096     QList<Link> list;
0097     list.reserve(a.count());
0098 
0099     std::transform(a.cbegin(), a.cend(), std::back_inserter(list), [](const QDomElement &element) {
0100         return Link(element);
0101     });
0102 
0103     return list;
0104 }
0105 
0106 QString Entry::rights() const
0107 {
0108     return extractAtomText(*this, QStringLiteral("rights"));
0109 }
0110 
0111 Source Entry::source() const
0112 {
0113     return Source(firstElementByTagNameNS(atom1Namespace(), QStringLiteral("source")));
0114 }
0115 
0116 time_t Entry::published() const
0117 {
0118     QString pub = extractElementTextNS(atom1Namespace(), QStringLiteral("published"));
0119     return parseDate(pub, ISODate);
0120 }
0121 
0122 time_t Entry::updated() const
0123 {
0124     QString upd = extractElementTextNS(atom1Namespace(), QStringLiteral("updated"));
0125     return parseDate(upd, ISODate);
0126 }
0127 
0128 QString Entry::summary() const
0129 {
0130     return extractAtomText(*this, QStringLiteral("summary"));
0131 }
0132 
0133 QString Entry::title() const
0134 {
0135     return extractAtomText(*this, QStringLiteral("title"));
0136 }
0137 
0138 Content Entry::content() const
0139 {
0140     return Content(firstElementByTagNameNS(atom1Namespace(), QStringLiteral("content")));
0141 }
0142 
0143 QList<QDomElement> Entry::unhandledElements() const
0144 {
0145     // TODO: do not hardcode this list here
0146     static std::vector<ElementType> handled; // QVector would require a default ctor, and ElementType is too big for QList
0147     if (handled.empty()) {
0148         handled.reserve(12);
0149         handled.push_back(ElementType(QStringLiteral("author"), atom1Namespace()));
0150         handled.push_back(ElementType(QStringLiteral("contributor"), atom1Namespace()));
0151         handled.push_back(ElementType(QStringLiteral("category"), atom1Namespace()));
0152         handled.push_back(ElementType(QStringLiteral("id"), atom1Namespace()));
0153         handled.push_back(ElementType(QStringLiteral("link"), atom1Namespace()));
0154         handled.push_back(ElementType(QStringLiteral("rights"), atom1Namespace()));
0155         handled.push_back(ElementType(QStringLiteral("source"), atom1Namespace()));
0156         handled.push_back(ElementType(QStringLiteral("published"), atom1Namespace()));
0157         handled.push_back(ElementType(QStringLiteral("updated"), atom1Namespace()));
0158         handled.push_back(ElementType(QStringLiteral("summary"), atom1Namespace()));
0159         handled.push_back(ElementType(QStringLiteral("title"), atom1Namespace()));
0160         handled.push_back(ElementType(QStringLiteral("content"), atom1Namespace()));
0161     }
0162 
0163     QList<QDomElement> notHandled;
0164 
0165     QDomNodeList children = element().childNodes();
0166     const int numChildren = children.size();
0167     for (int i = 0; i < numChildren; ++i) {
0168         QDomElement el = children.at(i).toElement();
0169         if (!el.isNull() //
0170             && std::find(handled.cbegin(), handled.cend(), ElementType(el.localName(), el.namespaceURI())) == handled.cend()) {
0171             notHandled.append(el);
0172         }
0173     }
0174 
0175     return notHandled;
0176 }
0177 
0178 QString Entry::debugInfo() const
0179 {
0180     QString info;
0181     info += QLatin1String("### Entry: ###################\n");
0182     if (!title().isEmpty()) {
0183         info += QLatin1String("title: #") + title() + QLatin1String("#\n");
0184     }
0185     if (!summary().isEmpty()) {
0186         info += QLatin1String("summary: #") + summary() + QLatin1String("#\n");
0187     }
0188     if (!id().isEmpty()) {
0189         info += QLatin1String("id: #") + id() + QLatin1String("#\n");
0190     }
0191     if (!content().isNull()) {
0192         info += content().debugInfo();
0193     }
0194 
0195     if (!rights().isEmpty()) {
0196         info += QLatin1String("rights: #") + rights() + QLatin1String("#\n");
0197     }
0198 
0199     QString dupdated = dateTimeToString(updated());
0200     if (!dupdated.isNull()) {
0201         info += QLatin1String("updated: #") + dupdated + QLatin1String("#\n");
0202     }
0203 
0204     QString dpublished = dateTimeToString(published());
0205     if (!dpublished.isNull()) {
0206         info += QLatin1String("published: #") + dpublished + QLatin1String("#\n");
0207     }
0208 
0209     const QList<Link> dlinks = links();
0210     for (const auto &link : dlinks) {
0211         info += link.debugInfo();
0212     }
0213 
0214     const QList<Category> dcats = categories();
0215     for (const auto &cat : dcats) {
0216         info += cat.debugInfo();
0217     }
0218 
0219     info += QLatin1String("### Authors: ###################\n");
0220 
0221     const QList<Person> dauthors = authors();
0222     for (const auto &author : dauthors) {
0223         info += author.debugInfo();
0224     }
0225 
0226     info += QLatin1String("### Contributors: ###################\n");
0227 
0228     const QList<Person> dcontri = contributors();
0229     for (const auto &person : dcontri) {
0230         info += person.debugInfo();
0231     }
0232 
0233     if (!source().isNull()) {
0234         info += source().debugInfo();
0235     }
0236 
0237     info += QLatin1String("### Entry end ################\n");
0238 
0239     return info;
0240 }
0241 
0242 bool Entry::accept(SpecificItemVisitor *visitor)
0243 {
0244     return visitor->visitAtomEntry(this);
0245 }
0246 
0247 } // namespace Atom
0248 } // namespace Syndication