File indexing completed on 2025-06-29 04:46:12

0001 /*
0002     SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "jsonldfilterengine.h"
0008 #include "jsonld.h"
0009 
0010 #include <QJsonArray>
0011 #include <QJsonObject>
0012 
0013 #include <cstring>
0014 
0015 using namespace KItinerary;
0016 
0017 void KItinerary::JsonLd::renameProperty(QJsonObject &obj, const char *oldName, const char *newName)
0018 {
0019   const auto value = obj.value(QLatin1StringView(oldName));
0020   if (!value.isUndefined() && !obj.contains(QLatin1StringView(newName))) {
0021     obj.insert(QLatin1StringView(newName), value);
0022     obj.remove(QLatin1StringView(oldName));
0023   }
0024 }
0025 
0026 JsonLdFilterEngine::JsonLdFilterEngine() = default;
0027 JsonLdFilterEngine::~JsonLdFilterEngine() = default;
0028 
0029 void JsonLdFilterEngine::filterRecursive(QJsonObject &obj)
0030 {
0031     auto type = JsonLd::typeName(obj).toUtf8();
0032 
0033     // normalize type
0034     if (m_typeMappings)  {
0035         const auto it = std::lower_bound(m_typeMappings, m_typeMappings + m_typeMappingsSize, type, [](const auto &lhs, const auto &rhs) {
0036             return std::strcmp(lhs.fromType, rhs.constData()) < 0;
0037         });
0038         if (it != (m_typeMappings + m_typeMappingsSize) && std::strcmp((*it).fromType, type.constData()) == 0) {
0039             type = it->toType;
0040             obj.insert(QStringLiteral("@type"), QLatin1StringView(type));
0041         }
0042     }
0043 
0044     for (auto it = obj.begin(); it != obj.end(); ++it) {
0045         if ((*it).type() == QJsonValue::Object) {
0046             QJsonObject subObj = (*it).toObject();
0047             filterRecursive(subObj);
0048             *it = subObj;
0049         } else if ((*it).type() == QJsonValue::Array) {
0050             QJsonArray array = (*it).toArray();
0051             filterRecursive(array);
0052             *it = array;
0053         }
0054     }
0055 
0056     // rename properties
0057     if (m_propertyMappings) {
0058         const auto [pBegin, pEnd] = std::equal_range(m_propertyMappings, m_propertyMappings + m_propertyMappingsSize, type, [](const auto &lhs, const auto &rhs) {
0059             if constexpr (std::is_same_v<std::decay_t<decltype(lhs)>, QByteArray>) {
0060                 return std::strcmp(lhs.constData(), rhs.type) < 0;
0061             } else {
0062                 return std::strcmp(lhs.type, rhs.constData()) < 0;
0063             }
0064         });
0065         for (auto it = pBegin; it != pEnd; ++it) {
0066             JsonLd::renameProperty(obj, (*it).fromName, (*it).toName);
0067         }
0068     }
0069 
0070     // apply filter functions
0071     if (m_typeFilters) {
0072         const auto filterIt = std::lower_bound(m_typeFilters, m_typeFilters + m_typeFiltersSize, type, [](const auto &lhs, const auto &rhs) {
0073             return std::strcmp(lhs.type, rhs.constData()) < 0;
0074         });
0075         if (filterIt != (m_typeFilters + m_typeFiltersSize) && std::strcmp((*filterIt).type, type.constData()) == 0) {
0076             (*filterIt).filterFunc(obj);
0077         }
0078     }
0079 }
0080 
0081 void JsonLdFilterEngine::filterRecursive(QJsonArray &array)
0082 {
0083     for (auto it = array.begin(); it != array.end(); ++it) {
0084         if ((*it).type() == QJsonValue::Object) {
0085             QJsonObject subObj = (*it).toObject();
0086             filterRecursive(subObj);
0087             *it = subObj;
0088         } else if ((*it).type() == QJsonValue::Array) {
0089             QJsonArray array = (*it).toArray();
0090             filterRecursive(array);
0091             *it = array;
0092         }
0093     }
0094 }
0095 
0096 void JsonLdFilterEngine::setTypeMappings(const JsonLdFilterEngine::TypeMapping *typeMappings, std::size_t count)
0097 {
0098     m_typeMappings = typeMappings;
0099     m_typeMappingsSize = count;
0100 }
0101 
0102 void JsonLdFilterEngine::setTypeFilters(const JsonLdFilterEngine::TypeFilter *typeFilters, std::size_t count)
0103 {
0104     m_typeFilters = typeFilters;
0105     m_typeFiltersSize = count;
0106 }
0107 
0108 void JsonLdFilterEngine::setPropertyMappings(const JsonLdFilterEngine::PropertyMapping *propertyMappings, std::size_t count)
0109 {
0110     m_propertyMappings = propertyMappings;
0111     m_propertyMappingsSize = count;
0112 }