QJsonValue QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex,
                                              const QJsonArray &args)
{
    const QMetaMethod &method = object->metaObject()->method(methodIndex);

    if (method.name() == QByteArrayLiteral("deleteLater")) {
        // invoke `deleteLater` on wrapped QObject indirectly
        deleteWrappedObject(object);
        return QJsonValue();
    } else if (!method.isValid()) {
        qWarning() << "Cannot invoke unknown method of index" << methodIndex << "on object" << object << '.';
        return QJsonValue();
    } else if (method.access() != QMetaMethod::Public) {
        qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.';
        return QJsonValue();
    } else if (method.methodType() != QMetaMethod::Method && method.methodType() != QMetaMethod::Slot) {
        qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.';
        return QJsonValue();
    } else if (args.size() > 10) {
        qWarning() << "Cannot invoke method" << method.name() << "on object" << object << "with more than 10 arguments, as that is not supported by QMetaMethod::invoke.";
        return QJsonValue();
    } else if (args.size() > method.parameterCount()) {
        qWarning() << "Ignoring additional arguments while invoking method" << method.name() << "on object" << object << ':'
                   << args.size() << "arguments given, but method only takes" << method.parameterCount() << '.';
    }

    // construct converter objects of QVariant to QGenericArgument
    VariantArgument arguments[10];
    for (int i = 0; i < qMin(args.size(), method.parameterCount()); ++i) {
        QVariant arg = args.at(i).toVariant();
        if (method.parameterType(i) != QMetaType::QVariant && !arg.convert(method.parameterType(i))) {
            qWarning() << "Could not convert argument" << args.at(i) << "to target type" << method.parameterTypes().at(i) << '.';
        }
        arguments[i].value = arg;
    }

    // construct QGenericReturnArgument
    QVariant returnValue;
    if (method.returnType() != qMetaTypeId<QVariant>() && method.returnType() != qMetaTypeId<void>()) {
        // Only init variant with return type if its not a variant itself, which would
        // lead to nested variants which is not what we want.
        // Also, skip void-return types for obvious reasons (and to prevent a runtime warning inside Qt).
        returnValue = QVariant(method.returnType(), 0);
    }
    QGenericReturnArgument returnArgument(method.typeName(), returnValue.data());

    // now we can call the method
    method.invoke(object, returnArgument,
                  arguments[0], arguments[1], arguments[2], arguments[3], arguments[4],
                  arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]);

    return wrapResult(returnValue);
}
/*!
Function for executing a slot that does not take parameters
*/
QString ObjectService::doCallMethod(TasCommand* command, QObject* target, QString& errorString)
{
    Q_ASSERT(command->name() == "CallMethod");

    QString methodName = command->parameter("method_name");
    TasLogger::logger()->debug("name: " + methodName);
    int methodId = target->metaObject()->indexOfMethod(
                QMetaObject::normalizedSignature(methodName.toLatin1()).constData());
    if (methodId == -1){
        errorString.append(methodName + " method not found on object. ");
        TasLogger::logger()->debug("...method not found on object");
    }
    else{
        QMetaMethod metaMethod = target->metaObject()->method(methodId);
        QVariantList args = parseArguments(command);
        QList<QGenericArgument> arguments;
        for (int i = 0; i < args.size(); i++) {
            QVariant& argument = args[i];
            QGenericArgument genericArgument(
                QMetaType::typeName(argument.userType()),
                const_cast<void*>(argument.constData()));
            arguments << genericArgument;
        }

        QVariant returnValue(QMetaType::type(metaMethod.typeName()),
                             static_cast<void*>(NULL));
        QGenericReturnArgument returnArgument(
            metaMethod.typeName(),
            const_cast<void*>(returnValue.constData()));

        if (!metaMethod.invoke(
                target,
                Qt::AutoConnection, // In case the object is in another thread.
                returnArgument,
                arguments.value(0),
                arguments.value(1),
                arguments.value(2),
                arguments.value(3),
                arguments.value(4),
                arguments.value(5),
                arguments.value(6),
                arguments.value(7),
                arguments.value(8),
                arguments.value(9))) {
            errorString.append(methodName + " method invocation failed! ");
        } else {
            return returnValue.toString();
        }
    }
    return QString("");
}