diff options
Diffstat (limited to 'vpp-api/java/jvpp/gen')
-rw-r--r-- | vpp-api/java/jvpp/gen/callback_gen.py | 19 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/dto_gen.py | 93 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/jvpp_c_gen.py | 36 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py | 52 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py | 128 | ||||
-rwxr-xr-x | vpp-api/java/jvpp/gen/jvpp_gen.py | 9 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/jvpp_impl_gen.py | 4 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/notification_gen.py | 164 | ||||
-rw-r--r-- | vpp-api/java/jvpp/gen/util.py | 22 |
9 files changed, 392 insertions, 135 deletions
diff --git a/vpp-api/java/jvpp/gen/callback_gen.py b/vpp-api/java/jvpp/gen/callback_gen.py index 8a0d20124ae..eadf3b5c50d 100644 --- a/vpp-api/java/jvpp/gen/callback_gen.py +++ b/vpp-api/java/jvpp/gen/callback_gen.py @@ -31,7 +31,7 @@ package $base_package.$callback_package; $docs * </pre> */ -public interface $cls_name extends $base_package.$callback_package.JVppCallback { +public interface $cls_name extends $base_package.$callback_package.$callback_type { $callback_method @@ -61,15 +61,21 @@ def generate_callbacks(func_list, base_package, callback_package, dto_package, i callbacks = [] for func in func_list: - if util.is_notification(func['name']) or util.is_ignored(func['name']): - # FIXME handle notifications + if util.is_ignored(func['name']): continue camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) - if not util.is_reply(camel_case_name_with_suffix): + if not util.is_reply(camel_case_name_with_suffix) and not util.is_notification(func['name']): continue - camel_case_name = util.remove_reply_suffix(camel_case_name_with_suffix) + if util.is_reply(camel_case_name_with_suffix): + camel_case_name = util.remove_reply_suffix(camel_case_name_with_suffix) + callback_type = "JVppCallback" + else: + camel_case_name_with_suffix = util.add_notification_suffix(camel_case_name_with_suffix) + camel_case_name = camel_case_name_with_suffix + callback_type = "JVppNotificationCallback" + callbacks.append("{0}.{1}.{2}".format(base_package, callback_package, camel_case_name + callback_suffix)) callback_path = os.path.join(callback_package, camel_case_name + callback_suffix + ".java") callback_file = open(callback_path, 'w') @@ -82,7 +88,8 @@ def generate_callbacks(func_list, base_package, callback_package, dto_package, i cls_name=camel_case_name + callback_suffix, callback_method=method, base_package=base_package, - callback_package=callback_package)) + callback_package=callback_package, + callback_type=callback_type)) callback_file.flush() callback_file.close() diff --git a/vpp-api/java/jvpp/gen/dto_gen.py b/vpp-api/java/jvpp/gen/dto_gen.py index 05859dbe83a..426cd96b2ac 100644 --- a/vpp-api/java/jvpp/gen/dto_gen.py +++ b/vpp-api/java/jvpp/gen/dto_gen.py @@ -13,9 +13,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os, util +import os from string import Template +import util + dto_template = Template(""" package $base_package.$dto_package; @@ -40,6 +42,7 @@ send_template = Template(""" @Override return jvpp.$method_name($args); }\n""") + def generate_dtos(func_list, base_package, dto_package, inputfile): """ Generates dto objects in a dedicated package """ print "Generating DTOs" @@ -52,8 +55,7 @@ def generate_dtos(func_list, base_package, dto_package, inputfile): camel_case_method_name = util.underscore_to_camelcase(func['name']) dto_path = os.path.join(dto_package, camel_case_dto_name + ".java") - if util.is_notification(func['name']) or util.is_ignored(func['name']): - # TODO handle notifications + if util.is_ignored(func['name']): continue fields = "" @@ -66,44 +68,63 @@ def generate_dtos(func_list, base_package, dto_package, inputfile): name=field_name) methods = "" base_type = "" - if util.is_reply(camel_case_dto_name): - description = "vpe.api reply DTO" - request_dto_name = get_request_name(camel_case_dto_name, func['name']) - if util.is_details(camel_case_dto_name): - # FIXME assumption that dump calls end with "Dump" suffix. Not enforced in vpe.api - base_type += "JVppReply<%s.%s.%s>" % (base_package, dto_package, request_dto_name + "Dump") - generate_dump_reply_dto(request_dto_name, base_package, dto_package, camel_case_dto_name, - camel_case_method_name, func) - else: - base_type += "JVppReply<%s.%s.%s>" % (base_package, dto_package, request_dto_name) - else: - args = "" if fields is "" else "this" - methods = send_template.substitute(method_name=camel_case_method_name, - base_package=base_package, - args=args) - if util.is_dump(camel_case_dto_name): - base_type += "JVppDump" - description = "vpe.api dump request DTO" - else: - base_type += "JVppRequest" - description = "vpe.api request DTO" - dto_file = open(dto_path, 'w') - dto_file.write(dto_template.substitute(inputfile=inputfile, - description=description, - docs=util.api_message_to_javadoc(func), - cls_name=camel_case_dto_name, - fields=fields, - methods=methods, - base_package=base_package, - base_type=base_type, - dto_package=dto_package)) - dto_file.flush() - dto_file.close() + # Generate request/reply or dump/dumpReply even if structure can be used as notification + if not util.is_just_notification(func["name"]): + if util.is_reply(camel_case_dto_name): + description = "vpe.api reply DTO" + request_dto_name = get_request_name(camel_case_dto_name, func['name']) + if util.is_details(camel_case_dto_name): + # FIXME assumption that dump calls end with "Dump" suffix. Not enforced in vpe.api + base_type += "JVppReply<%s.%s.%s>" % (base_package, dto_package, request_dto_name + "Dump") + generate_dump_reply_dto(request_dto_name, base_package, dto_package, camel_case_dto_name, + camel_case_method_name, func) + else: + base_type += "JVppReply<%s.%s.%s>" % (base_package, dto_package, request_dto_name) + else: + args = "" if fields is "" else "this" + methods = send_template.substitute(method_name=camel_case_method_name, + base_package=base_package, + args=args) + if util.is_dump(camel_case_dto_name): + base_type += "JVppDump" + description = "vpe.api dump request DTO" + else: + base_type += "JVppRequest" + description = "vpe.api request DTO" + + write_dto_file(base_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, + inputfile, methods) + + # for structures that are also used as notifications, generate dedicated notification DTO + if util.is_notification(func["name"]): + base_type = "JVppNotification" + description = "vpe.api notification DTO" + camel_case_dto_name = util.add_notification_suffix(camel_case_dto_name) + methods = "" + dto_path = os.path.join(dto_package, camel_case_dto_name + ".java") + write_dto_file(base_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, + inputfile, methods) flush_dump_reply_dtos(inputfile) +def write_dto_file(base_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func, + inputfile, methods): + dto_file = open(dto_path, 'w') + dto_file.write(dto_template.substitute(inputfile=inputfile, + description=description, + docs=util.api_message_to_javadoc(func), + cls_name=camel_case_dto_name, + fields=fields, + methods=methods, + base_package=base_package, + base_type=base_type, + dto_package=dto_package)) + dto_file.flush() + dto_file.close() + + dump_dto_suffix = "ReplyDump" dump_reply_artificial_dtos = {} diff --git a/vpp-api/java/jvpp/gen/jvpp_c_gen.py b/vpp-api/java/jvpp/gen/jvpp_c_gen.py index 082fd5d73ae..c006c34103b 100644 --- a/vpp-api/java/jvpp/gen/jvpp_c_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_c_gen.py @@ -53,16 +53,21 @@ def generate_class_cache(func_list): class_name = util.underscore_to_camelcase_upper(c_name) ref_name = util.underscore_to_camelcase(c_name) - if not util.is_reply(class_name) or util.is_ignored(c_name) or util.is_notification(c_name): - # TODO handle notifications + if util.is_ignored(c_name): continue - class_references.append(class_reference_template.substitute( + if util.is_reply(class_name): + class_references.append(class_reference_template.substitute( ref_name=ref_name)) - - find_class_invocations.append(find_class_invocation_template.substitute( + find_class_invocations.append(find_class_invocation_template.substitute( ref_name=ref_name, class_name=class_name)) + elif util.is_notification(c_name): + class_references.append(class_reference_template.substitute( + ref_name=util.add_notification_suffix(ref_name))) + find_class_invocations.append(find_class_invocation_template.substitute( + ref_name=util.add_notification_suffix(ref_name), + class_name=util.add_notification_suffix(class_name))) # add exception class to class cache ref_name = 'callbackException' @@ -73,7 +78,7 @@ def generate_class_cache(func_list): ref_name=ref_name, class_name=class_name)) return class_cache_template.substitute( - class_references="".join(class_references), find_class_invocations="".join(find_class_invocations)) + class_references="".join(class_references), find_class_invocations="".join(find_class_invocations)) # TODO: cache method and field identifiers to achieve better performance @@ -174,7 +179,7 @@ def generate_jni_impl(func_list, inputfile): f_name = f['name'] camel_case_function_name = util.underscore_to_camelcase(f_name) if is_manually_generated(f_name) or util.is_reply(camel_case_function_name) \ - or util.is_ignored(f_name) or util.is_notification(f_name): + or util.is_ignored(f_name) or util.is_just_notification(f_name): continue arguments = '' @@ -331,10 +336,16 @@ def generate_msg_handlers(func_list, inputfile): dto_name = util.underscore_to_camelcase_upper(handler_name) ref_name = util.underscore_to_camelcase(handler_name) - if is_manually_generated(handler_name) or not util.is_reply(dto_name) or util.is_ignored(handler_name) or util.is_notification(handler_name): - # TODO handle notifications + if is_manually_generated(handler_name) or util.is_ignored(handler_name): + continue + + if not util.is_reply(dto_name) and not util.is_notification(handler_name): continue + if util.is_notification(handler_name): + dto_name = util.add_notification_suffix(dto_name) + ref_name = util.add_notification_suffix(ref_name) + dto_setters = '' err_handler = '' # dto setters @@ -391,13 +402,12 @@ def generate_handler_registration(func_list): name = f['name'] camelcase_name = util.underscore_to_camelcase(f['name']) - if not util.is_reply(camelcase_name) or util.is_ignored(name) or util.is_notification(name): - # TODO handle notifications + if (not util.is_reply(camelcase_name) and not util.is_notification(name)) or util.is_ignored(name): continue handler_registration.append(handler_registration_template.substitute( - name=name, - upercase_name=name.upper())) + name=name, + upercase_name=name.upper())) return "".join(handler_registration) diff --git a/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py b/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py index acf29eb85b8..7df17486a60 100644 --- a/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_callback_facade_gen.py @@ -27,7 +27,7 @@ package $base_package.$callback_facade_package; * <br>It was generated by jvpp_callback_facade_gen.py based on $inputfile * <br>(python representation of vpe.api generated by vppapigen). */ -public interface CallbackJVpp extends java.lang.AutoCloseable { +public interface CallbackJVpp extends $base_package.$notification_package.NotificationRegistryProvider, java.lang.AutoCloseable { @Override void close(); @@ -46,7 +46,7 @@ package $base_package.$callback_facade_package; * <br>It was generated by jvpp_callback_facade_gen.py based on $inputfile * <br>(python representation of vpe.api generated by vppapigen). */ -public final class CallbackJVppFacade implements $base_package.$callback_facade_package.CallbackJVpp { +public final class CallbackJVppFacade extends $base_package.$notification_package.NotificationRegistryProviderContext implements $base_package.$callback_facade_package.CallbackJVpp { private final $base_package.JVpp jvpp; private final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> callbacks; @@ -63,7 +63,7 @@ public final class CallbackJVppFacade implements $base_package.$callback_facade_ public CallbackJVppFacade(final $base_package.JVpp jvpp) throws java.io.IOException { this.jvpp = java.util.Objects.requireNonNull(jvpp,"jvpp is null"); this.callbacks = new java.util.HashMap<>(); - this.jvpp.connect(new CallbackJVppFacadeCallback(this.callbacks)); + this.jvpp.connect(new CallbackJVppFacadeCallback(this.callbacks, getNotificationCallback())); } @Override @@ -95,7 +95,7 @@ no_arg_method_impl_template = Template(""" public final void $name($base_pack """) -def generate_jvpp(func_list, base_package, dto_package, callback_package, callback_facade_package, inputfile): +def generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, inputfile): """ Generates callback facade """ print "Generating JVpp callback facade" @@ -152,6 +152,7 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, callba methods="\n".join(methods), base_package=base_package, dto_package=dto_package, + notification_package=notification_package, callback_facade_package=callback_facade_package)) jvpp_file.flush() jvpp_file.close() @@ -161,12 +162,13 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, callba methods="\n".join(methods_impl), base_package=base_package, dto_package=dto_package, + notification_package=notification_package, callback_package=callback_package, callback_facade_package=callback_facade_package)) jvpp_file.flush() jvpp_file.close() - generate_callback(func_list, base_package, dto_package, callback_package, callback_facade_package, inputfile) + generate_callback(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, inputfile) jvpp_facade_callback_template = Template(""" @@ -180,10 +182,13 @@ package $base_package.$callback_facade_package; public final class CallbackJVppFacadeCallback implements $base_package.$callback_package.JVppGlobalCallback { private final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> requests; + private final $base_package.$notification_package.GlobalNotificationCallback notificationCallback; private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(CallbackJVppFacadeCallback.class.getName()); - public CallbackJVppFacadeCallback(final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> requestMap) { + public CallbackJVppFacadeCallback(final java.util.Map<Integer, $base_package.$callback_package.JVppCallback> requestMap, + final $base_package.$notification_package.GlobalNotificationCallback notificationCallback) { this.requests = requestMap; + this.notificationCallback = notificationCallback; } @Override @@ -224,29 +229,44 @@ jvpp_facade_callback_method_template = Template(""" } """) +jvpp_facade_callback_notification_method_template = Template(""" + @Override + @SuppressWarnings("unchecked") + public void on$callback_dto($base_package.$dto_package.$callback_dto notification) { + notificationCallback.on$callback_dto(notification); + } +""") -def generate_callback(func_list, base_package, dto_package, callback_package, callback_facade_package, inputfile): + +def generate_callback(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, inputfile): callbacks = [] for func in func_list: - if util.is_notification(func['name']) or util.is_ignored(func['name']): - # TODO handle notifications + if util.is_ignored(func['name']): continue camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) - if not util.is_reply(camel_case_name_with_suffix): - continue - callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, - dto_package=dto_package, - callback_package=callback_package, - callback=util.remove_reply_suffix(camel_case_name_with_suffix) + callback_gen.callback_suffix, - callback_dto=camel_case_name_with_suffix)) + if util.is_reply(camel_case_name_with_suffix): + callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, + dto_package=dto_package, + callback_package=callback_package, + callback=util.remove_reply_suffix(camel_case_name_with_suffix) + callback_gen.callback_suffix, + callback_dto=camel_case_name_with_suffix)) + + if util.is_notification(func["name"]): + with_notification_suffix = util.add_notification_suffix(camel_case_name_with_suffix) + callbacks.append(jvpp_facade_callback_notification_method_template.substitute(base_package=base_package, + dto_package=dto_package, + callback_package=callback_package, + callback=with_notification_suffix + callback_gen.callback_suffix, + callback_dto=with_notification_suffix)) jvpp_file = open(os.path.join(callback_facade_package, "CallbackJVppFacadeCallback.java"), 'w') jvpp_file.write(jvpp_facade_callback_template.substitute(inputfile=inputfile, base_package=base_package, dto_package=dto_package, + notification_package=notification_package, callback_package=callback_package, methods="".join(callbacks), callback_facade_package=callback_facade_package)) diff --git a/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py b/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py index 7a5a166733c..e1ca4d022e0 100644 --- a/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_future_facade_gen.py @@ -30,12 +30,16 @@ package $base_package.$future_package; public final class FutureJVppFacadeCallback implements $base_package.$callback_package.JVppGlobalCallback { private final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requests; + private final $base_package.$notification_package.GlobalNotificationCallback notificationCallback; - public FutureJVppFacadeCallback(final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requestMap) { + public FutureJVppFacadeCallback(final java.util.Map<java.lang.Integer, java.util.concurrent.CompletableFuture<? extends $base_package.$dto_package.JVppReply<?>>> requestMap, + final $base_package.$notification_package.GlobalNotificationCallback notificationCallback) { this.requests = requestMap; + this.notificationCallback = notificationCallback; } @Override + @SuppressWarnings("unchecked") public void onError(org.openvpp.jvpp.VppCallbackException reply) { final java.util.concurrent.CompletableFuture<$base_package.$dto_package.JVppReply<?>> completableFuture; @@ -76,6 +80,13 @@ jvpp_facade_callback_method_template = Template(""" } """) +jvpp_facade_callback_notification_method_template = Template(""" + @Override + public void on$callback_dto($base_package.$dto_package.$callback_dto notification) { + notificationCallback.on$callback_dto(notification); + } +""") + # TODO reuse common parts with generic method callback jvpp_facade_control_ping_method_template = Template(""" @Override @@ -129,7 +140,7 @@ jvpp_facade_details_callback_method_template = Template(""" """) -def generate_jvpp(func_list, base_package, dto_package, callback_package, future_facade_package, inputfile): +def generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, future_facade_package, inputfile): """ Generates JVpp interface and JNI implementation """ print "Generating JVpp future facade" @@ -141,70 +152,77 @@ def generate_jvpp(func_list, base_package, dto_package, callback_package, future callbacks = [] for func in func_list: - if util.is_notification(func['name']) or util.is_ignored(func['name']): - # TODO handle notifications + if util.is_ignored(func['name']): continue camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) - if not util.is_reply(camel_case_name_with_suffix): + if not util.is_reply(camel_case_name_with_suffix) and not util.is_notification(func['name']): continue camel_case_method_name = util.underscore_to_camelcase(func['name']) - camel_case_request_method_name = util.remove_reply_suffix(util.underscore_to_camelcase(func['name'])) - if util.is_details(camel_case_name_with_suffix): - camel_case_reply_name = get_standard_dump_reply_name(util.underscore_to_camelcase_upper(func['name']), - func['name']) - callbacks.append(jvpp_facade_details_callback_method_template.substitute(base_package=base_package, - dto_package=dto_package, - callback_dto=camel_case_name_with_suffix, - callback_dto_field=camel_case_method_name, - callback_dto_reply_dump=camel_case_reply_name + dto_gen.dump_dto_suffix, - future_package=future_facade_package)) - - methods.append(future_jvpp_method_template.substitute(base_package=base_package, - dto_package=dto_package, - method_name=camel_case_request_method_name + - util.underscore_to_camelcase_upper(util.dump_suffix), - reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix, - request_name=util.remove_reply_suffix(camel_case_reply_name) + - util.underscore_to_camelcase_upper(util.dump_suffix))) - methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package, - dto_package=dto_package, - method_name=camel_case_request_method_name + - util.underscore_to_camelcase_upper(util.dump_suffix), - reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix, - request_name=util.remove_reply_suffix(camel_case_reply_name) + - util.underscore_to_camelcase_upper(util.dump_suffix))) - else: - request_name = util.underscore_to_camelcase_upper(util.unconventional_naming_rep_req[func['name']]) \ - if func['name'] in util.unconventional_naming_rep_req else util.remove_reply_suffix(camel_case_name_with_suffix) - - methods.append(future_jvpp_method_template.substitute(base_package=base_package, - dto_package=dto_package, - method_name=camel_case_request_method_name, - reply_name=camel_case_name_with_suffix, - request_name=request_name)) - methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package, - dto_package=dto_package, - method_name=camel_case_request_method_name, - reply_name=camel_case_name_with_suffix, - request_name=request_name)) - - # Callback handler is a bit special and a different template has to be used - if util.is_control_ping(camel_case_name_with_suffix): - callbacks.append(jvpp_facade_control_ping_method_template.substitute(base_package=base_package, - dto_package=dto_package, - callback_dto=camel_case_name_with_suffix, - future_package=future_facade_package)) + + if not util.is_notification(func["name"]): + camel_case_request_method_name = util.remove_reply_suffix(util.underscore_to_camelcase(func['name'])) + if util.is_details(camel_case_name_with_suffix): + camel_case_reply_name = get_standard_dump_reply_name(util.underscore_to_camelcase_upper(func['name']), + func['name']) + callbacks.append(jvpp_facade_details_callback_method_template.substitute(base_package=base_package, + dto_package=dto_package, + callback_dto=camel_case_name_with_suffix, + callback_dto_field=camel_case_method_name, + callback_dto_reply_dump=camel_case_reply_name + dto_gen.dump_dto_suffix, + future_package=future_facade_package)) + + methods.append(future_jvpp_method_template.substitute(base_package=base_package, + dto_package=dto_package, + method_name=camel_case_request_method_name + + util.underscore_to_camelcase_upper(util.dump_suffix), + reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix, + request_name=util.remove_reply_suffix(camel_case_reply_name) + + util.underscore_to_camelcase_upper(util.dump_suffix))) + methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package, + dto_package=dto_package, + method_name=camel_case_request_method_name + + util.underscore_to_camelcase_upper(util.dump_suffix), + reply_name=camel_case_reply_name + dto_gen.dump_dto_suffix, + request_name=util.remove_reply_suffix(camel_case_reply_name) + + util.underscore_to_camelcase_upper(util.dump_suffix))) else: - callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, - dto_package=dto_package, - callback_dto=camel_case_name_with_suffix)) + request_name = util.underscore_to_camelcase_upper(util.unconventional_naming_rep_req[func['name']]) \ + if func['name'] in util.unconventional_naming_rep_req else util.remove_reply_suffix(camel_case_name_with_suffix) + + methods.append(future_jvpp_method_template.substitute(base_package=base_package, + dto_package=dto_package, + method_name=camel_case_request_method_name, + reply_name=camel_case_name_with_suffix, + request_name=request_name)) + methods_impl.append(future_jvpp_method_impl_template.substitute(base_package=base_package, + dto_package=dto_package, + method_name=camel_case_request_method_name, + reply_name=camel_case_name_with_suffix, + request_name=request_name)) + + # Callback handler is a bit special and a different template has to be used + if util.is_control_ping(camel_case_name_with_suffix): + callbacks.append(jvpp_facade_control_ping_method_template.substitute(base_package=base_package, + dto_package=dto_package, + callback_dto=camel_case_name_with_suffix, + future_package=future_facade_package)) + else: + callbacks.append(jvpp_facade_callback_method_template.substitute(base_package=base_package, + dto_package=dto_package, + callback_dto=camel_case_name_with_suffix)) + + if util.is_notification(func["name"]): + callbacks.append(jvpp_facade_callback_notification_method_template.substitute(base_package=base_package, + dto_package=dto_package, + callback_dto=util.add_notification_suffix(camel_case_name_with_suffix))) jvpp_file = open(os.path.join(future_facade_package, "FutureJVppFacadeCallback.java"), 'w') jvpp_file.write(jvpp_facade_callback_template.substitute(inputfile=inputfile, base_package=base_package, dto_package=dto_package, + notification_package=notification_package, callback_package=callback_package, methods="".join(callbacks), future_package=future_facade_package)) @@ -268,7 +286,7 @@ public class FutureJVppFacade extends FutureJVppInvokerFacade implements FutureJ */ public FutureJVppFacade(final $base_package.JVpp jvpp) throws java.io.IOException { super(jvpp, new java.util.HashMap<>()); - jvpp.connect(new FutureJVppFacadeCallback(getRequests())); + jvpp.connect(new FutureJVppFacadeCallback(getRequests(), getNotificationCallback())); } $methods } diff --git a/vpp-api/java/jvpp/gen/jvpp_gen.py b/vpp-api/java/jvpp/gen/jvpp_gen.py index e2ff2adcf14..c08593e180f 100755 --- a/vpp-api/java/jvpp/gen/jvpp_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_gen.py @@ -19,6 +19,7 @@ import importlib import sys import callback_gen +import notification_gen import dto_gen import jvpp_callback_facade_gen import jvpp_future_facade_gen @@ -32,7 +33,7 @@ import util # # Compilation: # ~/Projects/vpp/vpp-api/jvpp/gen/java/org/openvpp/jvpp$ javac *.java dto/*.java callback/*.java -# +# # where # defs_api_vpp_papi.py - vpe.api in python format (generated by vppapigen) from util import vpp_2_jni_type_mapping @@ -122,6 +123,7 @@ func_list, func_name = get_definitions() base_package = 'org.openvpp.jvpp' dto_package = 'dto' callback_package = 'callback' +notification_package = 'notification' future_package = 'future' # TODO find better package name callback_facade_package = 'callfacade' @@ -129,6 +131,7 @@ callback_facade_package = 'callfacade' dto_gen.generate_dtos(func_list, base_package, dto_package, args.inputfile) jvpp_impl_gen.generate_jvpp(func_list, base_package, dto_package, args.inputfile) callback_gen.generate_callbacks(func_list, base_package, callback_package, dto_package, args.inputfile) +notification_gen.generate_notification_registry(func_list, base_package, notification_package, callback_package, dto_package, args.inputfile) jvpp_c_gen.generate_jvpp(func_list, args.inputfile) -jvpp_future_facade_gen.generate_jvpp(func_list, base_package, dto_package, callback_package, future_package, args.inputfile) -jvpp_callback_facade_gen.generate_jvpp(func_list, base_package, dto_package, callback_package, callback_facade_package, args.inputfile) +jvpp_future_facade_gen.generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, future_package, args.inputfile) +jvpp_callback_facade_gen.generate_jvpp(func_list, base_package, dto_package, callback_package, notification_package, callback_facade_package, args.inputfile) diff --git a/vpp-api/java/jvpp/gen/jvpp_impl_gen.py b/vpp-api/java/jvpp/gen/jvpp_impl_gen.py index dfec6a743de..93ffd0fb359 100644 --- a/vpp-api/java/jvpp/gen/jvpp_impl_gen.py +++ b/vpp-api/java/jvpp/gen/jvpp_impl_gen.py @@ -121,8 +121,8 @@ def generate_jvpp(func_list, base_package, dto_package, inputfile): methods_impl = [] for func in func_list: - if util.is_notification(func['name']) or util.is_ignored(func['name']): - # TODO handle notifications + # Skip structures that are used only as notifications + if util.is_just_notification(func['name']) or util.is_ignored(func['name']): continue camel_case_name = util.underscore_to_camelcase(func['name']) diff --git a/vpp-api/java/jvpp/gen/notification_gen.py b/vpp-api/java/jvpp/gen/notification_gen.py new file mode 100644 index 00000000000..4ca3c070431 --- /dev/null +++ b/vpp-api/java/jvpp/gen/notification_gen.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python +# +# Copyright (c) 2016 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. + +import os + +import callback_gen +import util +from string import Template + +from util import remove_suffix + +notification_registry_template = Template(""" +package $base_package.$notification_package; + +/** + * <p>Registry for notification callbacks. + * <br>It was generated by notification_gen.py based on $inputfile + * <br>(python representation of vpe.api generated by vppapigen). + */ +public interface NotificationRegistry extends java.lang.AutoCloseable { + + $register_callback_methods + + @Override + void close(); +} +""") + +global_notification_callback_template = Template(""" +package $base_package.$notification_package; + +/** + * <p>Aggregated callback interface for notifications only. + * <br>It was generated by notification_gen.py based on $inputfile + * <br>(python representation of vpe.api generated by vppapigen). + */ +public interface GlobalNotificationCallback extends $callbacks { + +} +""") + +notification_registry_impl_template = Template(""" +package $base_package.$notification_package; + +/** + * <p>Notification registry delegating notification processing to registered callbacks. + * <br>It was generated by notification_gen.py based on $inputfile + * <br>(python representation of vpe.api generated by vppapigen). + */ +public final class NotificationRegistryImpl implements NotificationRegistry, GlobalNotificationCallback { + + // TODO add a special NotificationCallback interface and only allow those to be registered + private final java.util.concurrent.ConcurrentMap<Class<? extends $base_package.$dto_package.JVppNotification>, $base_package.$callback_package.JVppNotificationCallback> registeredCallbacks = + new java.util.concurrent.ConcurrentHashMap<>(); + + $register_callback_methods + $handler_methods + + @Override + public void close() { + registeredCallbacks.clear(); + } +} +""") + +register_callback_impl_template = Template(""" + public java.lang.AutoCloseable register$callback(final $base_package.$callback_package.$callback callback){ + if(null != registeredCallbacks.putIfAbsent($base_package.$dto_package.$notification.class, callback)){ + throw new IllegalArgumentException("Callback for " + $base_package.$dto_package.$notification.class + + "notification already registered"); + } + return () -> registeredCallbacks.remove($base_package.$dto_package.$notification.class); + } +""") + +handler_impl_template = Template(""" + @Override + public void on$notification( + final $base_package.$dto_package.$notification notification) { + final $base_package.$callback_package.JVppNotificationCallback JVppNotificationCallback = registeredCallbacks.get($base_package.$dto_package.$notification.class); + if (null != JVppNotificationCallback) { + (($base_package.$callback_package.$callback) registeredCallbacks + .get($base_package.$dto_package.$notification.class)) + .on$notification(notification); + } + } +""") + + +def generate_notification_registry(func_list, base_package, notification_package, callback_package, dto_package, inputfile): + """ Generates notification registry interface and implementation """ + print "Generating Notification interfaces and implementation" + + if not os.path.exists(notification_package): + raise Exception("%s folder is missing" % notification_package) + + callbacks = [] + register_callback_methods = [] + register_callback_methods_impl = [] + handler_methods = [] + for func in func_list: + + if not util.is_notification(func['name']): + continue + + camel_case_name_with_suffix = util.underscore_to_camelcase_upper(func['name']) + notification_dto = util.add_notification_suffix(camel_case_name_with_suffix) + callback_ifc = notification_dto + callback_gen.callback_suffix + fully_qualified_callback_ifc = "{0}.{1}.{2}".format(base_package, callback_package, callback_ifc) + callbacks.append(fully_qualified_callback_ifc) + + # TODO create NotificationListenerRegistration and return that instead of AutoCloseable to better indicate + # that the registration should be closed + register_callback_methods.append("java.lang.AutoCloseable register{0}({1} callback);" + .format(callback_ifc, fully_qualified_callback_ifc)) + register_callback_methods_impl.append(register_callback_impl_template.substitute(base_package=base_package, + callback_package=callback_package, + dto_package=dto_package, + notification=notification_dto, + callback=callback_ifc)) + handler_methods.append(handler_impl_template.substitute(base_package=base_package, + callback_package=callback_package, + dto_package=dto_package, + notification=notification_dto, + callback=callback_ifc)) + + callback_file = open(os.path.join(notification_package, "NotificationRegistry.java"), 'w') + callback_file.write(notification_registry_template.substitute(inputfile=inputfile, + register_callback_methods="\n ".join(register_callback_methods), + base_package=base_package, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() + + callback_file = open(os.path.join(notification_package, "GlobalNotificationCallback.java"), 'w') + callback_file.write(global_notification_callback_template.substitute(inputfile=inputfile, + callbacks=", ".join(callbacks), + base_package=base_package, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() + + callback_file = open(os.path.join(notification_package, "NotificationRegistryImpl.java"), 'w') + callback_file.write(notification_registry_impl_template.substitute(inputfile=inputfile, + callback_package=callback_package, + dto_package=dto_package, + register_callback_methods="".join(register_callback_methods_impl), + handler_methods="".join(handler_methods), + base_package=base_package, + notification_package=notification_package)) + callback_file.flush() + callback_file.close() diff --git a/vpp-api/java/jvpp/gen/util.py b/vpp-api/java/jvpp/gen/util.py index 072c9d592f2..12c8bc3170f 100644 --- a/vpp-api/java/jvpp/gen/util.py +++ b/vpp-api/java/jvpp/gen/util.py @@ -148,15 +148,21 @@ unconventional_naming_rep_req = { # # FIXME no convention in the naming of events (notifications) in vpe.api notifications_message_suffixes = ("event", "counters") -notification_messages = ["from_netconf_client", "from_netconf_server", "to_netconf_client", "to_netconf_server"] +notification_messages_reused = ["sw_interface_set_flags"] # messages that must be ignored. These messages are INSUFFICIENTLY marked as disabled in vpe.api # FIXME ignored_messages = ["is_address_reachable"] -def is_notification(param): - return param.lower().endswith(notifications_message_suffixes) or param.lower() in notification_messages +def is_notification(name): + """ Returns true if the structure is a notification regardless of its no other use """ + return is_just_notification(name) or name.lower() in notification_messages_reused + + +def is_just_notification(name): + """ Returns true if the structure is just a notification and has no other use """ + return name.lower().endswith(notifications_message_suffixes) def is_ignored(param): @@ -178,4 +184,12 @@ def is_control_ping(camel_case_name_with_suffix): def api_message_to_javadoc(api_message): """ Converts vpe.api message description to javadoc """ str = pprint.pformat(api_message, indent=4, width=120, depth=None) - return " * " + str.replace("\n", "\n * ")
\ No newline at end of file + return " * " + str.replace("\n", "\n * ") + + +notification_dto_suffix = "Notification" + + +def add_notification_suffix(camel_case_dto_name): + camel_case_dto_name += notification_dto_suffix + return camel_case_dto_name
\ No newline at end of file |