nymea/server/jsonrpc/jsonhandler.cpp

270 lines
8.1 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::JsonHandler
\brief This class represents an interface for developing a handler for the JSON-RPC API.
\ingroup json
\inmodule core
\sa JsonRPCServer, JsonReply
*/
#include "jsonhandler.h"
#include "loggingcategories.h"
#include <QMetaMethod>
#include <QDebug>
#include <QRegExp>
namespace guhserver {
/*! Constructs a new \l JsonHandler with the given \a parent. */
JsonHandler::JsonHandler(QObject *parent) :
QObject(parent)
{
}
/*! Returns a map with all supported methods, notifications and types for the given meta \a type. */
QVariantMap JsonHandler::introspect(QMetaMethod::MethodType type)
{
QVariantMap data;
for (int i = 0; i < metaObject()->methodCount(); ++i) {
QMetaMethod method = metaObject()->method(i);
if (method.methodType() != type) {
continue;
}
switch (method.methodType()) {
case QMetaMethod::Method: {
if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name()) || !m_returns.contains(method.name())) {
continue;
}
qCDebug(dcJsonRpc) << "got method" << method.name();
QVariantMap methodData;
methodData.insert("description", m_descriptions.value(method.name()));
methodData.insert("params", m_params.value(method.name()));
methodData.insert("returns", m_returns.value(method.name()));
data.insert(name() + "." + method.name(), methodData);
break;
}
case QMetaMethod::Signal: {
if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name())) {
continue;
}
if (QString(method.name()).contains(QRegExp("^[A-Z]"))) {
qCDebug(dcJsonRpc) << "got signal" << method.name();
QVariantMap methodData;
methodData.insert("description", m_descriptions.value(method.name()));
methodData.insert("params", m_params.value(method.name()));
data.insert(name() + "." + method.name(), methodData);
}
break;
default:
;;// Nothing to do for slots
}
}
}
return data;
}
/*! Returns true if this \l JsonHandler has a method with the given \a methodName.*/
bool JsonHandler::hasMethod(const QString &methodName)
{
return m_descriptions.contains(methodName) && m_params.contains(methodName) && m_returns.contains(methodName);
}
QPair<bool, QString> JsonHandler::validateParams(const QString &methodName, const QVariantMap &params)
{
QVariantMap paramTemplate = m_params.value(methodName);
return JsonTypes::validateMap(paramTemplate, params);
}
QPair<bool, QString> JsonHandler::validateReturns(const QString &methodName, const QVariantMap &returns)
{
QVariantMap returnsTemplate = m_returns.value(methodName);
return JsonTypes::validateMap(returnsTemplate, returns);
}
void JsonHandler::setDescription(const QString &methodName, const QString &description)
{
for(int i = 0; i < metaObject()->methodCount(); ++i) {
QMetaMethod method = metaObject()->method(i);
if (method.name() == methodName) {
m_descriptions.insert(methodName, description);
return;
}
}
qCWarning(dcJsonRpc) << "Cannot set description. No such method:" << methodName;
}
void JsonHandler::setParams(const QString &methodName, const QVariantMap &params)
{
for(int i = 0; i < metaObject()->methodCount(); ++i) {
QMetaMethod method = metaObject()->method(i);
if (method.name() == methodName) {
m_params.insert(methodName, params);
return;
}
}
qCWarning(dcJsonRpc) << "Cannot set params. No such method:" << methodName;
}
void JsonHandler::setReturns(const QString &methodName, const QVariantMap &returns)
{
for(int i = 0; i < metaObject()->methodCount(); ++i) {
QMetaMethod method = metaObject()->method(i);
if (method.name() == methodName) {
m_returns.insert(methodName, returns);
return;
}
}
qCWarning(dcJsonRpc) << "Cannot set returns. No such method:" << methodName;
}
JsonReply *JsonHandler::createReply(const QVariantMap &data) const
{
return JsonReply::createReply(const_cast<JsonHandler*>(this), data);
}
JsonReply* JsonHandler::createAsyncReply(const QString &method) const
{
return JsonReply::createAsyncReply(const_cast<JsonHandler*>(this), method);
}
QVariantMap JsonHandler::statusToReply(DeviceManager::DeviceError status) const
{
QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
return returns;
}
QVariantMap JsonHandler::statusToReply(RuleEngine::RuleError status) const
{
QVariantMap returns;
returns.insert("ruleError", JsonTypes::ruleErrorToString(status));
return returns;
}
QVariantMap JsonHandler::statusToReply(Logging::LoggingError status) const
{
QVariantMap returns;
returns.insert("loggingError", JsonTypes::loggingErrorToString(status));
return returns;
}
/*!
\class guhserver::JsonReply
\brief This class represents a reply for the JSON-RPC API request.
\ingroup json
\inmodule core
\sa JsonHandler, JsonRPCServer
*/
JsonReply::JsonReply(Type type, JsonHandler *handler, const QString &method, const QVariantMap &data):
m_type(type),
m_data(data),
m_handler(handler),
m_method(method),
m_timedOut(false)
{
connect(&m_timeout, &QTimer::timeout, this, &JsonReply::timeout);
}
JsonReply *JsonReply::createReply(JsonHandler *handler, const QVariantMap &data)
{
return new JsonReply(TypeSync, handler, QString(), data);
}
JsonReply *JsonReply::createAsyncReply(JsonHandler *handler, const QString &method)
{
return new JsonReply(TypeAsync, handler, method);
}
JsonReply::Type JsonReply::type() const
{
return m_type;
}
QVariantMap JsonReply::data() const
{
return m_data;
}
void JsonReply::setData(const QVariantMap &data)
{
m_data = data;
}
JsonHandler *JsonReply::handler() const
{
return m_handler;
}
QString JsonReply::method() const
{
return m_method;
}
QUuid JsonReply::clientId() const
{
return m_clientId;
}
void JsonReply::setClientId(const QUuid &clientId)
{
m_clientId = clientId;
}
int JsonReply::commandId() const
{
return m_commandId;
}
void JsonReply::setCommandId(int commandId)
{
m_commandId = commandId;
}
void JsonReply::startWait()
{
m_timeout.start(10000);
}
void JsonReply::timeout()
{
m_timedOut = true;
emit finished();
}
bool JsonReply::timedOut() const
{
return m_timedOut;
}
}