KWeatherCore

feedparser.cpp
1/*
2 * SPDX-FileCopyrightText: 2021 Han Young <hanyoung@protonmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6#include "feedparser.h"
7#include "kweathercore_p.h"
8#include <QDateTime>
9#include <QJsonObject>
10namespace KWeatherCore
11{
12FeedParser::FeedParser(const QJsonDocument &configFile, QObject *parent)
13 : QObject(parent)
14{
15 setConfig(configFile);
16}
17
18void FeedParser::setConfig(const QJsonDocument &configFile)
19{
20 const auto obj = configFile.object();
21
22 m_url = QUrl(obj[QLatin1String("url")].toString());
23 m_entryMarker = obj[QLatin1String("entry_marker")].toString();
24 m_titleMarker = obj[QLatin1String("title")].toString();
25
26 auto cap_it = obj.find(QLatin1String("cap"));
27 if (cap_it != obj.end()) {
28 m_hasCap = true;
29 const auto cap_obj = cap_it->toObject();
30 m_capLinkElementMarker = cap_obj[QLatin1String("element")].toString();
31 m_capValueType = cap_obj[QLatin1String("type")].toString();
32 m_capValueMarker = cap_obj[QLatin1String("value")].toString();
33 } else {
34 m_hasCap = false;
35 m_capLinkElementMarker.clear();
36 m_capValueMarker.clear();
37 m_capValueType.clear();
38 }
39 m_summaryMarker = obj[QLatin1String("summary")].toString();
40
41 auto area_it = obj.find(QLatin1String("area"));
42 if (area_it != obj.end()) {
43 m_hasArea = true;
44 const auto area_obj = area_it->toObject();
45 m_areaNameMarker = area_obj[QLatin1String("name")].toString();
46 m_polygonMarker = area_obj[QLatin1String("polygon")].toString();
47 m_FIPS6Marker = area_obj[QLatin1String("FIPS6")].toString();
48 m_UGCMarker = area_obj[QLatin1String("UGC")].toString();
49 } else {
50 m_hasArea = false;
51 m_areaNameMarker.clear();
52 m_polygonMarker.clear();
53 m_FIPS6Marker.clear();
54 m_UGCMarker.clear();
55 }
56
57 m_urgencyMarker = obj[QLatin1String("urgency")].toString();
58 m_severityMarker = obj[QLatin1String("severity")].toString();
59 m_certaintyMarker = obj[QLatin1String("certainty")].toString();
60
61 auto date_it = obj.find(QLatin1String("date"));
62 if (date_it != obj.end()) {
63 m_hasDate = true;
64 const auto date_obj = date_it->toObject();
65 m_dateFormat = date_obj[QLatin1String("format")].toString();
66 m_dateMarker = date_obj[QLatin1String("element")].toString();
67 } else {
68 m_hasDate = false;
69 m_dateFormat.clear();
70 m_dateMarker.clear();
71 }
72}
73std::unique_ptr<std::vector<std::unique_ptr<AlertFeedEntry>>> FeedParser::parse(const QByteArray &data) const
74{
75 QXmlStreamReader reader(data);
76 std::unique_ptr<std::vector<std::unique_ptr<AlertFeedEntry>>> result(new std::vector<std::unique_ptr<AlertFeedEntry>>());
77
78 while (!reader.atEnd()) {
79 result->push_back(parseOneEntry(reader));
80 }
81
82 return result;
83}
84std::unique_ptr<AlertFeedEntry> FeedParser::parseOneEntry(QXmlStreamReader &reader) const
85{
86 std::unique_ptr<AlertFeedEntry> entry(new AlertFeedEntry);
87 std::vector<std::pair<QString, QString>> areaCodes;
88 while (reader.readNextStartElement()) {
89 if (reader.name() == m_titleMarker) {
90 entry->setTitle(reader.readElementText());
91 } else if (reader.name() == m_summaryMarker) {
92 entry->setSummary(reader.readElementText());
93 } else if (reader.name() == m_urgencyMarker) {
94 entry->setUrgency(KWeatherCorePrivate::urgencyStringToEnum(reader.readElementText()));
95 } else if (reader.name() == m_severityMarker) {
96 entry->setSeverity(KWeatherCorePrivate::severityStringToEnum(reader.readElementText()));
97 } else if (reader.name() == m_certaintyMarker) {
98 entry->setCertainty(KWeatherCorePrivate::certaintyStringToEnum(reader.readElementText()));
99 } else if (m_hasCap && reader.name() == m_capLinkElementMarker) {
100 entry->setUrl(parseCapElement(reader));
101 } else if (m_hasArea && reader.name() == m_areaNameMarker) {
102 entry->setArea(reader.readElementText());
103 } else if (m_hasArea && reader.name() == m_polygonMarker) {
104 parsePolygonElement(reader, *entry);
105 } else if (m_hasArea && reader.name() == m_FIPS6Marker) {
106 areaCodes.push_back({QStringLiteral("FIPS6"), reader.readElementText()});
107 } else if (m_hasArea && reader.name() == m_UGCMarker) {
108 areaCodes.push_back({QStringLiteral("UGC"), reader.readElementText()});
109 } else if (m_hasDate && reader.name() == m_dateMarker) {
110 if (m_dateFormat == QLatin1String("ISO-8601")) {
111 entry->setDate(QDateTime::fromString(reader.readElementText(), Qt::ISODate));
112 } else {
113 entry->setDate(QDateTime::fromString(reader.readElementText(), m_dateFormat));
114 }
115 }
116 }
117
118 entry->setAreaCodes(std::move(areaCodes));
119 return entry;
120}
121QUrl FeedParser::parseCapElement(QXmlStreamReader &reader) const
122{
123 Q_ASSERT(m_hasCap && reader.isStartElement() && reader.name() == m_capLinkElementMarker);
124
125 if (m_capValueType == QLatin1String("attribute")) {
126 return QUrl(reader.attributes().value(m_capValueMarker).toString());
127 } else if (m_capValueType == QLatin1String("text")) {
128 return QUrl(reader.readElementText());
129 } else {
130 return QUrl();
131 }
132}
133void FeedParser::parsePolygonElement(QXmlStreamReader &reader, AlertFeedEntry &entry) const
134{
135 if (reader.name() == m_polygonMarker) {
136 entry.setPolygon(KWeatherCorePrivate::stringToPolygon(reader.readElementText()));
137 }
138}
139}
140
141#include "moc_feedparser.cpp"
char * toString(const EngineQuery &query)
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
QJsonObject object() const const
QString toString() const const
QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const const
QXmlStreamAttributes attributes() const const
bool isStartElement() const const
QStringView name() const const
QString readElementText(ReadElementTextBehaviour behaviour)
bool readNextStartElement()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 24 2024 12:02:06 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.