VPP-120: add custom types support to jvpp

Generates java classes based on typeonly definitions
(hashcode, equals and toString methods are also included).

Adds JNI handling for request and reply messages
(also arrays of custom types).

Change-Id: I16f1cea17899704426aa083fad1cb800a8d115df
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
This commit is contained in:
Marek Gradzki
2016-09-29 13:22:35 +02:00
committed by Damjan Marion
parent c967a8239d
commit 81c7dfc1bb
10 changed files with 779 additions and 342 deletions

View File

@ -19,6 +19,7 @@ import importlib
import sys
import os
from jvppgen import types_gen
from jvppgen import callback_gen
from jvppgen import notification_gen
from jvppgen import dto_gen
@ -37,7 +38,6 @@ from jvppgen import util
#
# where
# defs_api_vpp_papi.py - vpe.api in python format (generated by vppapigen)
from jvppgen.util import vpp_2_jni_type_mapping
parser = argparse.ArgumentParser(description='VPP Java API generator')
parser.add_argument('-i', action="store", dest="inputfile")
@ -47,7 +47,7 @@ args = parser.parse_args()
sys.path.append(".")
print "args.inputfile %s" % args.inputfile
print "Generating Java API for %s" % args.inputfile
importdir = os.path.dirname(args.inputfile)
print "importdir %s" % importdir
inputfile = os.path.basename(args.inputfile)
@ -60,13 +60,6 @@ print "control_ping_class %s" % control_ping_class
sys.path.append(importdir)
cfg = importlib.import_module(inputfile, package=None)
# FIXME: functions unsupported due to problems with vpe.api
def is_supported(f_name):
return f_name not in {'vnet_ip4_fib_counters', 'vnet_ip6_fib_counters',
'lisp_adjacencies_get_reply', 'lisp_adjacencies_get'}
def is_request_field(field_name):
return field_name not in {'_vl_msg_id', 'client_index', 'context'}
@ -86,60 +79,52 @@ def get_args(t, filter):
def get_types(t, filter):
types_list = []
c_types_list = []
lengths_list = []
for i in t:
if not filter(i[1]):
continue
if len(i) is 3: # array type
types_list.append(vpp_2_jni_type_mapping[i[0]] + 'Array')
c_types_list.append(i[0] + '[]')
types_list.append(i[0] + '[]')
lengths_list.append((i[2], False))
elif len(i) is 4: # variable length array type
types_list.append(vpp_2_jni_type_mapping[i[0]] + 'Array')
c_types_list.append(i[0] + '[]')
types_list.append(i[0] + '[]')
lengths_list.append((i[3], True))
else: # primitive type
types_list.append(vpp_2_jni_type_mapping[i[0]])
c_types_list.append(i[0])
types_list.append(i[0])
lengths_list.append((0, False))
return types_list, c_types_list, lengths_list
return types_list, lengths_list
def get_definitions():
def get_definitions(defs):
# Pass 1
func_list = []
func_name = {}
for a in cfg.messages:
if not is_supported(a[0]):
continue
for a in defs:
java_name = util.underscore_to_camelcase(a[0])
# For replies include all the arguments except message_id
if util.is_reply(java_name):
types, c_types, lengths = get_types(a[1:], is_response_field)
types, lengths = get_types(a[1:], is_response_field)
func_name[a[0]] = dict(
[('name', a[0]), ('java_name', java_name),
('args', get_args(a[1:], is_response_field)), ('full_args', get_args(a[1:], lambda x: True)),
('types', types), ('c_types', c_types), ('lengths', lengths)])
('types', types), ('lengths', lengths)])
# For requests skip message_id, client_id and context
else:
types, c_types, lengths = get_types(a[1:], is_request_field)
types, lengths = get_types(a[1:], is_request_field)
func_name[a[0]] = dict(
[('name', a[0]), ('java_name', java_name),
('args', get_args(a[1:], is_request_field)), ('full_args', get_args(a[1:], lambda x: True)),
('types', types), ('c_types', c_types), ('lengths', lengths)])
('types', types), ('lengths', lengths)])
# Indexed by name
func_list.append(func_name[a[0]])
return func_list, func_name
func_list, func_name = get_definitions()
base_package = 'io.fd.vpp.jvpp'
plugin_package = base_package + '.' + plugin_name
types_package = 'types'
dto_package = 'dto'
callback_package = 'callback'
notification_package = 'notification'
@ -148,6 +133,11 @@ future_package = 'future'
callback_facade_package = 'callfacade'
control_ping_class_fqn = "%s.%s.%s" % (plugin_package, dto_package, control_ping_class)
types_list, types_name = get_definitions(cfg.types)
types_gen.generate_types(types_list, plugin_package, types_package, inputfile)
func_list, func_name = get_definitions(cfg.messages)
dto_gen.generate_dtos(func_list, base_package, plugin_package, plugin_name.title(), dto_package, args.inputfile)
jvpp_impl_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name, control_ping_class_fqn, dto_package, args.inputfile)
callback_gen.generate_callbacks(func_list, base_package, plugin_package, plugin_name.title(), callback_package, dto_package, args.inputfile)
@ -155,3 +145,5 @@ notification_gen.generate_notification_registry(func_list, base_package, plugin_
jvpp_c_gen.generate_jvpp(func_list, plugin_name, args.inputfile)
jvpp_future_facade_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name.title(), dto_package, callback_package, notification_package, future_package, args.inputfile)
jvpp_callback_facade_gen.generate_jvpp(func_list, base_package, plugin_package, plugin_name.title(), dto_package, callback_package, notification_package, callback_facade_package, args.inputfile)
print "Java API for %s generated successfully" % args.inputfile