1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*
SPDX-FileCopyrightText: 2017 Volker Krause <vkrause@kde.org>
SPDX-License-Identifier: MIT
*/
#include "surveytargetexpressionevaluator.h"
#include "surveytargetexpression.h"
using namespace KUserFeedback;
SurveyTargetExpressionDataProvider::SurveyTargetExpressionDataProvider()
{
}
SurveyTargetExpressionDataProvider::~SurveyTargetExpressionDataProvider()
{
}
SurveyTargetExpressionEvaluator::SurveyTargetExpressionEvaluator()
: m_provider(nullptr)
{
}
SurveyTargetExpressionEvaluator::~SurveyTargetExpressionEvaluator()
{
}
void SurveyTargetExpressionEvaluator::setDataProvider(const SurveyTargetExpressionDataProvider* provider)
{
m_provider = provider;
}
static bool variantLess(const QVariant &lhs, const QVariant &rhs)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return QVariant::compare(lhs, rhs) == QPartialOrdering::Less;
#else
return lhs < rhs;
#endif
}
static bool variantLessOrEqual(const QVariant &lhs, const QVariant &rhs)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
const auto order = QVariant::compare(lhs, rhs);
return order == QPartialOrdering::Less || order == QPartialOrdering::Equivalent;
#else
return lhs <= rhs;
#endif
}
bool SurveyTargetExpressionEvaluator::evaluate(SurveyTargetExpression* expression)
{
// logical operations
switch (expression->type()) {
case SurveyTargetExpression::OpLogicAnd:
return evaluate(expression->left()) && evaluate(expression->right());
case SurveyTargetExpression::OpLogicOr:
return evaluate(expression->left()) || evaluate(expression->right());
default:
break;
}
// comparisson operations:
const auto lhs = value(expression->left());
const auto rhs = value(expression->right());
if (lhs.typeId() == QMetaType::UnknownType || rhs.typeId() == QMetaType::UnknownType) // invalid element access can never succeed
return false;
if ((lhs.typeId() == QMetaType::QString && rhs.typeId() != QMetaType::QString)
|| (lhs.typeId() != QMetaType::QString && rhs.typeId() == QMetaType::QString))
return false; // strings can only be compared to strings
switch (expression->type()) {
case SurveyTargetExpression::OpEqual:
return lhs == rhs;
case SurveyTargetExpression::OpNotEqual:
return lhs != rhs;
case SurveyTargetExpression::OpGreater:
return variantLess(rhs, lhs);
case SurveyTargetExpression::OpGreaterEqual:
return variantLessOrEqual(rhs, lhs);
case SurveyTargetExpression::OpLess:
return variantLess(lhs, rhs);
case SurveyTargetExpression::OpLessEqual:
return variantLessOrEqual(lhs, rhs);
default:
break;
}
return false;
}
QVariant SurveyTargetExpressionEvaluator::value(SurveyTargetExpression* expression)
{
switch (expression->type()) {
case SurveyTargetExpression::Value:
return expression->value();
case SurveyTargetExpression::ScalarElement:
{
const auto v = value(expression->source());
if (v.canConvert<QVariantList>() && expression->sourceElement() == QLatin1String("size"))
return v.value<QVariantList>().size();
const auto m = v.toMap();
const auto it = m.find(expression->sourceElement());
if (it != m.end() && !it.value().canConvert<QVariantMap>())
return it.value();
if (expression->sourceElement() == QLatin1String("size"))
return m.size();
return QVariant();
}
case SurveyTargetExpression::ListElement:
{
const auto v = value(expression->source()).value<QVariantList>().value(expression->value().toInt());
return v.toMap().value(expression->sourceElement());
}
case SurveyTargetExpression::MapElement:
{
const auto v = value(expression->source()).toMap().value(expression->value().toString());
qDebug() << v << value(expression->source()).toMap() << expression->value().toString();
return v.toMap().value(expression->sourceElement());
}
default:
break;
}
Q_ASSERT(false);
return QVariant();
}
QVariant SurveyTargetExpressionEvaluator::value(const QString& source)
{
Q_ASSERT(m_provider);
const auto it = m_dataCache.constFind(source);
if (it != m_dataCache.constEnd())
return it.value();
const auto v = m_provider->sourceData(source);
m_dataCache.insert(source, v);
return v;
}
|