File indexing completed on 2024-12-15 03:44:59

0001 /*
0002     SPDX-FileCopyrightText: 2016 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: MIT
0005 */
0006 
0007 #include "product.h"
0008 #include "aggregation.h"
0009 
0010 #include <QDebug>
0011 #include <QJsonArray>
0012 #include <QJsonDocument>
0013 #include <QJsonObject>
0014 #include <QSharedData>
0015 #include <QString>
0016 
0017 using namespace KUserFeedback::Console;
0018 
0019 namespace KUserFeedback {
0020 namespace Console {
0021 class ProductData : public QSharedData
0022 {
0023 public:
0024     QString name;
0025     QVector<SchemaEntry> schema;
0026     QVector<Aggregation> aggregations;
0027 };
0028 
0029 }
0030 }
0031 
0032 Product::Product() : d(new ProductData) {}
0033 Product::Product(const Product&) = default;
0034 Product::~Product() = default;
0035 Product& Product::operator=(const Product&) = default;
0036 
0037 bool Product::isValid() const
0038 {
0039     return !d->name.isEmpty();
0040 }
0041 
0042 QString Product::name() const
0043 {
0044     return d->name;
0045 }
0046 
0047 void Product::setName(const QString& name)
0048 {
0049     d->name = name;
0050 }
0051 
0052 QVector<SchemaEntry> Product::schema() const
0053 {
0054     return d->schema;
0055 }
0056 
0057 SchemaEntry Product::schemaEntry(const QString& name) const
0058 {
0059     const auto it = std::find_if(d->schema.cbegin(), d->schema.cend(), [name](const auto &entry) {
0060         return entry.name() == name;
0061     });
0062     if (it == d->schema.cend())
0063         return {};
0064     return *it;
0065 }
0066 
0067 void Product::setSchema(const QVector<SchemaEntry> &schema)
0068 {
0069     d->schema = schema;
0070 }
0071 
0072 QVector<Aggregation> Product::aggregations() const
0073 {
0074     return d->aggregations;
0075 }
0076 
0077 void Product::setAggregations(const QVector<Aggregation>& aggregations)
0078 {
0079     d->aggregations = aggregations;
0080 }
0081 
0082 void Product::addTemplate(const Product& tpl)
0083 {
0084     // TODO could be done slightly more clever
0085     d->schema += tpl.schema();
0086     d->aggregations += tpl.aggregations();
0087 }
0088 
0089 QByteArray Product::toJson() const
0090 {
0091     QJsonObject obj;
0092     obj.insert(QStringLiteral("name"), name());
0093     {
0094         QJsonArray schema;
0095         foreach (const auto &s, d->schema)
0096             schema.push_back(s.toJsonObject());
0097         obj.insert(QStringLiteral("schema"), schema);
0098     }
0099 
0100     {
0101         QJsonArray aggrs;
0102         foreach (const auto &a, d->aggregations)
0103             aggrs.push_back(a.toJsonObject());
0104         obj.insert(QStringLiteral("aggregation"), aggrs);
0105     }
0106     QJsonDocument doc(obj);
0107     return doc.toJson();
0108 }
0109 
0110 static Product productFromJsonObject(const QJsonObject &obj)
0111 {
0112     Product product;
0113     product.setName(obj.value(QStringLiteral("name")).toString());
0114     product.setSchema(SchemaEntry::fromJson(obj.value(QStringLiteral("schema")).toArray()));
0115     product.setAggregations(Aggregation::fromJson(product, obj.value(QLatin1String("aggregation")).toArray()));
0116     return product;
0117 }
0118 
0119 QVector<Product> Product::fromJson(const QByteArray &data)
0120 {
0121     QVector<Product> products;
0122     QJsonParseError error;
0123     const auto doc = QJsonDocument::fromJson(data, &error);
0124     if (doc.isArray()) {
0125         const auto array = doc.array();
0126         products.reserve(array.size());
0127         foreach (const auto &value, array) {
0128             const auto obj = value.toObject();
0129             products.push_back(productFromJsonObject(obj));
0130         }
0131     } else if (doc.isObject()) {
0132         products.push_back(productFromJsonObject(doc.object()));
0133     } else {
0134         qDebug() << "Failed to parse product JSON:" << error.errorString() << error.offset;
0135     }
0136     return products;
0137 }