jvpp: object model for jvpp generator (VPP-1184)
[vpp.git] / src / vpp-api / java / jvpp / gen / jvppgen / types_gen.py
old mode 100644 (file)
new mode 100755 (executable)
index c655933..3767b53
@@ -1,6 +1,6 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
 #
-# Copyright (c) 2016 Cisco and/or its affiliates.
+# 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:
 # 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
 from string import Template
 
-import util
-import jni_gen
-import dto_gen
+from jvpp_common_gen import generate_hash_code, generate_equals, generate_to_string, generate_fields
+from jvpp_model import Class
+
+
+def generate_types(work_dir, model, logger):
+    logger.debug("Generating custom types for %s " % model.json_api_files)
+
+    for t in model.types:
+        if not isinstance(t, Class):
+            continue
+        logger.debug("Generating DTO for type %s", t)
+        type_class_name = t.java_name
+        fields = t.fields
+        type_class = _TYPE_TEMPLATE.substitute(
+            plugin_package=model.plugin_package,
+            c_type_name=t.name,
+            json_filename=model.json_api_files,
+            json_definition=t.doc,
+            java_type_name=type_class_name,
+            fields=generate_fields(fields),
+            hash_code=generate_hash_code(fields),
+            equals=generate_equals(type_class_name, fields),
+            to_string=generate_to_string(type_class_name, fields)
+        )
+        with open("%s/%s.java" % (work_dir, type_class_name), "w") as f:
+            f.write(type_class)
 
-type_template = Template("""
-package $plugin_package.$type_package;
+_TYPE_TEMPLATE = Template("""
+package $plugin_package.types;
 
 /**
  * <p>This class represents $c_type_name type definition.
- * <br>It was generated by types_gen.py based on $inputfile preparsed data:
+ * <br>It was generated by jvpp_types_gen.py based on $json_filename:
  * <pre>
-$docs
+$json_definition
  * </pre>
  */
 public final class $java_type_name {
 $fields
-$methods
+$hash_code
+$equals
+$to_string
 }
 """)
-
-field_template = Template("""    public $type $name;\n""")
-
-
-def generate_type_fields(type_definition):
-    """
-    Generates fields for class representing typeonly definition
-    :param type_definition: python representation of typeonly definition
-    :return: string representing class fields
-    """
-    fields = ""
-    for t in zip(type_definition['types'], type_definition['args']):
-        field_name = util.underscore_to_camelcase(t[1])
-        fields += field_template.substitute(type=util.jni_2_java_type_mapping[t[0]],
-                                            name=field_name)
-    return fields
-
-object_struct_setter_template = Template("""
-    {
-        jclass ${field_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
-        memset (&(mp->${c_name}), 0, sizeof (mp->${c_name}));
-        ${struct_initialization}
-    }
-""")
-
-object_array_struct_setter_template = Template("""
-    {
-        jclass ${field_reference_name}ArrayElementClass = (*env)->FindClass(env, "${class_FQN}");
-        if (${field_reference_name}) {
-            size_t _i;
-            jsize cnt = (*env)->GetArrayLength (env, ${field_reference_name});
-            ${field_length_check}
-            for (_i = 0; _i < cnt; _i++) {
-                jobject ${field_reference_name}ArrayElement = (*env)->GetObjectArrayElement(env, ${field_reference_name}, _i);
-                memset (&(mp->${c_name}[_i]), 0, sizeof (mp->${c_name}[_i]));
-                ${struct_initialization}
-            }
-        }
-    }
-""")
-
-object_dto_field_setter_template = Template("""
-    {
-        jclass ${field_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
-        jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
-        jobject ${field_reference_name} = (*env)->NewObject(env, ${field_reference_name}Class,  ${field_reference_name}Constructor);
-        ${type_initialization}
-        (*env)->SetObjectField(env, dto, ${field_reference_name}FieldId, ${field_reference_name});
-        (*env)->DeleteLocalRef(env, ${field_reference_name});
-    }
-""")
-
-object_array_dto_field_setter_template = Template("""
-    {
-        jclass ${field_reference_name}Class = (*env)->FindClass(env, "${class_FQN}");
-        jobjectArray ${field_reference_name} = (*env)->NewObjectArray(env, ${field_length}, ${field_reference_name}Class, 0);
-        jmethodID ${field_reference_name}Constructor = (*env)->GetMethodID(env, ${field_reference_name}Class, "<init>", "()V");
-        unsigned int _i;
-        for (_i = 0; _i < ${field_length}; _i++) {
-            jobject ${field_reference_name}ArrayElement = (*env)->NewObject(env, ${field_reference_name}Class,  ${field_reference_name}Constructor);
-            ${type_initialization}
-            (*env)->SetObjectArrayElement(env, ${field_reference_name}, _i, ${field_reference_name}ArrayElement);
-            (*env)->DeleteLocalRef(env, ${field_reference_name}ArrayElement);
-        }
-        (*env)->SetObjectField(env, dto, ${field_reference_name}FieldId, ${field_reference_name});
-        (*env)->DeleteLocalRef(env, ${field_reference_name});
-    }
-""")
-
-
-def generate_struct_initialization(type_def, c_name_prefix, object_name, indent):
-    struct_initialization = ""
-    # field identifiers
-    for t in zip(type_def['types'], type_def['args'], type_def['lengths']):
-        field_reference_name = "${c_name}" + util.underscore_to_camelcase_upper(t[1])
-        field_name = util.underscore_to_camelcase(t[1])
-        struct_initialization += jni_gen.jni_request_identifiers_for_type(field_type=t[0],
-                                                                          field_reference_name=field_reference_name,
-                                                                          field_name=field_name,
-                                                                          object_name=object_name)
-        struct_initialization += jni_gen.jni_request_binding_for_type(field_type=t[0], c_name=c_name_prefix + t[1],
-                                                                      field_reference_name=field_reference_name,
-                                                                      field_length=t[2][0],
-                                                                      is_variable_len_array=t[2][1])
-    return indent + struct_initialization.replace('\n', '\n' + indent)
-
-
-def generate_type_setter(handler_name, type_def, c_name_prefix, object_name, indent):
-    type_initialization = ""
-    for t in zip(type_def['types'], type_def['args'], type_def['lengths']):
-        field_length = t[2][0]
-        is_variable_len_array = t[2][1]
-        length_field_type = None
-        if is_variable_len_array:
-            length_field_type = type_def['types'][type_def['args'].index(field_length)]
-        type_initialization += jni_gen.jni_reply_handler_for_type(handler_name=handler_name,
-                                                                  ref_name="${field_reference_name}",
-                                                                  field_type=t[0], c_name=c_name_prefix + t[1],
-                                                                  field_reference_name="${c_name}" + util.underscore_to_camelcase_upper(t[1]),
-                                                                  field_name=util.underscore_to_camelcase(t[1]),
-                                                                  field_length=field_length,
-                                                                  is_variable_len_array=is_variable_len_array,
-                                                                  length_field_type=length_field_type,
-                                                                  object_name=object_name)
-    return indent + type_initialization.replace('\n', '\n' + indent)
-
-
-def generate_types(types_list, plugin_package, types_package, inputfile, logger):
-    """
-    Generates Java representation of custom types defined in api file.
-    """
-
-    if not types_list:
-        logger.debug("Skipping custom types generation (%s does not define custom types)." % inputfile)
-        return
-
-    logger.debug("Generating custom types for %s" % inputfile)
-
-    if not os.path.exists(types_package):
-        os.mkdir(types_package)
-
-    for type in types_list:
-        c_type_name = type['name']
-        java_type_name = util.underscore_to_camelcase_upper(type['name'])
-        dto_path = os.path.join(types_package, java_type_name + ".java")
-
-        fields = generate_type_fields(type)
-
-        dto_file = open(dto_path, 'w')
-        dto_file.write(type_template.substitute(plugin_package=plugin_package,
-                                                type_package=types_package,
-                                                c_type_name=c_type_name,
-                                                inputfile=inputfile,
-                                                docs=util.api_message_to_javadoc(type),
-                                                java_type_name=java_type_name,
-                                                fields=fields,
-                                                methods=dto_gen.generate_dto_base_methods(java_type_name, type)
-                                                ))
-
-        # update type mappings:
-        # todo fix vpe.api to use type_name instead of vl_api_type_name_t
-        type_name = "vl_api_" + c_type_name + "_t"
-        java_fqn = "%s.%s.%s" % (plugin_package, types_package, java_type_name)
-        util.vpp_2_jni_type_mapping[type_name] = "jobject"
-        util.vpp_2_jni_type_mapping[type_name + "[]"] = "jobjectArray"
-        util.jni_2_java_type_mapping[type_name] = java_fqn
-        util.jni_2_java_type_mapping[type_name + "[]"] = java_fqn + "[]"
-        jni_name = java_fqn.replace('.', "/")
-        jni_signature = "L" + jni_name + ";"
-        util.jni_2_signature_mapping[type_name] = "L" + jni_name + ";"
-        util.jni_2_signature_mapping[type_name + "[]"] = "[" + jni_signature
-        util.jni_field_accessors[type_name] = "ObjectField"
-        util.jni_field_accessors[type_name + "[]"] = "ObjectField"
-
-        jni_gen.struct_setter_templates[type_name] = Template(
-                object_struct_setter_template.substitute(
-                        c_name="${c_name}",
-                        field_reference_name="${field_reference_name}",
-                        class_FQN=jni_name,
-                        struct_initialization=generate_struct_initialization(type, "${c_name}.",
-                                                                           "${field_reference_name}", ' ' * 4))
-        )
-
-        jni_gen.struct_setter_templates[type_name+ "[]"] = Template(
-                object_array_struct_setter_template.substitute(
-                        c_name="${c_name}",
-                        field_reference_name="${field_reference_name}",
-                        field_length_check="${field_length_check}",
-                        class_FQN=jni_name,
-                        struct_initialization=generate_struct_initialization(type, "${c_name}[_i].",
-                                                                           "${field_reference_name}ArrayElement", ' ' * 8))
-        )
-
-        jni_gen.dto_field_setter_templates[type_name] = Template(
-                object_dto_field_setter_template.substitute(
-                        field_reference_name="${field_reference_name}",
-                        field_length="${field_length}",
-                        class_FQN=jni_name,
-                        type_initialization=generate_type_setter(c_type_name, type, "${c_name}.",
-                                                                 "${field_reference_name}", ' ' * 4))
-        )
-
-        jni_gen.dto_field_setter_templates[type_name + "[]"] = Template(
-                object_array_dto_field_setter_template.substitute(
-                        field_reference_name="${field_reference_name}",
-                        field_length="${field_length}",
-                        class_FQN=jni_name,
-                        type_initialization=generate_type_setter(c_type_name, type, "${c_name}[_i].",
-                                                                 "${field_reference_name}ArrayElement", ' ' * 8))
-        )
-
-        dto_file.flush()
-        dto_file.close()
-