#!/usr/bin/env python2 # # Copyright (c) 2016,2018 Cisco and/or its affiliates. # Licensed 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. from string import Template from jvpp_model import is_control_ping, is_control_ping_reply, is_dump, is_request, is_details, is_reply, is_event def generate_future_facade(work_dir, model, logger): logger.debug("Generating JVpp future facade for %s" % model.json_api_files) _generate_future_jvpp(work_dir, model), _generate_future_jvpp_facade(work_dir, model) _generate_future_jvpp_callback(work_dir, model) def _generate_future_jvpp(work_dir, model): with open("%s/FutureJVpp%s.java" % (work_dir, model.plugin_java_name), "w") as f: f.write(_FUTURE_JVPP_TEMPLATE.substitute( plugin_package=model.plugin_package, json_filename=model.json_api_files, plugin_name=model.plugin_java_name, methods=_generate_future_jvpp_methods(model) )) _FUTURE_JVPP_TEMPLATE = Template(''' package $plugin_package.future; /** *
Async facade extension adding specific methods for each request invocation
*
It was generated by jvpp_future_facade_gen.py based on $json_filename.
*/
public interface FutureJVpp${plugin_name} extends io.fd.vpp.jvpp.future.FutureJVppInvoker {
$methods
@Override
public $plugin_package.notification.${plugin_name}EventRegistry getEventRegistry();
}
''')
def _generate_future_jvpp_methods(model):
methods = []
for msg in model.messages:
if is_control_ping(msg) or is_control_ping_reply(msg):
# Skip control_ping managed by jvpp registry.
continue
reply_name = None
if is_request(msg):
reply_name = msg.reply_java
elif is_dump(msg):
# use reply dump wrappers
reply_name = "%sReplyDump" % msg.reply_java
else:
continue
methods.append(_FUTURE_JVPP_METHOD_TEMPLATE.substitute(
plugin_package=model.plugin_package,
method_name=msg.java_name_lower,
reply_name=reply_name,
request_name=msg.java_name_upper
))
return "".join(methods)
_FUTURE_JVPP_METHOD_TEMPLATE = Template('''
java.util.concurrent.CompletionStage<${plugin_package}.dto.${reply_name}> ${method_name}(${plugin_package}.dto.${request_name} request);
''')
def _generate_future_jvpp_facade(work_dir, model):
with open("%s/FutureJVpp%sFacade.java" % (work_dir, model.plugin_java_name), "w") as f:
f.write(_FUTURE_JVPP_FACADE_TEMPLATE.substitute(
plugin_package=model.plugin_package,
json_filename=model.json_api_files,
plugin_name=model.plugin_java_name,
methods=_generate_future_jvpp_facade_methods(model)
))
_FUTURE_JVPP_FACADE_TEMPLATE = Template('''
package $plugin_package.future;
/**
*
Implementation of FutureJVpp based on AbstractFutureJVppInvoker
*
It was generated by jvpp_future_facade_gen.py based on $json_filename.
*/
public class FutureJVpp${plugin_name}Facade extends io.fd.vpp.jvpp.future.AbstractFutureJVppInvoker implements FutureJVpp${plugin_name} {
private final $plugin_package.notification.${plugin_name}EventRegistryImpl eventRegistry = new $plugin_package.notification.${plugin_name}EventRegistryImpl();
/**
*
Create FutureJVpp${plugin_name}Facade object for provided JVpp instance. * Constructor internally creates FutureJVppFacadeCallback class for processing callbacks * and then connects to provided JVpp instance * * @param jvpp provided io.fd.vpp.jvpp.JVpp instance * * @throws java.io.IOException in case instance cannot connect to JVPP */ public FutureJVpp${plugin_name}Facade(final io.fd.vpp.jvpp.JVppRegistry registry, final io.fd.vpp.jvpp.JVpp jvpp) throws java.io.IOException { super(jvpp, registry, new java.util.HashMap<>()); java.util.Objects.requireNonNull(registry, "JVppRegistry should not be null"); registry.register(jvpp, new FutureJVpp${plugin_name}FacadeCallback(getRequests(), eventRegistry)); } @Override public $plugin_package.notification.${plugin_name}EventRegistry getEventRegistry() { return eventRegistry; } $methods } ''') def _generate_future_jvpp_facade_methods(model): methods = [] for msg in model.messages: if is_control_ping(msg) or is_control_ping_reply(msg): # Skip control_ping managed by jvpp registry. continue template = None if is_request(msg): template = _FUTURE_JVPP_FACADE_REQUEST_TEMPLATE elif is_dump(msg): template = _FUTURE_JVPP_FACADE_DUMP_TEMPLATE else: continue methods.append(template.substitute( plugin_package=model.plugin_package, method_name=msg.java_name_lower, reply_name=msg.reply_java, request_name=msg.java_name_upper )) return "".join(methods) _FUTURE_JVPP_FACADE_REQUEST_TEMPLATE = Template(''' @Override public java.util.concurrent.CompletionStage<${plugin_package}.dto.${reply_name}> ${method_name}(${plugin_package}.dto.${request_name} request) { return send(request); } ''') _FUTURE_JVPP_FACADE_DUMP_TEMPLATE = Template(''' @Override public java.util.concurrent.CompletionStage<${plugin_package}.dto.${reply_name}ReplyDump> ${method_name}(${plugin_package}.dto.${request_name} request) { return send(request, new ${plugin_package}.dto.${reply_name}ReplyDump()); } ''') def _generate_future_jvpp_callback(work_dir, model): with open("%s/FutureJVpp%sFacadeCallback.java" % (work_dir, model.plugin_java_name), "w") as f: f.write(_FUTURE_JVPP_CALLBACK_TEMPLATE.substitute( plugin_package=model.plugin_package, json_filename=model.json_api_files, plugin_name=model.plugin_java_name, methods=_generate_future_jvpp_callback_methods(model) )) _FUTURE_JVPP_CALLBACK_TEMPLATE = Template(""" package $plugin_package.future; /** *
Async facade callback setting values to future objects
*
It was generated by jvpp_future_facade_gen.py based on $json_filename.
*/
public final class FutureJVpp${plugin_name}FacadeCallback implements $plugin_package.callback.JVpp${plugin_name}GlobalCallback {
private final java.util.Map