2016-04-28 12:29:33 +02:00
#!/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 , util
from string import Template
import callback_gen
import dto_gen
jvpp_ifc_template = Template ( """
2016-07-26 15:28:22 +02:00
package $ plugin_package . $ callback_facade_package ;
2016-04-28 12:29:33 +02:00
2016-04-26 12:09:05 +02:00
/ * *
2016-07-26 15:28:22 +02:00
* < p > Callback Java API representation of $ plugin_package plugin .
2016-04-26 12:09:05 +02:00
* < br > It was generated by jvpp_callback_facade_gen . py based on $ inputfile
2016-07-26 15:28:22 +02:00
* < br > ( python representation of api file generated by vppapigen ) .
2016-04-26 12:09:05 +02:00
* /
2016-07-26 15:28:22 +02:00
public interface CallbackJVpp $ { plugin_name } extends $ base_package . $ notification_package . NotificationRegistryProvider , java . lang . AutoCloseable {
2016-04-28 12:29:33 +02:00
/ / TODO add send
$ methods
}
""" )
jvpp_impl_template = Template ( """
2016-07-26 15:28:22 +02:00
package $ plugin_package . $ callback_facade_package ;
2016-04-28 12:29:33 +02:00
2016-04-26 12:09:05 +02:00
/ * *
2016-07-26 15:28:22 +02:00
* < p > Default implementation of Callback $ { plugin_name } JVpp interface .
2016-04-26 12:09:05 +02:00
* < br > It was generated by jvpp_callback_facade_gen . py based on $ inputfile
2016-07-26 15:28:22 +02:00
* < br > ( python representation of api file generated by vppapigen ) .
2016-04-26 12:09:05 +02:00
* /
2016-07-26 15:28:22 +02:00
public final class CallbackJVpp $ { plugin_name } Facade implements CallbackJVpp $ { plugin_name } {
2016-04-28 12:29:33 +02:00
2016-07-26 15:28:22 +02:00
private final $ plugin_package . JVpp $ { plugin_name } jvpp ;
2016-04-28 12:29:33 +02:00
private final java . util . Map < Integer , $ base_package . $ callback_package . JVppCallback > callbacks ;
2016-07-26 15:28:22 +02:00
private final $ plugin_package . $ notification_package . $ { plugin_name } NotificationRegistryImpl notificationRegistry = new $ plugin_package . $ notification_package . $ { plugin_name } NotificationRegistryImpl ( ) ;
2016-05-13 10:17:51 +02:00
/ * *
2016-07-26 15:28:22 +02:00
* < p > Create CallbackJVpp $ { plugin_name } Facade object for provided JVpp instance .
2016-05-13 10:17:51 +02:00
* Constructor internally creates CallbackJVppFacadeCallback class for processing callbacks
* and then connects to provided JVpp instance
*
* @param jvpp provided $ base_package . JVpp instance
*
* @throws java . io . IOException in case instance cannot connect to JVPP
* /
2016-07-26 15:28:22 +02:00
public CallbackJVpp $ { plugin_name } Facade ( final $ base_package . JVppRegistry registry , final $ plugin_package . JVpp $ { plugin_name } jvpp ) throws java . io . IOException {
2016-05-09 16:41:31 +02:00
this . jvpp = java . util . Objects . requireNonNull ( jvpp , " jvpp is null " ) ;
2016-05-13 10:17:51 +02:00
this . callbacks = new java . util . HashMap < > ( ) ;
2016-07-26 15:28:22 +02:00
java . util . Objects . requireNonNull ( registry , " JVppRegistry should not be null " ) ;
registry . register ( jvpp , new CallbackJVpp $ { plugin_name } FacadeCallback ( this . callbacks , notificationRegistry ) ) ;
}
@Override
public $ plugin_package . $ notification_package . $ { plugin_name } NotificationRegistry getNotificationRegistry ( ) {
return notificationRegistry ;
2016-04-28 12:29:33 +02:00
}
@Override
2016-07-26 15:28:22 +02:00
public void close ( ) throws Exception {
jvpp . close ( ) ;
2016-04-28 12:29:33 +02:00
}
/ / TODO add send ( )
$ methods
}
""" )
method_template = Template (
2016-07-26 15:28:22 +02:00
""" void $name($plugin_package.$dto_package.$request request, $plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException; """ )
2016-05-18 14:54:50 +02:00
2016-07-26 15:28:22 +02:00
method_impl_template = Template ( """ public final void $name($plugin_package.$dto_package.$request request, $plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException {
2016-04-28 12:29:33 +02:00
synchronized ( callbacks ) {
callbacks . put ( jvpp . $ name ( request ) , callback ) ;
}
}
""" )
2016-07-26 15:28:22 +02:00
no_arg_method_template = Template ( """ void $name($plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException; """ )
no_arg_method_impl_template = Template ( """ public final void $name($plugin_package.$callback_package.$callback callback) throws $base_package.VppInvocationException {
2016-04-28 12:29:33 +02:00
synchronized ( callbacks ) {
callbacks . put ( jvpp . $ name ( ) , callback ) ;
}
}
""" )
2016-07-26 15:28:22 +02:00
def generate_jvpp ( func_list , base_package , plugin_package , plugin_name , dto_package , callback_package , notification_package , callback_facade_package , inputfile ) :
2016-04-28 12:29:33 +02:00
""" Generates callback facade """
print " Generating JVpp callback facade "
if os . path . exists ( callback_facade_package ) :
util . remove_folder ( callback_facade_package )
os . mkdir ( callback_facade_package )
methods = [ ]
methods_impl = [ ]
for func in func_list :
if util . is_notification ( func [ ' name ' ] ) or util . is_ignored ( func [ ' name ' ] ) :
continue
camel_case_name = util . underscore_to_camelcase ( func [ ' name ' ] )
camel_case_name_upper = util . underscore_to_camelcase_upper ( func [ ' name ' ] )
2016-07-26 15:28:22 +02:00
if util . is_reply ( camel_case_name ) or util . is_control_ping ( camel_case_name ) :
2016-04-28 12:29:33 +02:00
continue
# Strip suffix for dump calls
callback_type = get_request_name ( camel_case_name_upper , func [ ' name ' ] ) + callback_gen . callback_suffix
if len ( func [ ' args ' ] ) == 0 :
methods . append ( no_arg_method_template . substitute ( name = camel_case_name ,
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
callback_package = callback_package ,
callback = callback_type ) )
methods_impl . append ( no_arg_method_impl_template . substitute ( name = camel_case_name ,
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
callback_package = callback_package ,
callback = callback_type ) )
else :
methods . append ( method_template . substitute ( name = camel_case_name ,
request = camel_case_name_upper ,
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
callback_package = callback_package ,
callback = callback_type ) )
methods_impl . append ( method_impl_template . substitute ( name = camel_case_name ,
request = camel_case_name_upper ,
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
callback_package = callback_package ,
callback = callback_type ) )
2016-07-26 15:28:22 +02:00
join = os . path . join ( callback_facade_package , " CallbackJVpp %s .java " % plugin_name )
2016-04-28 12:29:33 +02:00
jvpp_file = open ( join , ' w ' )
jvpp_file . write (
2016-04-26 12:09:05 +02:00
jvpp_ifc_template . substitute ( inputfile = inputfile ,
methods = " \n " . join ( methods ) ,
2016-04-28 12:29:33 +02:00
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
plugin_name = plugin_name ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
2016-05-31 17:45:16 +02:00
notification_package = notification_package ,
2016-04-28 12:29:33 +02:00
callback_facade_package = callback_facade_package ) )
jvpp_file . flush ( )
jvpp_file . close ( )
2016-07-26 15:28:22 +02:00
jvpp_file = open ( os . path . join ( callback_facade_package , " CallbackJVpp %s Facade.java " % plugin_name ) , ' w ' )
2016-04-26 12:09:05 +02:00
jvpp_file . write ( jvpp_impl_template . substitute ( inputfile = inputfile ,
methods = " \n " . join ( methods_impl ) ,
2016-04-28 12:29:33 +02:00
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
plugin_name = plugin_name ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
2016-05-31 17:45:16 +02:00
notification_package = notification_package ,
2016-04-28 12:29:33 +02:00
callback_package = callback_package ,
callback_facade_package = callback_facade_package ) )
jvpp_file . flush ( )
jvpp_file . close ( )
2016-07-26 15:28:22 +02:00
generate_callback ( func_list , base_package , plugin_package , plugin_name , dto_package , callback_package , notification_package , callback_facade_package , inputfile )
2016-04-28 12:29:33 +02:00
jvpp_facade_callback_template = Template ( """
2016-07-26 15:28:22 +02:00
package $ plugin_package . $ callback_facade_package ;
2016-04-28 12:29:33 +02:00
/ * *
2016-05-18 14:54:50 +02:00
* < p > Implementation of JVppGlobalCallback interface for Java Callback API .
2016-04-26 12:09:05 +02:00
* < br > It was generated by jvpp_callback_facade_gen . py based on $ inputfile
2016-07-26 15:28:22 +02:00
* < br > ( python representation of api file generated by vppapigen ) .
2016-04-28 12:29:33 +02:00
* /
2016-07-26 15:28:22 +02:00
public final class CallbackJVpp $ { plugin_name } FacadeCallback implements $ plugin_package . $ callback_package . JVpp $ { plugin_name } GlobalCallback {
2016-04-28 12:29:33 +02:00
private final java . util . Map < Integer , $ base_package . $ callback_package . JVppCallback > requests ;
2016-07-26 15:28:22 +02:00
private final $ plugin_package . $ notification_package . Global $ { plugin_name } NotificationCallback notificationCallback ;
private static final java . util . logging . Logger LOG = java . util . logging . Logger . getLogger ( CallbackJVpp $ { plugin_name } FacadeCallback . class . getName ( ) ) ;
2016-04-28 12:29:33 +02:00
2016-07-26 15:28:22 +02:00
public CallbackJVpp $ { plugin_name } FacadeCallback ( final java . util . Map < Integer , $ base_package . $ callback_package . JVppCallback > requestMap ,
final $ plugin_package . $ notification_package . Global $ { plugin_name } NotificationCallback notificationCallback ) {
2016-04-28 12:29:33 +02:00
this . requests = requestMap ;
2016-05-31 17:45:16 +02:00
this . notificationCallback = notificationCallback ;
2016-04-28 12:29:33 +02:00
}
2016-05-18 14:54:50 +02:00
@Override
2016-07-26 15:28:22 +02:00
public void onError ( $ base_package . VppCallbackException reply ) {
2016-05-18 14:54:50 +02:00
$ base_package . $ callback_package . JVppCallback failedCall ;
synchronized ( requests ) {
failedCall = requests . remove ( reply . getCtxId ( ) ) ;
}
if ( failedCall != null ) {
try {
failedCall . onError ( reply ) ;
} catch ( RuntimeException ex ) {
ex . addSuppressed ( reply ) ;
LOG . log ( java . util . logging . Level . WARNING , String . format ( " Callback: %s failed while handling exception: %s " , failedCall , reply ) , ex ) ;
}
}
}
2016-07-26 15:28:22 +02:00
@Override
@SuppressWarnings ( " unchecked " )
public void onControlPingReply ( $ base_package . $ dto_package . ControlPingReply reply ) {
$ base_package . $ callback_package . ControlPingCallback callback ;
synchronized ( requests ) {
callback = ( $ base_package . $ callback_package . ControlPingCallback ) requests . remove ( reply . context ) ;
}
if ( callback != null ) {
callback . onControlPingReply ( reply ) ;
}
}
2016-04-28 12:29:33 +02:00
$ methods
}
""" )
jvpp_facade_callback_method_template = Template ( """
@Override
@SuppressWarnings ( " unchecked " )
2016-07-26 15:28:22 +02:00
public void on $ callback_dto ( $ plugin_package . $ dto_package . $ callback_dto reply ) {
2016-04-28 12:29:33 +02:00
2016-07-26 15:28:22 +02:00
$ plugin_package . $ callback_package . $ callback callback ;
2016-04-28 12:29:33 +02:00
synchronized ( requests ) {
2016-07-26 15:28:22 +02:00
callback = ( $ plugin_package . $ callback_package . $ callback ) requests . remove ( reply . context ) ;
2016-04-28 12:29:33 +02:00
}
if ( callback != null ) {
callback . on $ callback_dto ( reply ) ;
}
}
""" )
2016-05-31 17:45:16 +02:00
jvpp_facade_callback_notification_method_template = Template ( """
@Override
@SuppressWarnings ( " unchecked " )
2016-07-26 15:28:22 +02:00
public void on $ callback_dto ( $ plugin_package . $ dto_package . $ callback_dto notification ) {
2016-05-31 17:45:16 +02:00
notificationCallback . on $ callback_dto ( notification ) ;
}
""" )
2016-04-28 12:29:33 +02:00
2016-05-31 17:45:16 +02:00
2016-07-26 15:28:22 +02:00
def generate_callback ( func_list , base_package , plugin_package , plugin_name , dto_package , callback_package , notification_package , callback_facade_package , inputfile ) :
2016-04-28 12:29:33 +02:00
callbacks = [ ]
for func in func_list :
camel_case_name_with_suffix = util . underscore_to_camelcase_upper ( func [ ' name ' ] )
2016-07-26 15:28:22 +02:00
if util . is_ignored ( func [ ' name ' ] ) or util . is_control_ping ( camel_case_name_with_suffix ) :
continue
2016-05-31 17:45:16 +02:00
if util . is_reply ( camel_case_name_with_suffix ) :
2016-07-26 15:28:22 +02:00
callbacks . append ( jvpp_facade_callback_method_template . substitute ( plugin_package = plugin_package ,
2016-05-31 17:45:16 +02:00
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 )
2016-07-26 15:28:22 +02:00
callbacks . append ( jvpp_facade_callback_notification_method_template . substitute ( plugin_package = plugin_package ,
2016-05-31 17:45:16 +02:00
dto_package = dto_package ,
callback_package = callback_package ,
callback = with_notification_suffix + callback_gen . callback_suffix ,
callback_dto = with_notification_suffix ) )
2016-04-28 12:29:33 +02:00
2016-07-26 15:28:22 +02:00
jvpp_file = open ( os . path . join ( callback_facade_package , " CallbackJVpp %s FacadeCallback.java " % plugin_name ) , ' w ' )
2016-04-26 12:09:05 +02:00
jvpp_file . write ( jvpp_facade_callback_template . substitute ( inputfile = inputfile ,
base_package = base_package ,
2016-07-26 15:28:22 +02:00
plugin_package = plugin_package ,
plugin_name = plugin_name ,
2016-04-28 12:29:33 +02:00
dto_package = dto_package ,
2016-05-31 17:45:16 +02:00
notification_package = notification_package ,
2016-04-28 12:29:33 +02:00
callback_package = callback_package ,
methods = " " . join ( callbacks ) ,
callback_facade_package = callback_facade_package ) )
jvpp_file . flush ( )
jvpp_file . close ( )
# Returns request name or special one from unconventional_naming_rep_req map
def get_request_name ( camel_case_dto_name , func_name ) :
if func_name in reverse_dict ( util . unconventional_naming_rep_req ) :
request_name = util . underscore_to_camelcase_upper ( reverse_dict ( util . unconventional_naming_rep_req ) [ func_name ] )
else :
request_name = camel_case_dto_name
return remove_suffix ( request_name )
def reverse_dict ( map ) :
return dict ( ( v , k ) for k , v in map . iteritems ( ) )
def remove_suffix ( name ) :
if util . is_reply ( name ) :
return util . remove_reply_suffix ( name )
else :
if util . is_dump ( name ) :
return util . remove_suffix ( name , util . dump_suffix )
else :
return name