def write_param_validation(self, param, param_name, fail_statement, out, level=0): if not param.mandatory and ( param.restricted or param.restrictedArray or (param.struct and any( map(lambda x: x.restricted, self.structs[param.fulltype])))): out.write("if (%s.presence) {\n" % param_name) param_copy = copy(param) param_copy.mandatory = True with CodeBlock(out) as out: self.write_param_validation(param_copy, param_name + ".val", fail_statement, out, level + 1) out.write("}\n") elif param.array: if param.minSize > 0: out.write("if ({0}.count() < {1}) {{ {2}; }}\n".format( param_name, param.minSize, fail_statement)) if param.maxSize != None: out.write("if ({0}.count() > {1}) {{ {2}; }}\n".format( param_name, param.maxSize, fail_statement)) if param.restricted: out.write( 'for ({0}::const_iterator it_{2} = {1}.begin(); it_{2} != {1}.end(); ++it_{2}) {{\n' .format(self.qt_param_type(param), param_name, level)) with CodeBlock(out) as out: param_copy = copy(param) param_copy.array = False self.write_param_validation(param_copy, "(*it_{0})".format(level), fail_statement, out, level + 1) out.write("}\n") elif param.struct: for p in self.structs[param.fulltype]: self.write_param_validation( p, "{0}.{1}".format(param_name, p.name), fail_statement, out, level + 1) elif param.type == "Integer" or param.type == "Float": conditions = [] if (param.minValue != None): conditions.append("(%s < %s)" % (param_name, param.minValue)) if (param.maxValue != None): conditions.append("(%s > %s)" % (param_name, param.maxValue)) if conditions: out.write('if (%s) { %s; }\n' % (' || '.join(conditions), fail_statement)) elif param.type == "String": conditions = [] if (param.minLength > 0): conditions.append("(%s.size() < %s)" % (param_name, param.minLength)) if (param.maxLength > 0): conditions.append("(%s.size() > %s)" % (param_name, param.maxLength)) if conditions: out.write('if (%s) { %s; }\n' % (' || '.join(conditions), fail_statement))
def make_requests_for_source(self, out): for interface_el in self.el_tree.findall('interface'): request_responses = self.find_request_response_pairs_by_provider(interface_el, "sdl") for (request, response) in request_responses: request_name = request.get('name') iface_name = interface_el.get('name') request_full_name = iface_name + '_' + request_name out.write('bool RequestToSDL::' + request_full_name + '(') for param_el in request.findall('param'): out.write('QVariant %s, ' % (param_el.get('name'))) out.write('Q%sValue hmi_callback) {\n' % prefix_class_item) with CodeBlock(out) as output: output.write('LOG4CXX_TRACE(logger_, "ENTER");\n') output.write('QList<QVariant> args;\n') for param_el in request.findall('param'): param = self.make_param_desc(param_el, iface_name) output.write('%s %s;\n' % (impl.qt_param_type(param), param.name + "_tmp")) output.write('if (VariantToValue(%s, %s)) {\n' % (param.name, param.name + '_tmp')) with CodeBlock(output) as out: self.write_param_validation(param, param.name + "_tmp", "\nLOG4CXX_ERROR(logger_, \"%s in %s out of bounds\");\nreturn false" % (param.name, request_full_name), out) out.write('args << QVariant::fromValue(%s);\n' % (param.name + '_tmp')) output.write('} else {\n') with CodeBlock(output) as out: out.write('LOG4CXX_ERROR(logger_, "%s in %s is NOT valid");\n' % (param.name, request_full_name)) out.write('return false;\n') out.write('}\n') output.write('new requests::' + request_full_name + '(hmi_callback, ' + interface_el.get('name') + ' , args, ' + '"' + request_name + '");\n') output.write('LOG4CXX_TRACE(logger_, "EXIT");\n') output.write('return true;\n') out.write('}\n\n')
def make_header_file(self, out): out.write("class RequestToSDL : public QObject\n") out.write("{\n") out.write(" public:\n") with CodeBlock(out) as output: output.write("explicit RequestToSDL(QObject *parent = 0);\n") output.write("~RequestToSDL();\n") impl.make_requests_for_header(out) out.write(" private:\n") with CodeBlock(out) as output: for interface_el in self.el_tree.findall('interface'): output.write('QDBusInterface *' + interface_el.get('name') + ';\n') out.write("};\n")
def make_source_file(self, out): out.write('RequestToSDL::RequestToSDL(QObject *parent) {\n') with CodeBlock(out) as output: output.write('QDBusConnection bus = QDBusConnection::sessionBus();\n') for interface_el in self.el_tree.findall('interface'): iface_name = interface_el.get('name') output.write(iface_name + ' = new QDBusInterface("com.ford.sdl.core", "/", "com.ford.sdl.core.' + iface_name + '", bus, this);\n') out.write('}\n\n') out.write('RequestToSDL::~RequestToSDL() {\n') with CodeBlock(out) as output: for interface_el in self.el_tree.findall('interface'): iface_name = interface_el.get('name') output.write(iface_name + '->deleteLater();\n') output.write('this->deleteLater();\n') out.write('}\n\n') impl.make_requests_for_source(out)
class Impl(FordXmlParser): def make_dbus_type_declarations(self, out): for struct in self.structs.items(): self.write_struct_declaration(struct, out) def make_dbus_metatype_declarations(self, out): for struct in self.structs.items(): self.write_struct_metatype_declaration(struct, out) def write_struct_declaration(self, ((iface, name), params), out): struct_name = "{0}_{1}".format(iface, name) out.write("struct {0} {{\n".format(struct_name)) with CodeBlock(out) as out: for param in params: out.write("{0} {1};\n".format(self.qt_param_type(param), param.name)) out.write("{0}()\n".format(struct_name)) initializersList = map(lambda x: "{0}({1})".format(x.name, defaultValue(x)), [p for p in params if p.type != "String" and not p.struct and not p.array]) if initializersList: out.write(": " + ",\n ".join(initializersList)) out.write("{ }\n") out.write("};\n") out.write('QDBusArgument& operator << (QDBusArgument&, const ' + struct_name + "&);\n") out.write('const QDBusArgument& operator >> (const QDBusArgument&, ' + struct_name + "&);\n") out.write('void PutArgToMap(QVariantMap& map, const char* name, const ' + struct_name + "& v);\n") out.write('QVariant ValueToVariant(const ' + struct_name + "& v);\n") out.write('QVariant ValueToVariant(const QList<' + struct_name + " >& v);\n") out.write('bool GetArgFromMap(const QVariantMap& map, const char* name, ' + struct_name + "& v);\n") out.write('bool VariantToValue(const QVariant& variant, ' + struct_name + "& v);\n") out.write('bool VariantToValue(const QVariant& variant, QList<' + struct_name + " >& v);\n")
def make_requests_for_header(self, out): for interface_el in self.el_tree.findall('interface'): request_responses = self.find_request_response_pairs_by_provider(interface_el, "sdl") for (request, response) in request_responses: all_params = list() for param_el in request.findall('param'): all_params.append(param_el) with CodeBlock(out) as output: output.write("Q_INVOKABLE bool %s_%s(" % (interface_el.get('name'), request.get('name'))) impl.args_for_function_definition(all_params, interface_el.get('name'), out) output.write(");\n")
def make_requests_classes_header(self, out): for interface_el in self.el_tree.findall('interface'): request_responses = self.find_request_response_pairs_by_provider( interface_el, "sdl") for (request, response) in request_responses: request_full_name = interface_el.get( 'name') + '_' + request.get('name') out.write('class ' + request_full_name + ': public HMIRequest {\n') with CodeBlock(out) as output: output.write('Q_OBJECT\n') out.write(' public:\n') with CodeBlock(out) as output: output.write( request_full_name + '(QJSValue hmi_callback, QDBusInterface *interface, QList<QVariant> args, QString name):\n' ) output.write( ' HMIRequest(hmi_callback, interface, args, name) {}\n' ) out.write(' private:\n') with CodeBlock(out) as output: output.write('QJSValueList fillArgsList();\n};\n\n')
def make_source_file(self, out): out.write("namespace requests {\n") for interface_el in self.el_tree.findall('interface'): for struct_el in interface_el.findall('struct'): out.write('template<>\n') out.write('QJSValue HMIRequest::CreateQJSValue(Common_' + struct_el.get('name') + ' value){\n') with CodeBlock(out) as output: output.write( 'QJSValue object = hmi_callback_.engine()->newObject();\n' ) for param_el in struct_el.findall('param'): param_name = param_el.get('name') if param_el.get('mandatory') == 'true': with CodeBlock(out) as output: output.write('object.setProperty("' + param_name + '", CreateQJSValue(value.' + param_name + '));\n') elif param_el.get('mandatory') == 'false': with CodeBlock(out) as output: output.write('object.setProperty("' + param_name + '", value.' + param_name + '.presence ? CreateQJSValue(value.' + param_name + '.val) : QJSValue());\n') out.write('return object;\n') out.write('}\n\n') out.write( 'HMIRequest::HMIRequest(QJSValue hmi_callback, QDBusInterface *interface, QList<QVariant> args, QString name) :\n' ) out.write( ' hmi_callback_(hmi_callback), interface_(interface), args_(args) {\n' ) with CodeBlock(out) as output: output.write( 'QDBusPendingCall pcall = interface->asyncCallWithArgumentList(name, args);\n' ) output.write('watcher_ = new QDBusPendingCallWatcher(pcall);\n') output.write( 'QObject::connect(watcher_, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(invokeCallback()));\n}\n\n' ) out.write('void HMIRequest::invokeCallback() {\n') with CodeBlock(out) as output: output.write('if (!hmi_callback_.isUndefined()) {\n') with CodeBlock(output) as output: output.write('QJSValueList qjsValueList;\n') output.write('qjsValueList = this->fillArgsList();\n') output.write('hmi_callback_.call(qjsValueList);\n') output.write('}\n') output.write('watcher_->deleteLater();\n') output.write('this->deleteLater();\n}\n\n') impl.make_requests_methods_source(out) out.write("} // namespace requests\n")
def make_requests_for_source(self, out): for interface_el in self.el_tree.findall('interface'): request_responses = self.find_request_response_pairs_by_provider( interface_el, "sdl") for (request, response) in request_responses: out.write('void RequestToSDL::' + request.get('name') + '(QString name, ') for param_el in request.findall('param'): out.write('QVariant ' + param_el.get('name') + ', ') out.write('QJSValue hmi_callback) {\n') with CodeBlock(out) as output: output.write('QList<QVariant> args;\n') for param_el in request.findall('param'): output.write('args << ' + param_el.get('name') + ';\n') output.write('new ' + interface_el.get('name') + '_' + request.get('name') + '(' + interface_el.get('name') + ', name, args, hmi_callback);\n}\n')
def make_requests_methods_source(self, out): for interface_el in self.el_tree.findall('interface'): request_responses = self.find_request_response_pairs_by_provider( interface_el, "sdl") for (request, response) in request_responses: iface_name = interface_el.get('name') request_full_name = iface_name + '_' + request.get('name') out.write('QJSValueList ' + request_full_name + '::fillArgsList() {\n') out.write(' QDBusPendingReply< ') count = 0 for param_el in response.findall('param'): param = self.make_param_desc(param_el, iface_name) out.write(self.qt_param_type(param)) count += 1 if count < len(response.findall('param')): out.write(',') out.write(' > reply = *watcher_;\n') with CodeBlock(out) as out: out.write('QJSValueList qjsValueList;\n\n') out.write('QJSValue param;\n\n') count = 0 for param_el in response.findall('param'): if param_el.get('mandatory') == 'false': out.write('if (reply.argumentAt<' + str(count) + '>().presence) {\n') out.write( ' param = CreateQJSValue(reply.argumentAt<' + str(count) + '>().val);\n') out.write('} else {\n') out.write(' param = QJSValue();\n') out.write('}\n') out.write('qjsValueList.append(param);\n') else: out.write( 'param = CreateQJSValue(reply.argumentAt<' + str(count) + '>());\n') out.write('qjsValueList.append(param);\n') count += 1 out.write('return qjsValueList;\n') out.write('}\n\n')
def make_header_file(self, out): out.write("namespace requests {\n") out.write("class HMIRequest: public QObject {\n") with CodeBlock(out) as output: output.write('Q_OBJECT\n') out.write('public:\n') with CodeBlock(out) as output: output.write( 'HMIRequest(QJSValue hmi_callback, QDBusInterface *interface, QList<QVariant> args, QString name );\n' ) out.write('protected:\n') with CodeBlock(out) as output: output.write('virtual QJSValueList fillArgsList() = 0;\n') output.write('QDBusPendingCallWatcher *watcher_;\n') output.write('QJSValue hmi_callback_;\n\n') output.write('template<typename T>\n') output.write('QJSValue CreateQJSValue(T value) {\n') output.write(' return QJSValue(value);\n') output.write('}\n\n') output.write('template<typename T>\n') output.write('QJSValue CreateQJSValue(QList<T> value) {\n') with CodeBlock(output) as output: output.write( 'QJSValue array = hmi_callback_.engine()->newArray();\n') output.write('int i = 0;\n') output.write('foreach (T item, value) {\n') output.write(' QJSValue value = CreateQJSValue(item);\n') output.write(' array.setProperty(i, value);\n') output.write(' ++i;\n') output.write('}\n') output.write('return array;\n') output.write('}\n') out.write('private:\n') with CodeBlock(out) as output: output.write('QDBusInterface *interface_;\n') output.write('QList<QVariant> args_;\n') out.write('public slots:\n') with CodeBlock(out) as output: output.write('void invokeCallback();\n') out.write('};\n\n') output.write('template<>\n') output.write( 'QJSValue HMIRequest::CreateQJSValue(QStringList value);\n') for (interface_name, struct_name) in self.structs: out.write('template<>\n') out.write('QJSValue HMIRequest::CreateQJSValue(Common_' + struct_name + ' value);\n\n') impl.make_requests_classes_header(out) out.write("} // namespace requests\n")
def write_adaptor_definition(self, interface_el, notifications, request_responses, out): global prefix_class_item iface_name = interface_el.get('name') classname = iface_name + 'Adaptor' out.write( "{0}::{0}(QObject* parent) : QDBusAbstractAdaptor(parent) {{}}\n". format(classname)) out.write("void {0}::SetApi(Q{1}Item* api) {{\n".format( classname, prefix_class_item)) with CodeBlock(out) as out: out.write("api_ = api;\n") for n in notifications: signame = n.get('name') signame = signame[:1].lower() + signame[1:] slotname = n.get('name') + '_qml' sig_signature = self.make_qml_signal_signature( n, iface_name, signame, True) slot_signature = self.make_qml_signal_signature( n, iface_name, slotname, True) out.write("connect(api_, SIGNAL(" + sig_signature + "), this, SLOT(" + slot_signature + "));\n") out.write( "LOG4CXX_TRACE(logger_, \"CONNECT SIGNALS: \" << __PRETTY_FUNCTION__ );\n" ) out.write("}\n\n") for (request, response) in request_responses: in_params = [ self.make_param_desc(x, iface_name) for x in request.findall('param') ] out_params = [ self.make_param_desc(x, iface_name) for x in response.findall('param') ] out.write( "bool fill{0}{1}Reply(QDBusMessage& message, const QVariantMap& map) {{\n" .format(classname, request.get('name'))) with CodeBlock(out) as out: out.write("int retCode_out = 0;\n") out.write("GetArgFromMap(map, \"__retCode\", retCode_out);\n") out.write( "QVariant retCode_arg = QVariant::fromValue(retCode_out);\n" ) out.write("message << retCode_arg;\n") out.write("QString userMessage_out;\n") out.write( "GetArgFromMap(map, \"__message\", userMessage_out);\n") out.write( "QVariant userMessage_arg = QVariant::fromValue(userMessage_out);\n" ) out.write("message << userMessage_arg;\n") for p in out_params: param_name = p.name param_type = self.qt_param_type(p) out.write("%s %s_out;\n" % (param_type, p.name)) out.write( "if (!GetArgFromMap(map, \"{0}\", {0}_out)) {{ return false; }}\n" .format(p.name)) self.write_param_validation(p, p.name + "_out", "return false", out) out.write("QVariant {0}_arg;\n".format(p.name)) out.write("{0}_arg.setValue({0}_out);\n".format(p.name)) out.write("message << {0}_arg;\n".format(p.name)) out.write( "LOG4CXX_DEBUG(logger_, \"Output arguments:\\n\" << QVariant(map));\n" ) out.write( "LOG4CXX_TRACE(logger_, \"REPLY ASYNC: \" << __PRETTY_FUNCTION__ );\n" ) out.write("return true;\n") out.write("}\n\n") out.write("{0} {{\n".format( self.make_method_signature(request, response, iface_name, True))) with CodeBlock(out) as out: out.write( "LOG4CXX_TRACE(logger_, \"ENTER: \" << __PRETTY_FUNCTION__ );\n" ) out.write("int ret = 0;\n") return_statement = "return ret;\n" out.write("QVariantMap in_arg;\n") out.write("QVariant out_arg_v;\n") for param in in_params: self.write_param_validation( param, param.name + "_in", "RaiseDbusError(this, InvalidData); return ret", out) out.write("PutArgToMap(in_arg, \"" + param.name + "\", " + param.name + "_in);\n") out.write( "LOG4CXX_DEBUG(logger_, \"Input arguments:\\n\" << in_arg);\n" ) method_name = request.get('name')[:1].lower() + request.get( 'name')[1:] out.write("dbusController->message = &message;\n") out.write("dbusController->fill = &fill{0}{1}Reply;\n".format( classname, request.get("name"))) out.write( """if (!QMetaObject::invokeMethod(api_, "{0}", Qt::{1}Connection, Q_RETURN_ARG(QVariant, out_arg_v), Q_ARG(QVariant, QVariant(in_arg)))) {{\n""" .format(method_name, invoke_type_connection)) with CodeBlock(out) as out: out.write("RaiseDbusError(this, InvalidData);\n") out.write("LOG4CXX_ERROR(logger_, \"Can't invoke method " + method_name + "\");\n ") out.write("return ret;\n") out.write("}\n") out.write("dbusController->message = NULL;\n") out.write("dbusController->fill = NULL;\n") out.write("if (message.isDelayedReply()) {\n") with CodeBlock(out) as out: out.write("return ret;\n") out.write("}\n") out.write("QVariantMap out_arg;\n") out.write("if (out_arg_v.type() == QVariant::Map) {\n") with CodeBlock(out) as out: out.write("out_arg = out_arg_v.toMap();\n") out.write("};\n") out.write("int err;\n") out.write( """if (GetArgFromMap(out_arg, "__errno", err)) { RaiseDbusError(this, err); return ret; }\n""" ) out.write("int async_uid;\n") out.write( "if (GetArgFromMap(out_arg, \"__async_uid\", async_uid)) {\n" ) with CodeBlock(out) as out: out.write("message.setDelayedReply(true);\n") out.write( "dbusController->addMessage(message, &fill%s%sReply, async_uid);\n" % (classname, request.get('name'))) out.write( "LOG4CXX_TRACE(logger_, \"EXIT ASYNC: \" << __PRETTY_FUNCTION__ );\n" ) out.write("return ret;\n") out.write("}\n\n") for param in out_params: out.write( "if (!GetArgFromMap(out_arg, \"{0}\", {0}_out)) {{ RaiseDbusError(this, InvalidData); return ret; }}\n" .format(param.name)) self.write_param_validation( param, param.name + "_out", "RaiseDbusError(this, InvalidData); return ret", out) out.write("GetArgFromMap(out_arg, \"__retCode\", ret);\n") out.write( "GetArgFromMap(out_arg, \"__message\", userMessage_out);\n" ) out.write( "LOG4CXX_DEBUG(logger_, \"Output arguments:\\n\" << QVariant(out_arg));\n" ) out.write( "LOG4CXX_TRACE(logger_, \"EXIT: \" << __PRETTY_FUNCTION__ );\n" ) out.write("return ret;\n") out.write("}\n\n") for n in notifications: slotname = n.get('name') + '_qml' slot_signature = self.make_qml_signal_signature( n, iface_name, slotname, False, True) out.write(slot_signature + " {\n") params = n.findall('param') out.write( " LOG4CXX_TRACE(logger_, \"EMIT SIGNAL: \" << __PRETTY_FUNCTION__ );\n" ) out.write(" LOG4CXX_DEBUG(logger_, \"Arguments:\\n{\"") for p in params[0:-1]: param = self.make_param_desc(p, iface_name) out.write(" << \" " + param.name + ":\" << " + param.name + " << \",\"") for p in params[-1:]: # last param without comma in end line p = params[-1] param = self.make_param_desc(p, iface_name) out.write(" << \" " + param.name + ":\" << " + param.name) out.write(" << \" }\");\n") for p in params: param = self.make_param_desc(p, iface_name) param_type = self.qt_param_type(param) param_name = 'p_' + param.name if param.mandatory: if param.array or (param.type not in [ 'Integer', 'String', 'Float', 'Boolean' ] and not param.enum): out.write(' ' + param_type + ' ' + param_name + ";\n") out.write(' if (!VariantToValue(' + param.name + ', ' + param_name + ")) {\n") out.write( " LOG4CXX_ERROR(logger_, \"Can't convert variant to value\");\n" ) out.write(" return;}\n") else: out.write(' ' + param_type + ' ' + param_name + ";\n") out.write(' ' + param_name + '.presence = !' + param.name + ".isNull();\n") out.write(' if (' + param_name + ".presence) {\n") out.write(' if (!VariantToValue(' + param.name + ', ' + param_name + ".val)) {\n") out.write( " LOG4CXX_ERROR(logger_, \"Can't convert variant to value\");\n" ) out.write(" return;\n }\n") out.write(" }\n") out.write(' emit ' + n.get('name') + '(') for i in range(len(params)): param = self.make_param_desc(params[i], iface_name) basic_type = (param.type in [ 'Integer', 'String', 'Float', 'Boolean' ]) or param.enum if param.array or (not param.mandatory) or (not basic_type): param_name = 'p_' + param.name else: param_name = param.name out.write(param_name) if i != len(params) - 1: out.write(', ') out.write(");\n") out.write("}\n\n")
out.write('Q_DECLARE_METATYPE(OptionalArgument<' + struct_name + ">)\n") out.write('Q_DECLARE_METATYPE(QList<' + struct_name + ">)\n") out.write('Q_DECLARE_METATYPE(OptionalArgument<QList<' + struct_name + "> >)\n\n") def make_dbus_type_definitions(self, out): for struct in self.structs.items(): self.write_struct_definition(struct, out) def write_struct_definition(self, ((iface, name), params), out): struct_name = iface + '_' + name out.write('QDBusArgument& operator << (QDBusArgument& arg, const ' + struct_name + "& v) {\n") with CodeBlock(out) as out: out.write("arg.beginStructure();\n") for param in params: out.write("arg << v.{0};\n".format(param.name)) out.write("arg.endStructure();\n") out.write("return arg;\n") out.write("}\n\n") out.write( 'const QDBusArgument& operator >> (const QDBusArgument& arg, ' + struct_name + "& v) {\n") with CodeBlock(out) as out: out.write("arg.beginStructure();\n") for param in params: out.write("arg >> v.{0};\n".format(param.name)) out.write("arg.endStructure();\n")