nymea/server/jsonrpc/jsontypes.cpp

493 lines
14 KiB
C++

#include "jsontypes.h"
#include "device.h"
#include <QDebug>
namespace JsonTypes {
QVariantMap allTypes()
{
QVariantMap allTypes;
allTypes.insert("BasicType", basicTypes());
allTypes.insert("ParamType", paramTypeDescription());
allTypes.insert("StateType", stateTypeDescription());
allTypes.insert("TriggerType", triggerTypeDescription());
allTypes.insert("ActionType", actionTypeDescription());
allTypes.insert("DeviceClass", deviceClassDescription());
allTypes.insert("PluginType", pluginTypeDescription());
allTypes.insert("Param", paramDescription());
allTypes.insert("State", stateDescription());
allTypes.insert("Trigger", triggerDescription());
allTypes.insert("Device", deviceDescription());
allTypes.insert("Action", actionDescription());
allTypes.insert("Rule", ruleDescription());
return allTypes;
}
QString basicTypesRef()
{
return "$ref:BasicType";
}
QVariantList basicTypes()
{
QVariantList basicTypes;
basicTypes.append("uuid");
basicTypes.append("string");
basicTypes.append("integer");
basicTypes.append("double");
basicTypes.append("bool");
return basicTypes;
}
QString paramTypeRef()
{
return "$ref:ParamType";
}
QVariantMap paramTypeDescription()
{
QVariantMap paramType;
paramType.insert("name", "string");
paramType.insert("type", basicTypesRef());
// paramType.insert("default", "value");
// paramType.insert("value", "value");
return paramType;
}
QString paramRef()
{
return "$ref:Param";
}
QVariantMap paramDescription()
{
QVariantMap param;
param.insert("name", "string");
param.insert("value", basicTypesRef());
return param;
}
QString stateTypeRef()
{
return "$ref:StateType";
}
QVariantMap stateTypeDescription()
{
QVariantMap stateTypeDescription;
stateTypeDescription.insert("id", "uuid");
stateTypeDescription.insert("name", "string");
stateTypeDescription.insert("type", basicTypesRef());
// stateTypeDescription.insert("default", "value");
return stateTypeDescription;
}
QString stateRef()
{
return "$ref:Sate";
}
QVariantMap stateDescription()
{
QVariantMap stateDescription;
stateDescription.insert("stateTypeId", "uuid");
stateDescription.insert("deviceId", "uuid");
stateDescription.insert("value", "variant");
return stateDescription;
}
QString triggerTypeRef()
{
return "$ref:TriggerType";
}
QVariantMap triggerTypeDescription()
{
QVariantMap triggerTypeDescription;
triggerTypeDescription.insert("id", "uuid");
triggerTypeDescription.insert("name", "string");
QVariantList params;
params.append(paramTypeRef());
triggerTypeDescription.insert("params", params);
return triggerTypeDescription;
}
QVariantMap packTriggerType(const TriggerType &triggerType)
{
QVariantMap variant;
variant.insert("id", triggerType.id());
variant.insert("name", triggerType.name());
variant.insert("params", triggerType.parameters());
return variant;
}
QString triggerRef()
{
return "$ref:Trigger";
}
QVariantMap triggerDescription()
{
QVariantMap triggerDescription;
triggerDescription.insert("triggerTypeId", "uuid");
triggerDescription.insert("deviceId", "uuid");
QVariantList params;
params.append(paramRef());
triggerDescription.insert("params", params);
return triggerDescription;
}
QVariantMap packTrigger(const Trigger &trigger)
{
QVariantMap variant;
variant.insert("triggerTypeId", trigger.triggerTypeId());
variant.insert("deviceId", trigger.deviceId());
variant.insert("params", trigger.params());
return variant;
}
QString actionTypeRef()
{
return "$ref:ActionType";
}
QVariantMap actionTypeDescription()
{
QVariantMap actionTypeDescription;
actionTypeDescription.insert("id", "uuid");
actionTypeDescription.insert("name", "string");
QVariantList params;
params.append(paramTypeRef());
actionTypeDescription.insert("params", params);
return actionTypeDescription;
}
QVariantMap packActionType(const ActionType &actionType)
{
QVariantMap variantMap;
variantMap.insert("id", actionType.id());
variantMap.insert("name", actionType.name());
variantMap.insert("params", actionType.parameters());
return variantMap;
}
QString actionRef()
{
return "$ref:Action";
}
QVariantMap actionDescription()
{
QVariantMap actionDescription;
actionDescription.insert("actionTypeId", "uuid");
actionDescription.insert("deviceId", "uuid");
QVariantList params;
params.append(paramRef());
actionDescription.insert("params", params);
return actionDescription;
}
QVariantMap packAction(const Action &action)
{
QVariantMap variant;
variant.insert("actionTypeId", action.actionTypeId());
variant.insert("deviceId", action.deviceId());
variant.insert("params", action.params());
return variant;
}
QString deviceClassRef()
{
return "$ref:DeviceClass";
}
QVariantMap deviceClassDescription()
{
QVariantMap deviceClass;
deviceClass.insert("id", "uuid");
deviceClass.insert("name", "string");
QVariantList states;
states.append(stateTypeRef());
deviceClass.insert("states", states);
QVariantList triggers;
triggers.append(triggerTypeRef());
deviceClass.insert("triggers", triggers);
QVariantList actions;
actions.append(actionTypeRef());
deviceClass.insert("actions", actions);
QVariantList params;
params.append(paramTypeRef());
deviceClass.insert("params", params);
return deviceClass;
}
QVariantMap packDeviceClass(const DeviceClass &deviceClass)
{
QVariantMap variant;
variant.insert("name", deviceClass.name());
variant.insert("id", deviceClass.id());
QVariantList stateTypes;
foreach (const StateType &stateType, deviceClass.states()) {
QVariantMap stateMap;
stateMap.insert("id", stateType.id().toString());
stateMap.insert("name", stateType.name());
stateMap.insert("type", QVariant::typeToName(stateType.type()));
stateTypes.append(stateMap);
}
QVariantList triggerTypes;
foreach (const TriggerType &triggerType, deviceClass.triggers()) {
QVariantMap triggerMap;
triggerMap.insert("id", triggerType.id().toString());
triggerMap.insert("name", triggerType.name());
triggerMap.insert("params", triggerType.parameters());
triggerTypes.append(triggerMap);
}
QVariantList actionTypes;
foreach (const ActionType &actionType, deviceClass.actions()) {
QVariantMap actionMap;
actionMap.insert("id", actionType.id().toString());
actionMap.insert("name", actionType.name());
actionMap.insert("params", actionType.parameters());
actionTypes.append(actionMap);
}
variant.insert("params", deviceClass.params());
variant.insert("states", stateTypes);
variant.insert("triggers", triggerTypes);
variant.insert("actions", actionTypes);
return variant;
}
QString pluginTypeRef()
{
return "$ref:PluginType";
}
QVariantMap pluginTypeDescription()
{
QVariantMap pluginDescription;
pluginDescription.insert("id", "uuid");
pluginDescription.insert("name", "string");
QVariantList params;
params.append(paramTypeRef());
pluginDescription.insert("params", params);
return pluginDescription;
}
QVariantMap packPlugin(DevicePlugin *plugin)
{
}
QString deviceRef()
{
return "$ref:Device";
}
QVariantMap deviceDescription()
{
QVariantMap deviceDescription;
deviceDescription.insert("id", "uuid");
deviceDescription.insert("deviceClassId", "uuid");
deviceDescription.insert("name", "string");
QVariantList params;
params.append(paramRef());
deviceDescription.insert("params", params);
return deviceDescription;
}
QVariantMap packDevice(Device *device)
{
QVariantMap variant;
variant.insert("id", device->id());
variant.insert("deviceClassId", device->deviceClassId());
variant.insert("name", device->name());
variant.insert("params", device->params());
return variant;
}
QString ruleRef()
{
return "$ref:Rule";
}
QVariantMap ruleDescription()
{
QVariantMap ruleDescription;
ruleDescription.insert("id", "uuid");
ruleDescription.insert("trigger", triggerRef());
QVariantList actions;
actions.append(actionRef());
ruleDescription.insert("actions", actions);
QVariantList states;
states.append(stateRef());
ruleDescription.insert("states", states);
return ruleDescription;
}
//QVariantMap packRule(const Rule &rule);
bool validateMap(const QVariantMap &templateMap, const QVariantMap &map)
{
foreach (const QString &key, templateMap.keys()) {
if (!map.contains(key)) {
qDebug() << "missing key" << key << templateMap << map;
return false;
}
if (!validateVariant(templateMap.value(key), map.value(key))) {
qDebug() << "Object not matching template";
return false;
}
}
return true;
}
bool validateProperty(const QVariant &templateValue, const QVariant &value)
{
if (templateValue == "uuid") {
return value.canConvert(QVariant::Uuid);
}
if (templateValue == "string") {
return value.canConvert(QVariant::String);
}
if (templateValue == "bool") {
return value.canConvert(QVariant::Bool);
}
qWarning() << "Unhandled property type!" << templateValue;
return false;
}
bool validateList(const QVariantList &templateList, const QVariantList &list)
{
Q_ASSERT(templateList.count() == 1);
QVariant entryTemplate = templateList.first();
qDebug() << "validating list" << templateList;
for (int i = 0; i < list.count(); ++i) {
QVariant listEntry = list.at(i);
if (!validateVariant(entryTemplate, listEntry)) {
qDebug() << "List entry not matching template";
return false;
}
}
return true;
}
bool validateVariant(const QVariant &templateVariant, const QVariant &variant)
{
switch(templateVariant.type()) {
case QVariant::String:
if (templateVariant.toString().startsWith("$ref:")) {
QString refName = templateVariant.toString();
if (refName == JsonTypes::actionRef()) {
qDebug() << "validating action";
if (!validateMap(actionDescription(), variant.toMap())) {
qDebug() << "Error validating action";
return false;
}
} else if (refName == JsonTypes::triggerRef()) {
if (!validateMap(triggerDescription(), variant.toMap())) {
qDebug() << "trigger not valid";
return false;
}
} else if (refName == deviceRef()) {
if (!validateMap(deviceDescription(), variant.toMap())) {
qDebug() << "device not valid";
return false;
}
} else if (refName == deviceClassRef()) {
if (!validateMap(deviceClassDescription(), variant.toMap())) {
qDebug() << "device class not valid";
return false;
}
} else if (refName == paramTypeRef()) {
if (!validateMap(paramTypeDescription(), variant.toMap())) {
qDebug() << "param types not matching";
return false;
}
} else if (refName == actionTypeRef()) {
if (!validateMap(actionTypeDescription(), variant.toMap())) {
qDebug() << "action type not matching";
return false;
}
} else if (refName == triggerTypeRef()) {
if (!validateMap(triggerTypeDescription(), variant.toMap())) {
qDebug() << "trigger type not matching";
return false;
}
} else if (refName == stateTypeRef()) {
if (!validateMap(stateTypeDescription(), variant.toMap())) {
qDebug() << "state type not matching";
return false;
}
} else if (refName == pluginTypeRef()) {
if (!validateMap(pluginTypeDescription(), variant.toMap())) {
qDebug() << "plugin type not matching";
return false;
}
} else if (refName == ruleRef()) {
if (!validateMap(ruleDescription(), variant.toMap())) {
qDebug() << "rule type not matching";
return false;
}
} else if (refName == basicTypesRef()) {
if (!validateBasicType(variant)) {
qDebug() << "value not allowed in" << basicTypesRef();
return false;
}
} else {
qDebug() << "unhandled ref:" << refName;
return false;
}
} else {
if (!JsonTypes::validateProperty(templateVariant, variant)) {
qDebug() << "property not matching:" << templateVariant << "!=" << variant;
return false;
}
}
break;
case QVariant::Map:
if (!validateMap(templateVariant.toMap(), variant.toMap())) {
return false;
}
break;
case QVariant::List:
if (!validateList(templateVariant.toList(), variant.toList())) {
return false;
}
break;
default:
qDebug() << "unhandled value" << templateVariant;
return false;
}
return true;
}
bool validateBasicType(const QVariant &variant)
{
if (variant.canConvert(QVariant::Uuid)) {
return true;
}
if (variant.canConvert(QVariant::String)) {
return true;
}
if (variant.canConvert(QVariant::Int)) {
return true;
}
if (variant.canConvert(QVariant::Double)) {
return true;
}
if (variant.canConvert(QVariant::Bool)) {
return true;
}
return false;
}
}