AmdaParser.cpp
125 lines
| 4.2 KiB
| text/x-c
|
CppLexer
Alexandre Leroux
|
r327 | #include "AmdaParser.h" | ||
Alexandre Leroux
|
r379 | #include "AmdaDefs.h" | ||
Alexandre Leroux
|
r327 | |||
#include <DataSource/DataSourceItem.h> | ||||
Alexandre Leroux
|
r328 | #include <QFile> | ||
Alexandre Leroux
|
r329 | #include <QJsonArray> | ||
Alexandre Leroux
|
r328 | #include <QJsonDocument> | ||
#include <QJsonObject> | ||||
Alexandre Leroux
|
r327 | Q_LOGGING_CATEGORY(LOG_AmdaParser, "AmdaParser") | ||
Alexandre Leroux
|
r328 | namespace { | ||
Alexandre Leroux
|
r329 | /// Returns the correct item type according to the key passed in parameter | ||
DataSourceItemType itemType(const QString &key) noexcept | ||||
{ | ||||
Alexandre Leroux
|
r379 | if (key == AMDA_PRODUCT_KEY) { | ||
Alexandre Leroux
|
r329 | return DataSourceItemType::PRODUCT; | ||
} | ||||
Alexandre Leroux
|
r379 | else if (key == AMDA_COMPONENT_KEY) { | ||
Alexandre Leroux
|
r329 | 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
|
r328 | } // namespace | ||
Alexandre Leroux
|
r327 | std::unique_ptr<DataSourceItem> AmdaParser::readJson(const QString &filePath) noexcept | ||
{ | ||||
Alexandre Leroux
|
r328 | 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(); | ||||
Alexandre Leroux
|
r379 | if (!jsonDocumentObject.contains(AMDA_ROOT_KEY)) { | ||
Alexandre Leroux
|
r328 | 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))") | ||||
Alexandre Leroux
|
r379 | .arg(filePath, AMDA_ROOT_KEY); | ||
Alexandre Leroux
|
r328 | return nullptr; | ||
} | ||||
Alexandre Leroux
|
r379 | auto rootValue = jsonDocumentObject.value(AMDA_ROOT_KEY); | ||
Alexandre Leroux
|
r328 | 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
|
r329 | |||
// 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
|
r327 | } | ||