File indexing completed on 2024-05-05 16:49:21
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 auto obj = configFile.object(); 0021 0022 m_url = QUrl(obj[QStringLiteral("url")].toString()); 0023 m_entryMarker = obj[QStringLiteral("entry_marker")].toString(); 0024 m_titleMarker = obj[QStringLiteral("title")].toString(); 0025 0026 auto cap_it = obj.find(QStringLiteral("cap")); 0027 if (cap_it != obj.end()) { 0028 m_hasCap = true; 0029 auto cap_obj = cap_it->toObject(); 0030 m_capLinkElementMarker = cap_obj[QStringLiteral("element")].toString(); 0031 m_capValueType = cap_obj[QStringLiteral("type")].toString(); 0032 m_capValueMarker = cap_obj[QStringLiteral("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[QStringLiteral("summary")].toString(); 0040 0041 auto area_it = obj.find(QStringLiteral("area")); 0042 if (area_it != obj.end()) { 0043 m_hasArea = true; 0044 auto area_obj = area_it->toObject(); 0045 m_areaNameMarker = area_obj[QStringLiteral("name")].toString(); 0046 m_polygonMarker = area_obj[QStringLiteral("polygon")].toString(); 0047 m_FIPS6Marker = area_obj[QStringLiteral("FIPS6")].toString(); 0048 m_UGCMarker = area_obj[QStringLiteral("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[QStringLiteral("urgency")].toString(); 0058 m_severityMarker = obj[QStringLiteral("severity")].toString(); 0059 m_certaintyMarker = obj[QStringLiteral("certainty")].toString(); 0060 0061 auto date_it = obj.find(QStringLiteral("date")); 0062 if (date_it != obj.end()) { 0063 m_hasDate = true; 0064 auto date_obj = date_it->toObject(); 0065 m_dateFormat = date_obj[QStringLiteral("format")].toString(); 0066 m_dateMarker = date_obj[QStringLiteral("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>>> 0074 FeedParser::parse(const QByteArray &data) const 0075 { 0076 QXmlStreamReader reader(data); 0077 std::unique_ptr<std::vector<std::unique_ptr<AlertFeedEntry>>> result( 0078 new std::vector<std::unique_ptr<AlertFeedEntry>>()); 0079 0080 while (!reader.atEnd()) { 0081 result->push_back(parseOneEntry(reader)); 0082 } 0083 0084 return result; 0085 } 0086 std::unique_ptr<AlertFeedEntry> 0087 FeedParser::parseOneEntry(QXmlStreamReader &reader) const 0088 { 0089 std::unique_ptr<AlertFeedEntry> entry(new AlertFeedEntry); 0090 std::vector<std::pair<QString, QString>> areaCodes; 0091 while (reader.readNextStartElement()) { 0092 if (reader.name() == m_titleMarker) { 0093 entry->setTitle(reader.readElementText()); 0094 } else if (reader.name() == m_summaryMarker) { 0095 entry->setSummary(reader.readElementText()); 0096 } else if (reader.name() == m_urgencyMarker) { 0097 entry->setUrgency(urgencyStrToEnum(reader.readElementText())); 0098 } else if (reader.name() == m_severityMarker) { 0099 entry->setSeverity(severityStrToEnum(reader.readElementText())); 0100 } else if (reader.name() == m_certaintyMarker) { 0101 entry->setCertainty(certaintyStrToEnum(reader.readElementText())); 0102 } else if (m_hasCap && reader.name() == m_capLinkElementMarker) { 0103 entry->setUrl(parseCapElement(reader)); 0104 } else if (m_hasArea && reader.name() == m_areaNameMarker) { 0105 entry->setArea(reader.readElementText()); 0106 } else if (m_hasArea && reader.name() == m_polygonMarker) { 0107 parsePolygonElement(reader, *entry); 0108 } else if (m_hasArea && reader.name() == m_FIPS6Marker) { 0109 areaCodes.push_back( 0110 {QStringLiteral("FIPS6"), reader.readElementText()}); 0111 } else if (m_hasArea && reader.name() == m_UGCMarker) { 0112 areaCodes.push_back( 0113 {QStringLiteral("UGC"), reader.readElementText()}); 0114 } else if (m_hasDate && reader.name() == m_dateMarker) { 0115 if (m_dateFormat == QStringLiteral("ISO-8601")) { 0116 entry->setDate(QDateTime::fromString(reader.readElementText(), 0117 Qt::ISODate)); 0118 } else { 0119 entry->setDate(QDateTime::fromString(reader.readElementText(), 0120 m_dateFormat)); 0121 } 0122 } 0123 } 0124 0125 entry->setAreaCodes(areaCodes); 0126 return entry; 0127 } 0128 QUrl FeedParser::parseCapElement(QXmlStreamReader &reader) const 0129 { 0130 Q_ASSERT(m_hasCap && reader.isStartElement() && 0131 reader.name() == m_capLinkElementMarker); 0132 0133 if (m_capValueType == QStringLiteral("attribute")) { 0134 return QUrl(reader.attributes().value(m_capValueMarker).toString()); 0135 } else if (m_capValueType == QStringLiteral("text")) 0136 return QUrl(reader.readElementText()); 0137 else 0138 return QUrl(); 0139 } 0140 void FeedParser::parsePolygonElement(QXmlStreamReader &reader, 0141 AlertFeedEntry &entry) const 0142 { 0143 if (reader.name() == m_polygonMarker) { 0144 entry.setPolygon(stringToPolygon(reader.readElementText())); 0145 } 0146 } 0147 }