AmdaParser.cpp
129 lines
| 4.4 KiB
| text/x-c
|
CppLexer
Alexandre Leroux
|
r354 | #include "AmdaParser.h" | ||
#include <DataSource/DataSourceItem.h> | ||||
Alexandre Leroux
|
r355 | #include <QFile> | ||
Alexandre Leroux
|
r356 | #include <QJsonArray> | ||
Alexandre Leroux
|
r355 | #include <QJsonDocument> | ||
#include <QJsonObject> | ||||
Alexandre Leroux
|
r354 | Q_LOGGING_CATEGORY(LOG_AmdaParser, "AmdaParser") | ||
Alexandre Leroux
|
r355 | namespace { | ||
// Significant keys of an AMDA's JSON file | ||||
Alexandre Leroux
|
r356 | const auto COMPONENT_KEY = QStringLiteral("component"); | ||
const auto PRODUCT_KEY = QStringLiteral("parameter"); | ||||
Alexandre Leroux
|
r355 | const auto ROOT_KEY = QStringLiteral("dataCenter"); | ||
Alexandre Leroux
|
r356 | /// Returns the correct item type according to the key passed in parameter | ||
DataSourceItemType itemType(const QString &key) noexcept | ||||
{ | ||||
if (key == PRODUCT_KEY) { | ||||
return DataSourceItemType::PRODUCT; | ||||
} | ||||
else if (key == COMPONENT_KEY) { | ||||
return DataSourceItemType::COMPONENT; | ||||
} | ||||
else { | ||||
return DataSourceItemType::NODE; | ||||
} | ||||
} | ||||
/** | ||||
* Processes an entry of the JSON file to populate/create data source items | ||||
* @param jsonKey the entry's key | ||||
* @param jsonValue the entry's value | ||||
* @param item the current item for which the entry processing will be applied | ||||
* @param appendData flag indicating that the entry is part of an array. In the case of an array of | ||||
* values, each value will be concatenated to the others (rather than replacing the others) | ||||
*/ | ||||
void parseEntry(const QString &jsonKey, const QJsonValue &jsonValue, DataSourceItem &item, | ||||
bool isArrayEntry = false) | ||||
{ | ||||
if (jsonValue.isObject()) { | ||||
// Case of an object: | ||||
// - a new data source item is created and | ||||
// - parsing is called recursively to process the new item | ||||
// - the new item is then added as a child of the former item | ||||
auto object = jsonValue.toObject(); | ||||
auto newItem = std::make_unique<DataSourceItem>(itemType(jsonKey)); | ||||
for (auto it = object.constBegin(), end = object.constEnd(); it != end; ++it) { | ||||
parseEntry(it.key(), it.value(), *newItem); | ||||
} | ||||
item.appendChild(std::move(newItem)); | ||||
} | ||||
else if (jsonValue.isArray()) { | ||||
// Case of an array: the item is populated with the arrays' content | ||||
auto object = jsonValue.toArray(); | ||||
for (auto it = object.constBegin(), end = object.constEnd(); it != end; ++it) { | ||||
parseEntry(jsonKey, *it, item, true); | ||||
} | ||||
} | ||||
else { | ||||
// Case of a simple value: we add a data to the item. If the simple value is a part of an | ||||
// array, it is concatenated to the values already existing for this key | ||||
item.setData(jsonKey, jsonValue.toVariant(), isArrayEntry); | ||||
} | ||||
} | ||||
Alexandre Leroux
|
r355 | } // namespace | ||
Alexandre Leroux
|
r354 | std::unique_ptr<DataSourceItem> AmdaParser::readJson(const QString &filePath) noexcept | ||
{ | ||||
Alexandre Leroux
|
r355 | QFile jsonFile{filePath}; | ||
if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) { | ||||
qCCritical(LOG_AmdaParser()) | ||||
<< QObject::tr("Can't retrieve data source tree from file %1: %2") | ||||
.arg(filePath, jsonFile.errorString()); | ||||
return nullptr; | ||||
} | ||||
auto json = jsonFile.readAll(); | ||||
auto jsonDocument = QJsonDocument::fromJson(json); | ||||
// Check preconditions for parsing | ||||
if (!jsonDocument.isObject()) { | ||||
qCCritical(LOG_AmdaParser()) | ||||
<< QObject::tr( | ||||
"Can't retrieve data source tree from file %1: the file is malformed (there is " | ||||
"not one and only one root object)") | ||||
.arg(filePath); | ||||
return nullptr; | ||||
} | ||||
auto jsonDocumentObject = jsonDocument.object(); | ||||
if (!jsonDocumentObject.contains(ROOT_KEY)) { | ||||
qCCritical(LOG_AmdaParser()) | ||||
<< QObject::tr( | ||||
"Can't retrieve data source tree from file %1: the file is malformed (the key " | ||||
"for the root element was not found (%2))") | ||||
.arg(filePath, ROOT_KEY); | ||||
return nullptr; | ||||
} | ||||
auto rootValue = jsonDocumentObject.value(ROOT_KEY); | ||||
if (!rootValue.isObject()) { | ||||
qCCritical(LOG_AmdaParser()) | ||||
<< QObject::tr( | ||||
"Can't retrieve data source tree from file %1: the file is malformed (the root " | ||||
"element is of the wrong type)") | ||||
.arg(filePath); | ||||
return nullptr; | ||||
} | ||||
Alexandre Leroux
|
r356 | |||
// Makes the parsing | ||||
auto rootObject = rootValue.toObject(); | ||||
auto rootItem = std::make_unique<DataSourceItem>(DataSourceItemType::NODE); | ||||
for (auto it = rootObject.constBegin(), end = rootObject.constEnd(); it != end; ++it) { | ||||
parseEntry(it.key(), it.value(), *rootItem); | ||||
} | ||||
return rootItem; | ||||
Alexandre Leroux
|
r354 | } | ||