#!/usr/bin/env ruby # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Usage: output_directory xml_spec_file [xml_spec_file...] # $: << '..' require 'cppgen' class OperationsInvokerGen < CppGen def initialize(chassis, outdir, amqp) super(outdir, amqp) @chassis=chassis @ops="AMQP_#{@chassis.caps}Operations" @classname="#{@ops}::Invoker" @filename="qpid/framing/#{@chassis.caps}Invoker" end def methods_on(parent, chassis) chassis == "all" ? parent.methods_ : parent.methods_on(chassis) end def handler(c) "#{@ops}::#{c.cppname}Handler"; end def getter(c) "get#{c.cppname}Handler"; end def invoker(c) "#{handler(c)}::Invoker"; end def visit_methods(c) methods_on(c, @chassis).select { |m| !m.content } end def handler_visits_cpp(c) visit_methods(c).each { |m| scope("void #{invoker(c)}::visit(const #{m.body_name}& body) {") { if (m.result) genl "this->encode(body.invoke(target), result.result);" else genl "body.invoke(target);" end genl "result.handled=true;" } } end def ops_visits_cpp() @amqp.classes.each { |c| visit_methods(c).each { |m| scope("void #{@classname}::visit(const #{m.body_name}& body) {") { genl "#{handler(c)}::Invoker invoker(*target.#{getter(c)}());" genl "body.accept(invoker);" genl "result=invoker.getResult();" } } } end def invoker_h(invoker, target, methods) return if methods.empty? genl cpp_extern_class("QPID_COMMON_CLASS_EXTERN", invoker, "public qpid::framing::Invoker") { genl "#{target}& target;" public genl("Invoker(#{target}& target_) : target(target_) {}") genl "using MethodBodyDefaultVisitor::visit;" methods.each { |m| genl "QPID_COMMON_EXTERN void visit(const #{m.body_name}& body);" } } end def generate() h_file(@filename) { include "qpid/framing/#{@ops}" include "qpid/framing/Invoker.h" include "qpid/CommonImportExport.h" namespace("qpid::framing") { # AMQP_*Operations invoker. methods=@amqp.classes.map { |c| visit_methods(c).to_a }.flatten invoker_h(@classname, @ops, methods) # AMQP_*Operations::*Handler invokers. @amqp.classes.each { |c| invoker_h(invoker(c), handler(c), visit_methods(c)) } } } cpp_file(@filename) { include @filename @amqp.classes.each { |c| visit_methods(c).each { |m| include "qpid/framing/#{m.body_name}" }} namespace("qpid::framing") { ops_visits_cpp @amqp.classes.each { |c| next if visit_methods(c).empty? handler_visits_cpp(c) } } } end end OperationsInvokerGen.new("client",$outdir, $amqp).generate() OperationsInvokerGen.new("server",$outdir, $amqp).generate() OperationsInvokerGen.new("all",$outdir, $amqp).generate()