Commit 3e00e466 authored by Wouter's avatar Wouter

Essential support for RPC methods introspection etc

parent d196babc
......@@ -24,6 +24,7 @@
#include "lib/metacode/constructor.h"
#include "lib/metacode/innertype.h"
#include "lib/metacode/notification.h"
#include "lib/metacode/rpcmethod.h"
#include "lib/metacode/wrappertype.h"
#include "lib/metacode/uniontype.h"
#include "lib/metacode/type.h"
......@@ -78,6 +79,8 @@ Introspector::Introspector(QObject *parent)
qRegisterMetaType<QList<InnerType*>>();
qRegisterMetaType<Notification*>();
qRegisterMetaType<QList<Notification*>>();
qRegisterMetaType<RpcMethod*>();
qRegisterMetaType<QList<RpcMethod*>>();
Grantlee::registerMetaType<Type::Inheritance>();
Grantlee::registerMetaType<EnumVariable>();
qRegisterMetaType<Initializer*>();
......@@ -268,8 +271,13 @@ bool Introspector::load(const QString& file)
break;
}
case JsonMethod:
case JsonMethod: {
ClassMember *rpcMethod = introspectMethod(item.id, item.data, main);
if (rpcMethod != 0) {
main->addMember(rpcMethod);
}
break;
}
case JsonNotification: {
ClassMember *notification = introspectNotification(item.id, item.data, main);
......@@ -575,6 +583,59 @@ QString Introspector::resolveJsonType(const QVariantMap &typeData) const
return typeName;
}
RpcMethod* Introspector::introspectMethod(const QString& id, const QVariantMap& data, Class* containerClass)
{
if (!data.contains("type") || data.value("type").toString() != "method") {
// Don't know what to do
return 0;
}
RpcMethod *method = new RpcMethod(makeIdentifier(id), containerClass);
if (data.contains("description")) {
method->setDocumentation(data.value("description").toString());
}
QVariantList parameters = data.value("params").toList();
QVariantList::ConstIterator pi;
qDebug() << tr("RPC Method parameter count: %1").arg(parameters.count());
for (pi = parameters.constBegin(); pi != parameters.constEnd(); ++pi) {
QVariantMap parameterMap = (*pi).toMap();
QString name = parameterMap.value("name").toString();
QString innerId = makeIdentifier(id) + "_" + capitalize(name);
qDebug() << tr("Scanning parameter %1 as type %2").arg(name, innerId);
Type *type = internalType(innerId, parameterMap, containerClass);
Q_ASSERT(type);
// Show warning if type is null type
if (isNullType(type)) {
qWarning(tr("Notification %1 parameter %2 declared as null type. This is a violation of JSON Schema. Skipping parameter.")
.arg(id, name).toLocal8Bit());
continue;
}
// Register anonymous types as nested types
if (type->isAnonymous()) {
InnerType *inner = new InnerType(type, containerClass);
containerClass->addMember(inner);
}
// Now construct the parameter
Field *parameter = new Field(name, type, Type::Public, containerClass);
// If not required: set default value
if (data.contains("required") && !data.value("required").toBool()) {
// Use default constructor
parameter->setDefaultValue(type->fullName() + "()");
}
// And add parameter
method->addParameter(parameter);
}
return method;
}
Notification* Introspector::introspectNotification(const QString& id, const QVariantMap& data, Class* containerClass)
{
......
......@@ -20,6 +20,7 @@ class Array;
class WrapperType;
class UnionType;
class Notification;
class RpcMethod;
class Property;
class Introspector : public QObject
......@@ -131,6 +132,7 @@ private:
Property* introspectProperty(const QString& id, const QVariantMap& data, const QVariantMap& parentData, Class* parent);
Notification *introspectNotification(const QString& id, const QVariantMap& data, Class* containerClass);
RpcMethod *introspectMethod(const QString& id, const QVariantMap& data, Class* containerClass);
/**
* Prepare the code writer that allows writing project files
......
......@@ -13,6 +13,7 @@ set(libMetacode_SRCS
initializer.cpp
field.cpp
property.cpp
rpcmethod.cpp
notification.cpp
array.cpp
wrappertype.cpp
......
......@@ -25,6 +25,8 @@
#include "lib/metacode/classmember.h"
#include "lib/metacode/field.h"
#include "lib/metacode/method.h"
#include "lib/metacode/rpcmethod.h"
#include "lib/metacode/notification.h"
#include "lib/metacode/constructor.h"
#include "lib/metacode/innertype.h"
#include "lib/metacode/property.h"
......@@ -112,6 +114,16 @@ QList< Method* > Class::methods() const
return membersSet<Method>();
}
QList< RpcMethod* > Class::rpcMethods() const
{
return membersSet<RpcMethod>();
}
QList< Notification* > Class::notifications() const
{
return membersSet<Notification>();
}
QList< Constructor* > Class::constructors() const
{
return membersSet<Constructor>();
......
......@@ -33,6 +33,8 @@
namespace QJsonIntrospect {
class Field;
class Method;
class RpcMethod;
class Notification;
class Constructor;
class Property;
class InnerType;
......@@ -52,6 +54,8 @@ class Class : public Type
Q_PROPERTY(QJsonIntrospect::SortedMembersList sortedMembers READ sortedMembers STORED false)
Q_PROPERTY(QList<QJsonIntrospect::Field *> fields READ fields STORED false)
Q_PROPERTY(QList<QJsonIntrospect::Method* > methods READ methods STORED false)
Q_PROPERTY(QList<QJsonIntrospect::RpcMethod* > rpcMethods READ rpcMethods STORED false)
Q_PROPERTY(QList<QJsonIntrospect::Notification* > notifications READ notifications STORED false)
Q_PROPERTY(QList<QJsonIntrospect::Constructor* > constructors READ constructors STORED false)
Q_PROPERTY(QList<QJsonIntrospect::Property *> properties READ properties STORED false)
Q_PROPERTY(QList<QJsonIntrospect::InnerType *> innerTypes READ innerTypes STORED false)
......@@ -101,6 +105,8 @@ public:
SortedMembersList sortedMembers() const;
QList< QJsonIntrospect::Field* > fields() const;
QList< QJsonIntrospect::Method* > methods() const;
QList< QJsonIntrospect::RpcMethod* > rpcMethods() const;
QList< QJsonIntrospect::Notification* > notifications() const;
QList< QJsonIntrospect::Constructor* > constructors() const;
QList< QJsonIntrospect::Property* > properties() const;
QList< QJsonIntrospect::InnerType* > innerTypes() const;
......
/*
* <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2015 W. Haffmans <wouter@simply-life.net>
*
* This program 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, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "rpcmethod.h"
using namespace QJsonIntrospect;
RpcMethod::RpcMethod(const QString& name, QJsonIntrospect::Class* parent)
: Method(name, parent)
{
}
RpcMethod::RpcMethod(const QString& name, Type::ProtectionLevel protectionLevel, Class* parent)
: Method(name, "void", protectionLevel, parent)
{
}
RpcMethod::~RpcMethod()
{
}
#include "moc_rpcmethod.cpp"
/*
* <one line to give the program's name and a brief idea of what it does.>
* Copyright (C) 2015 W. Haffmans <wouter@simply-life.net>
*
* This program 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, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef QJSONINTROSPECT_RPCMETHOD_H
#define QJSONINTROSPECT_RPCMETHOD_H
#include "lib/metacode/method.h"
namespace QJsonIntrospect {
/**
* Indicates an RPC Method. Basically just a method, but tagged separately so code writers
* can generate the method body better.
*/
class RpcMethod : public QJsonIntrospect::Method
{
Q_OBJECT
public:
RpcMethod(const QString& name, QJsonIntrospect::Class* parent);
RpcMethod(const QString& name, QJsonIntrospect::Type::ProtectionLevel protectionLevel, QJsonIntrospect::Class* parent);
virtual ~RpcMethod();
private:
};
}
Q_DECLARE_METATYPE(QJsonIntrospect::RpcMethod*)
Q_DECLARE_METATYPE(QList<QJsonIntrospect::RpcMethod*>)
#endif // QJSONINTROSPECT_RPCMETHOD_H
......@@ -38,7 +38,6 @@ class {{ class.className }}
{% endfilter %}
{% endfilter %}
{% endfor %}
{% endfor %}
......@@ -61,10 +60,23 @@ class {{ class.className }}
{# Default public data-loader #}
public:
virtual void Load(const QVariantMap &data);
virtual void load(const QVariantMap &data);
private:
void LoadOwnData(const QVariantMap &data);
void loadOwnData(const QVariantMap &data);
{# QVariant conversion #}
public:
QVariant toVariant() const;
operator QVariant() const {
return toVariant();
};
{% if not class.rpcMethods|length_is:0 %}
protected:
virtual QVariantMap doCall(const QString& methodName, const QVariantMap& parameters) = 0;
{% endif %}
public:
virtual ~{{ class.className }}();
......
......@@ -21,19 +21,19 @@
{
{{ member.body }}
{% for item in class.inheritance %}{% if item.type.isIntrospected %}
{{ item.type.fullName }}::Load(data);
{{ item.type.fullName }}::load(data);
{% endif %}{% endfor %}
LoadOwnData(data);
loadOwnData(data);
}
void {{ class.fullName }}::Load(const QVariantMap &data) {
void {{ class.fullName }}::load(const QVariantMap &data) {
{% for item in class.inheritance %}{% if item.type.isIntrospected %}
{{ item.type.fullName }}::Load(data);
{{ item.type.fullName }}::load(data);
{% endif %}{% endfor %}
LoadOwnData(data);
loadOwnData(data);
}
void {{ class.fullName }}::LoadOwnData(const QVariantMap &data) {
void {{ class.fullName }}::loadOwnData(const QVariantMap &data) {
{% for field in class.fields %}
if (data.contains("{{ field.originalName }}")) {
{% evalto src %}data.value("{{ field.originalName }}"){% evaltosplit %}
......@@ -45,13 +45,31 @@
{% endevalto %}
{% endevalto %}
// QVariant conversion
QVariant {{ class.fullName }}::toVariant() const {
// TODO
return QVariant();
};
{% case "RpcMethod" %}
{% if not member.isInline %}{% if not member.isPureVirtual %}
{{ member.returnType.signature }} {{ class.fullName }}::{{ member.name }}({% for param in member.parameters %}{% if not forloop.first %}, {% endif %}{{ param.type.signature }} {{ param.name }}{% endfor %}){% if member.isConst %} const{% endif %} {
QVariantMap data;
{% for param in member.parameters %}
// data.insert("{{ param.name }}", {{param.name}}.toVariant());
{% endfor %}
doCall("{{ member.name }}", data);
}
{% endif %}{% endif %}{# inline, pureVirtual #}
{% case "Method" %}
{% if not member.isInline %}{% if not member.isPureVirtual %}
{{ member.returnType.signature }} {{ class.fullName }}::{{ member.name }}({% for param in member.parameters %}{% if not forloop.first %}, {% endif %}{{ param.type.signature }} {{ param.name }}{% endfor %}){% if member.isConst %} const{% endif %} {
{{ member.body }}
}
{% endif %}{% endif %}
{% endif %}{% endif %}{# inline, pureVirtual #}
{% endswitch %}
{% endfor %}
......
......@@ -25,7 +25,7 @@
*/
{% if member.isExplicit %}explicit {% endif %}{{ member.name }}(const QVariantMap &data{% for param in member.parameters %}, {{ param.type.signature }} {{ param.name }}{% if param.defaultValue %} = {{ param.defaultValue }}{% endif %}{% endfor %});
{% endfilter %}
{% case "Method" "Notification" %}
{% case "Method" "RpcMethod" "Notification" %}
{% filter indent:0 %}
{% if member.isInline %}inline {% endif %}{% if member.isStatic %}static {% endif %}{% if member.isVirtual %}virtual {% endif %}{{ member.returnType.signature }} {{ member.name }}({% for param in member.parameters %}{% if not forloop.first %}, {% endif %}{{ param.type.signature }} {{ param.name }}{% if param.defaultValue %} = {{ param.defaultValue }}{% endif %}{% endfor %}){% if member.isConst %} const{% endif %}{% if member.isPureVirtual %} = 0{% endif %}{% if member.isInline %} {
{{ member.body }}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment