File indexing completed on 2024-04-28 04:42:42
0001 /* 0002 * SPDX-FileCopyrightText: 2021 Han Young <hanyoung@protonmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 #include "feedparser.h" 0007 #include "kweathercore_p.h" 0008 #include <QDateTime> 0009 #include <QJsonObject> 0010 namespace KWeatherCore 0011 { 0012 FeedParser::FeedParser(const QJsonDocument &configFile, QObject *parent) 0013 : QObject(parent) 0014 { 0015 setConfig(configFile); 0016 } 0017 0018 void FeedParser::setConfig(const QJsonDocument &configFile) 0019 { 0020 const auto obj = configFile.object(); 0021 0022 m_url = QUrl(obj[QLatin1String("url")].toString()); 0023 m_entryMarker = obj[QLatin1String("entry_marker")].toString(); 0024 m_titleMarker = obj[QLatin1String("title")].toString(); 0025 0026 auto cap_it = obj.find(QLatin1String("cap")); 0027 if (cap_it != obj.end()) { 0028 m_hasCap = true; 0029 const auto cap_obj = cap_it->toObject(); 0030 m_capLinkElementMarker = cap_obj[QLatin1String("element")].toString(); 0031 m_capValueType = cap_obj[QLatin1String("type")].toString(); 0032 m_capValueMarker = cap_obj[QLatin1String("value")].toString(); 0033 } else { 0034 m_hasCap = false; 0035 m_capLinkElementMarker.clear(); 0036 m_capValueMarker.clear(); 0037 m_capValueType.clear(); 0038 } 0039 m_summaryMarker = obj[QLatin1String("summary")].toString(); 0040 0041 auto area_it = obj.find(QLatin1String("area")); 0042 if (area_it != obj.end()) { 0043 m_hasArea = true; 0044 const auto area_obj = area_it->toObject(); 0045 m_areaNameMarker = area_obj[QLatin1String("name")].toString(); 0046 m_polygonMarker = area_obj[QLatin1String("polygon")].toString(); 0047 m_FIPS6Marker = area_obj[QLatin1String("FIPS6")].toString(); 0048 m_UGCMarker = area_obj[QLatin1String("UGC")].toString(); 0049 } else { 0050 m_hasArea = false; 0051 m_areaNameMarker.clear(); 0052 m_polygonMarker.clear(); 0053 m_FIPS6Marker.clear(); 0054 m_UGCMarker.clear(); 0055 } 0056 0057 m_urgencyMarker = obj[QLatin1String("urgency")].toString(); 0058 m_severityMarker = obj[QLatin1String("severity")].toString(); 0059 m_certaintyMarker = obj[QLatin1String("certainty")].toString(); 0060 0061 auto date_it = obj.find(QLatin1String("date")); 0062 if (date_it != obj.end()) { 0063 m_hasDate = true; 0064 const auto date_obj = date_it->toObject(); 0065 m_dateFormat = date_obj[QLatin1String("format")].toString(); 0066 m_dateMarker = date_obj[QLatin1String("element")].toString(); 0067 } else { 0068 m_hasDate = false; 0069 m_dateFormat.clear(); 0070 m_dateMarker.clear(); 0071 } 0072 } 0073 std::unique_ptr<std::vector<std::unique_ptr<AlertFeedEntry>>> FeedParser::parse(const QByteArray &data) const 0074 { 0075 QXmlStreamReader reader(data); 0076 std::unique_ptr<std::vector<std::unique_ptr<AlertFeedEntry>>> result(new std::vector<std::unique_ptr<AlertFeedEntry>>()); 0077 0078 while (!reader.atEnd()) { 0079 result->push_back(parseOneEntry(reader)); 0080 } 0081 0082 return result; 0083 } 0084 std::unique_ptr<AlertFeedEntry> FeedParser::parseOneEntry(QXmlStreamReader &reader) const 0085 { 0086 std::unique_ptr<AlertFeedEntry> entry(new AlertFeedEntry); 0087 std::vector<std::pair<QString, QString>> areaCodes; 0088 while (reader.readNextStartElement()) { 0089 if (reader.name() == m_titleMarker) { 0090 entry->setTitle(reader.readElementText()); 0091 } else if (reader.name() == m_summaryMarker) { 0092 entry->setSummary(reader.readElementText()); 0093 } else if (reader.name() == m_urgencyMarker) { 0094 entry->setUrgency(KWeatherCorePrivate::urgencyStringToEnum(reader.readElementText())); 0095 } else if (reader.name() == m_severityMarker) { 0096 entry->setSeverity(KWeatherCorePrivate::severityStringToEnum(reader.readElementText())); 0097 } else if (reader.name() == m_certaintyMarker) { 0098 entry->setCertainty(KWeatherCorePrivate::certaintyStringToEnum(reader.readElementText())); 0099 } else if (m_hasCap && reader.name() == m_capLinkElementMarker) { 0100 entry->setUrl(parseCapElement(reader)); 0101 } else if (m_hasArea && reader.name() == m_areaNameMarker) { 0102 entry->setArea(reader.readElementText()); 0103 } else if (m_hasArea && reader.name() == m_polygonMarker) { 0104 parsePolygonElement(reader, *entry); 0105 } else if (m_hasArea && reader.name() == m_FIPS6Marker) { 0106 areaCodes.push_back({QStringLiteral("FIPS6"), reader.readElementText()}); 0107 } else if (m_hasArea && reader.name() == m_UGCMarker) { 0108 areaCodes.push_back({QStringLiteral("UGC"), reader.readElementText()}); 0109 } else if (m_hasDate && reader.name() == m_dateMarker) { 0110 if (m_dateFormat == QLatin1String("ISO-8601")) { 0111 entry->setDate(QDateTime::fromString(reader.readElementText(), Qt::ISODate)); 0112 } else { 0113 entry->setDate(QDateTime::fromString(reader.readElementText(), m_dateFormat)); 0114 } 0115 } 0116 } 0117 0118 entry->setAreaCodes(areaCodes); 0119 return entry; 0120 } 0121 QUrl FeedParser::parseCapElement(QXmlStreamReader &reader) const 0122 { 0123 Q_ASSERT(m_hasCap && reader.isStartElement() && reader.name() == m_capLinkElementMarker); 0124 0125 if (m_capValueType == QLatin1String("attribute")) { 0126 return QUrl(reader.attributes().value(m_capValueMarker).toString()); 0127 } else if (m_capValueType == QLatin1String("text")) { 0128 return QUrl(reader.readElementText()); 0129 } else { 0130 return QUrl(); 0131 } 0132 } 0133 void FeedParser::parsePolygonElement(QXmlStreamReader &reader, AlertFeedEntry &entry) const 0134 { 0135 if (reader.name() == m_polygonMarker) { 0136 entry.setPolygon(KWeatherCorePrivate::stringToPolygon(reader.readElementText())); 0137 } 0138 } 0139 } 0140 0141 #include "moc_feedparser.cpp"