diff --git a/rcljava_common/CMakeLists.txt b/rcljava_common/CMakeLists.txt
index 7f474bc2..49810795 100644
--- a/rcljava_common/CMakeLists.txt
+++ b/rcljava_common/CMakeLists.txt
@@ -36,6 +36,7 @@ set(${PROJECT_NAME}_java_sources
"src/main/java/org/ros2/rcljava/common/JNIUtils.java"
"src/main/java/org/ros2/rcljava/exceptions/RCLException.java"
"src/main/java/org/ros2/rcljava/exceptions/RCLReturn.java"
+ "src/main/java/org/ros2/rcljava/interfaces/ActionDefinition.java"
"src/main/java/org/ros2/rcljava/interfaces/Disposable.java"
"src/main/java/org/ros2/rcljava/interfaces/MessageDefinition.java"
"src/main/java/org/ros2/rcljava/interfaces/ServiceDefinition.java"
diff --git a/rcljava_common/src/main/java/org/ros2/rcljava/interfaces/ActionDefinition.java b/rcljava_common/src/main/java/org/ros2/rcljava/interfaces/ActionDefinition.java
new file mode 100644
index 00000000..9681463b
--- /dev/null
+++ b/rcljava_common/src/main/java/org/ros2/rcljava/interfaces/ActionDefinition.java
@@ -0,0 +1,18 @@
+/* Copyright 2019 Open Source Robotics Foundation, Inc.
+ *
+ * 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.
+ */
+
+package org.ros2.rcljava.interfaces;
+
+public interface ActionDefinition {}
diff --git a/rosidl_generator_java/CMakeLists.txt b/rosidl_generator_java/CMakeLists.txt
index 62705679..13b0c00d 100644
--- a/rosidl_generator_java/CMakeLists.txt
+++ b/rosidl_generator_java/CMakeLists.txt
@@ -24,19 +24,17 @@ endif()
include(UseJava)
include(JavaExtra)
-set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.6" "-target" "1.6")
-
ament_index_register_resource("rosidl_generator_packages")
if(BUILD_TESTING)
find_package(rosidl_cmake REQUIRED)
find_package(rosidl_generator_c REQUIRED)
-
- find_package(ament_lint_auto REQUIRED)
+ find_package(test_interface_files REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
+ # TODO(jacobperron): Use test_interface_files instead and update tests
set(message_files
"msg/Bool.msg"
"msg/Byte.msg"
@@ -70,7 +68,9 @@ if(BUILD_TESTING)
"${CMAKE_CURRENT_SOURCE_DIR}/resource"
)
- rosidl_generate_interfaces(${PROJECT_NAME} ${message_files}
+ rosidl_generate_interfaces(${PROJECT_NAME}
+ ${message_files}
+ ${test_interface_files_SRV_FILES}
SKIP_INSTALL
)
diff --git a/rosidl_generator_java/bin/rosidl_generator_java b/rosidl_generator_java/bin/rosidl_generator_java
index 95ca2a86..a0f676d4 100755
--- a/rosidl_generator_java/bin/rosidl_generator_java
+++ b/rosidl_generator_java/bin/rosidl_generator_java
@@ -27,17 +27,13 @@ def main(argv=sys.argv[1:]):
'--generator-arguments-file',
required=True,
help='The location of the file containing the generator arguments')
- parser.add_argument(
- '--typesupport-impl',
- required=True,
- help='The typesupport implementation targeted by the C interface')
parser.add_argument(
'--typesupport-impls',
required=True,
help='All the available typesupport implementations')
args = parser.parse_args(argv)
- return generate_java(args.generator_arguments_file, args.typesupport_impl, args.typesupport_impls)
+ return generate_java(args.generator_arguments_file, args.typesupport_impls.split(';'))
if __name__ == '__main__':
diff --git a/rosidl_generator_java/cmake/custom_command.cmake b/rosidl_generator_java/cmake/custom_command.cmake
index 753c0835..db7d1cc1 100644
--- a/rosidl_generator_java/cmake/custom_command.cmake
+++ b/rosidl_generator_java/cmake/custom_command.cmake
@@ -11,19 +11,14 @@
# 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.
-
-
add_custom_command(
OUTPUT
- ${_generated_msg_java_files}
- ${_generated_msg_cpp_files}
- ${_generated_srv_java_files}
- ${_generated_srv_cpp_files}
+ ${_generated_extension_files}
+ ${_generated_java_files}
COMMAND ${PYTHON_EXECUTABLE} ${rosidl_generator_java_BIN}
--generator-arguments-file "${generator_arguments_file}"
- --typesupport-impl "${_typesupport_impl}"
--typesupport-impls "${_typesupport_impls}"
- DEPENDS ${target_dependencies}
+ DEPENDS ${target_dependencies} ${rosidl_generate_interfaces_TARGET}
COMMENT "Generating Java code for ROS interfaces"
VERBATIM
)
@@ -34,17 +29,14 @@ else()
add_custom_target(
${rosidl_generate_interfaces_TARGET}${_target_suffix}
DEPENDS
- ${_generated_msg_java_files}
- ${_generated_msg_cpp_files}
- ${_generated_srv_java_files}
- ${_generated_srv_cpp_files}
+ ${_generated_extension_files}
+ ${_generated_java_files}
)
endif()
add_jar("${PROJECT_NAME}_messages_jar"
SOURCES
- ${_generated_msg_java_files}
- ${_generated_srv_java_files}
+ ${_generated_java_files}
OUTPUT_NAME
${PROJECT_NAME}_messages
INCLUDE_JARS
diff --git a/rosidl_generator_java/cmake/register_java.cmake b/rosidl_generator_java/cmake/register_java.cmake
index d3e0b659..bcc41108 100644
--- a/rosidl_generator_java/cmake/register_java.cmake
+++ b/rosidl_generator_java/cmake/register_java.cmake
@@ -13,9 +13,9 @@
# limitations under the License.
macro(rosidl_generator_java_extras BIN GENERATOR_FILES TEMPLATE_DIR)
- find_package(ament_cmake_core QUIET REQUIRED)
+ find_package(ament_cmake_core REQUIRED)
ament_register_extension(
- "rosidl_generate_interfaces"
+ "rosidl_generate_idl_interfaces"
"rosidl_generator_java"
"rosidl_generator_java_generate_interfaces.cmake")
diff --git a/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake b/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake
index deacaa6f..e0b0ff17 100644
--- a/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake
+++ b/rosidl_generator_java/cmake/rosidl_generator_java_generate_interfaces.cmake
@@ -39,8 +39,6 @@ if(NOT WIN32)
endif()
endif()
-set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.6" "-target" "1.6")
-
# Get a list of typesupport implementations from valid rmw implementations.
rosidl_generator_java_get_typesupports(_typesupport_impls)
@@ -51,48 +49,53 @@ endif()
set(_output_path
"${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_java/${PROJECT_NAME}")
-set(_generated_cpp_files "")
-set(_generated_msg_java_files "")
-set(_generated_msg_cpp_files "")
-set(_generated_srv_java_files "")
-set(_generated_srv_cpp_files "")
+set(_generated_extension_files "")
+set(_generated_java_files "")
-foreach(_idl_file ${rosidl_generate_interfaces_IDL_FILES})
- get_filename_component(_parent_folder "${_idl_file}" DIRECTORY)
- get_filename_component(_parent_folder "${_parent_folder}" NAME)
- get_filename_component(_module_name "${_idl_file}" NAME_WE)
+foreach(_typesupport_impl ${_typesupport_impls})
+ set(_generated_extension_${_typesupport_impl}_files "")
+endforeach()
- if(_parent_folder STREQUAL "msg")
- list(APPEND _generated_msg_java_files
- "${_output_path}/${_parent_folder}/${_module_name}.java"
+foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES})
+ get_filename_component(_parent_folder "${_abs_idl_file}" DIRECTORY)
+ get_filename_component(_parent_folder "${_parent_folder}" NAME)
+ get_filename_component(_idl_name "${_abs_idl_file}" NAME_WE)
+ list(APPEND _generated_java_files
+ "${_output_path}/${_parent_folder}/${_idl_name}.java"
+ )
+ # TODO(jacobperron): Is there a more robust way of detecting services and actions
+ # Services generate extra files
+ if(_parent_folder STREQUAL "srv")
+ list(APPEND _generated_java_files
+ "${_output_path}/${_parent_folder}/${_idl_name}_Request.java"
+ "${_output_path}/${_parent_folder}/${_idl_name}_Response.java"
)
-
- foreach(_typesupport_impl ${_typesupport_impls})
- list_append_unique(_generated_msg_cpp_files
- "${_output_path}/${_parent_folder}/${_module_name}.ep.${_typesupport_impl}.cpp"
- )
- list(APPEND _type_support_by_generated_msg_cpp_files "${_typesupport_impl}")
- endforeach()
- elseif(_parent_folder STREQUAL "srv")
- list(APPEND _generated_srv_java_files
- "${_output_path}/${_parent_folder}/${_module_name}.java"
+ endif()
+ # Actions generate extra files
+ if(_parent_folder STREQUAL "action")
+ list(APPEND _generated_java_files
+ "${_output_path}/${_parent_folder}/${_idl_name}_Goal.java"
+ "${_output_path}/${_parent_folder}/${_idl_name}_Result.java"
+ "${_output_path}/${_parent_folder}/${_idl_name}_Feedback.java"
)
-
- foreach(_typesupport_impl ${_typesupport_impls})
- list_append_unique(_generated_srv_cpp_files
- "${_output_path}/${_parent_folder}/${_module_name}.ep.${_typesupport_impl}.cpp"
- )
- list(APPEND _type_support_by_generated_srv_cpp_files "${_typesupport_impl}")
- endforeach()
- else()
- message(FATAL_ERROR "Interface file with unknown parent folder: ${_idl_file}")
endif()
+
+ foreach(_typesupport_impl ${_typesupport_impls})
+ list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/${_parent_folder}/${_idl_name}.ep.${_typesupport_impl}.cpp")
+ endforeach()
+endforeach()
+
+foreach(_typesupport_impl ${_typesupport_impls})
+ foreach(_generated_file ${_generated_extension_${_typesupport_impl}_files})
+ list(APPEND _generated_extension_files "${_generated_file}")
+ list(APPEND _typesupport_by_generated_cpp_files "${_typesupport_impl}")
+ endforeach()
endforeach()
set(_dependency_files "")
set(_dependencies "")
foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES})
- foreach(_idl_file ${${_pkg_name}_INTERFACE_FILES})
+ foreach(_idl_file ${${_pkg_name}_IDL_FILES})
set(_abs_idl_file "${${_pkg_name}_DIR}/../${_idl_file}")
normalize_path(_abs_idl_file "${_abs_idl_file}")
list(APPEND _dependency_files "${_abs_idl_file}")
@@ -103,11 +106,15 @@ endforeach()
set(target_dependencies
"${rosidl_generator_java_BIN}"
${rosidl_generator_java_GENERATOR_FILES}
+ "${rosidl_generator_java_TEMPLATE_DIR}/action.cpp.em"
+ "${rosidl_generator_java_TEMPLATE_DIR}/idl.cpp.em"
"${rosidl_generator_java_TEMPLATE_DIR}/msg.cpp.em"
"${rosidl_generator_java_TEMPLATE_DIR}/srv.cpp.em"
+ "${rosidl_generator_java_TEMPLATE_DIR}/action.java.em"
+ "${rosidl_generator_java_TEMPLATE_DIR}/idl.java.em"
"${rosidl_generator_java_TEMPLATE_DIR}/msg.java.em"
"${rosidl_generator_java_TEMPLATE_DIR}/srv.java.em"
- ${rosidl_generate_interfaces_IDL_FILES}
+ ${rosidl_generate_interfaces_ABS_IDL_FILES}
${_dependency_files})
foreach(dep ${target_dependencies})
if(NOT EXISTS "${dep}")
@@ -119,7 +126,7 @@ set(generator_arguments_file "${CMAKE_BINARY_DIR}/rosidl_generator_java__argumen
rosidl_write_generator_arguments(
"${generator_arguments_file}"
PACKAGE_NAME "${PROJECT_NAME}"
- ROS_INTERFACE_FILES "${rosidl_generate_interfaces_IDL_FILES}"
+ IDL_TUPLES "${rosidl_generate_interfaces_IDL_TUPLES}"
ROS_INTERFACE_DEPENDENCIES "${_dependencies}"
OUTPUT_DIR "${_output_path}"
TEMPLATE_DIR "${rosidl_generator_java_TEMPLATE_DIR}"
@@ -128,7 +135,6 @@ rosidl_write_generator_arguments(
file(MAKE_DIRECTORY "${_output_path}")
-set(_generated_extension_files "")
set(_extension_dependencies "")
set(_target_suffix "__java")
@@ -156,10 +162,8 @@ add_subdirectory("${_subdir}" ${rosidl_generate_interfaces_TARGET}${_target_suff
set_property(
SOURCE
- ${_generated_msg_java_files}
- ${_generated_msg_cpp_files}
- ${_generated_srv_java_files}
- ${_generated_srv_cpp_files}
+ ${_generated_extension_files}
+ ${_generated_java_files}
PROPERTY GENERATED 1)
macro(set_properties _build_type)
@@ -172,28 +176,21 @@ macro(set_properties _build_type)
OUTPUT_NAME "${_library_path}")
endmacro()
-set(_type_support_by_generated_cpp_files ${_type_support_by_generated_msg_cpp_files} ${_type_support_by_generated_srv_cpp_files})
-set(_generated_cpp_files ${_generated_msg_cpp_files} ${_generated_srv_cpp_files})
-
-set(_javaext_suffix "__javaext")
-foreach(_generated_cpp_file ${_generated_cpp_files})
- get_filename_component(_full_folder "${_generated_cpp_file}" DIRECTORY)
- get_filename_component(_package_folder "${_full_folder}" DIRECTORY)
- get_filename_component(_package_name "${_package_folder}" NAME)
- get_filename_component(_parent_folder "${_full_folder}" NAME)
- get_filename_component(_base_msg_name "${_generated_cpp_file}" NAME_WE)
- list(FIND _generated_cpp_files ${_generated_cpp_file} _file_index)
- list(GET _type_support_by_generated_cpp_files ${_file_index} _typesupport_impl)
+foreach(_generated_cpp_file ${_generated_extension_files})
+ list(FIND _generated_extension_files ${_generated_cpp_file} _file_index)
+ list(GET _typesupport_by_generated_cpp_files ${_file_index} _typesupport_impl)
find_package(${_typesupport_impl} REQUIRED)
- set(_generated_msg_cpp_common_file "${_full_folder}/${_base_msg_name}.cpp")
+ get_filename_component(_parent_folder "${_generated_cpp_file}" DIRECTORY)
+ get_filename_component(_parent_folder "${_parent_folder}" NAME)
+ get_filename_component(_parent_folder "${_parent_folder}" NAME)
+ get_filename_component(_base_name "${_generated_cpp_file}" NAME_WE)
string(REGEX REPLACE "^rosidl_typesupport_" "" _short_typesupport_impl ${_typesupport_impl})
- set(_library_name
- "${_parent_folder}${_base_msg_name}${_short_typesupport_impl}"
- )
+ set(_library_name "${_parent_folder}${_base_name}${_short_typesupport_impl}")
set(_library_path
- "${_package_name}_${_parent_folder}_${_base_msg_name}__jni__${_typesupport_impl}"
+ "${rosidl_generate_interfaces_TARGET}_${_parent_folder}_${_base_name}__jni__${_typesupport_impl}"
)
string_camel_case_to_lower_case_underscore(${_library_path} _library_path)
+
add_library(${_library_name} SHARED
${_generated_cpp_file}
)
@@ -201,6 +198,7 @@ foreach(_generated_cpp_file ${_generated_cpp_files})
${_library_name}
${rosidl_generate_interfaces_TARGET}${_target_suffix}
${rosidl_generate_interfaces_TARGET}__rosidl_typesupport_c
+ ${_target_dependencies}
)
set(_extension_compile_flags "")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
@@ -248,9 +246,6 @@ foreach(_generated_cpp_file ${_generated_cpp_files})
)
target_link_libraries(${_library_name} ${${_pkg_name}_JNI_LIBRARIES})
endforeach()
- add_dependencies(${_library_name}
- ${rosidl_generate_interfaces_TARGET}__${_typesupport_impl}
- )
if(NOT rosidl_generate_interfaces_SKIP_INSTALL)
install(TARGETS ${_library_name}
ARCHIVE DESTINATION lib/jni
@@ -277,7 +272,7 @@ add_custom_command(
if(NOT rosidl_generate_interfaces_SKIP_INSTALL)
set(_install_jar_dir "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}")
- if(NOT _generated_msg_java_files STREQUAL "" OR NOT _generated_srv_java_files STREQUAL "")
+ if(NOT _generated_java_files STREQUAL "")
install_jar("${PROJECT_NAME}_messages_jar" "share/${PROJECT_NAME}/java")
ament_export_jars("share/${PROJECT_NAME}/java/${PROJECT_NAME}_messages.jar")
endif()
@@ -285,10 +280,8 @@ endif()
if(BUILD_TESTING AND rosidl_generate_interfaces_ADD_LINTER_TESTS)
if(
- NOT _generated_msg_java_files STREQUAL "" OR
- NOT _generated_msg_cpp_files STREQUAL "" OR
- NOT _generated_srv_java_files STREQUAL "" OR
- NOT _generated_srv_cpp_files STREQUAL ""
+ NOT _generated_java_files STREQUAL "" OR
+ NOT _generated_extension_files STREQUAL ""
)
find_package(ament_cmake_cppcheck REQUIRED)
ament_cppcheck(
diff --git a/rosidl_generator_java/package.xml b/rosidl_generator_java/package.xml
index 9d47a6c7..deffa059 100644
--- a/rosidl_generator_java/package.xml
+++ b/rosidl_generator_java/package.xml
@@ -35,15 +35,18 @@
rmw_implementation_cmake
rosidl_generator_c
- rosidl_parser
rosidl_cmake
+ rosidl_parser
rosidl_typesupport_c
rosidl_typesupport_connext_c
+ rosidl_typesupport_fastrtps_c
rosidl_typesupport_introspection_c
rosidl_typesupport_opensplice_c
+ test_interface_files
rosidl_generator_packages
+ rosidl_runtime_packages
ament_cmake
diff --git a/rosidl_generator_java/resource/action.cpp.em b/rosidl_generator_java/resource/action.cpp.em
new file mode 100644
index 00000000..17e456bf
--- /dev/null
+++ b/rosidl_generator_java/resource/action.cpp.em
@@ -0,0 +1,48 @@
+@# Included from rosidl_generator_java/resource/idl.cpp.em
+@{
+from rosidl_generator_c import idl_structure_type_to_c_include_prefix
+
+action_includes = [
+ 'rosidl_generator_c/action_type_support_struct.h',
+]
+}@
+@[for include in action_includes]@
+@[ if include in include_directives]@
+// already included above
+// @
+@[ else]@
+@{include_directives.add(include)}@
+@[ end if]@
+#include "@(include)"
+@[end for]@
+
+#include "@(idl_structure_type_to_c_include_prefix(action.namespaced_type)).h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+@{
+from rosidl_generator_java import get_jni_mangled_name
+
+action_fqn = action.namespaced_type.namespaced_name()
+underscore_separated_type_name = '_'.join(action_fqn)
+underscore_separated_jni_type_name = get_jni_mangled_name(action_fqn)
+}@
+/*
+ * Class: @(underscore_separated_type_name)
+ * Method: getActionTypeSupport
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getActionTypeSupport(JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getActionTypeSupport(JNIEnv *, jclass)
+{
+ const rosidl_action_type_support_t * ts = ROSIDL_GET_ACTION_TYPE_SUPPORT(
+ @(package_name), @(action.namespaced_type.name));
+ return reinterpret_cast(ts);
+}
diff --git a/rosidl_generator_java/resource/action.java.em b/rosidl_generator_java/resource/action.java.em
new file mode 100644
index 00000000..070ddd61
--- /dev/null
+++ b/rosidl_generator_java/resource/action.java.em
@@ -0,0 +1,79 @@
+@# Generation triggered from rosidl_generator_java/resource/idl.java.em
+// generated from rosidl_generator_java/resource/action.java.em
+// with input from @(package_name):@(interface_path)
+// generated code does not contain a copyright notice
+
+package @(package_name + '.' + interface_path.parts[0]);
+@{
+import os
+from rosidl_cmake import expand_template
+
+namespaces = action.namespaced_type.namespaces
+type_name = action.namespaced_type.name
+goal_type_name = action.goal.structure.namespaced_type.name
+result_type_name = action.result.structure.namespaced_type.name
+feedback_type_name = action.feedback.structure.namespaced_type.name
+
+data = {
+ 'package_name': package_name,
+ 'interface_path': interface_path,
+ 'output_dir': output_dir,
+ 'template_basepath': template_basepath,
+}
+data.update({'message': action.goal})
+output_file = os.path.join(output_dir, *namespaces[1:], goal_type_name + '.java')
+expand_template(
+ 'msg.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+
+data.update({'message': action.result})
+output_file = os.path.join(output_dir, *namespaces[1:], result_type_name + '.java')
+expand_template(
+ 'msg.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+
+data.update({'message': action.feedback})
+output_file = os.path.join(output_dir, *namespaces[1:], feedback_type_name + '.java')
+expand_template(
+ 'msg.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+
+action_imports = [
+ 'org.ros2.rcljava.common.JNIUtils',
+ 'org.ros2.rcljava.interfaces.ActionDefinition',
+ 'org.slf4j.Logger',
+ 'org.slf4j.LoggerFactory',
+]
+}@
+
+@[for action_import in action_imports]@
+import @(action_import);
+@[end for]@
+
+public class @(type_name) implements ActionDefinition {
+
+ private static final Logger logger = LoggerFactory.getLogger(@(type_name).class);
+
+ static {
+ try {
+ JNIUtils.loadTypesupport(@(type_name).class);
+ } catch (UnsatisfiedLinkError ule) {
+ logger.error("Native code library failed to load.\n" + ule);
+ System.exit(1);
+ }
+ }
+
+ public static native long getActionTypeSupport();
+
+ public static final Class<@(type_name)_Goal> GoalType = @(type_name)_Goal.class;
+
+ public static final Class<@(type_name)_Result> ResultType = @(type_name)_Result.class;
+
+ public static final Class<@(type_name)_Feedback> FeedbackType = @(type_name)_Feedback.class;
+}
diff --git a/rosidl_generator_java/resource/idl.cpp.em b/rosidl_generator_java/resource/idl.cpp.em
new file mode 100644
index 00000000..48098dd9
--- /dev/null
+++ b/rosidl_generator_java/resource/idl.cpp.em
@@ -0,0 +1,110 @@
+// generated from rosidl_generator_java/resource/idl.cpp.em
+// with input from @(package_name):@(interface_path)
+// generated code does not contain a copyright notice
+@
+@#######################################################################
+@# EmPy template for generating .cpp files
+@#
+@# Context:
+@# - package_name (string)
+@# - interface_path (Path relative to the directory named after the package)
+@# - content (IdlContent, list of elements, e.g. Messages or Services)
+@#######################################################################
+@{
+include_directives = set()
+
+jni_includes = [
+ 'jni.h',
+]
+include_directives.update(jni_includes)
+std_includes = [
+ 'cassert',
+ 'cstdint',
+ 'string',
+]
+include_directives.update(std_includes)
+rosidl_includes = [
+ 'rosidl_generator_c/message_type_support_struct.h',
+]
+include_directives.update(rosidl_includes)
+rcljava_includes = [
+ 'rcljava_common/exceptions.h',
+ 'rcljava_common/signatures.h',
+]
+include_directives.update(rcljava_includes)
+}@
+@[for include in jni_includes]@
+#include <@(include)>
+@[end for]@
+
+@[for include in std_includes]@
+#include <@(include)>
+@[end for]@
+
+@[for include in rosidl_includes]@
+#include "@(include)"
+@[end for]@
+
+@[for include in rcljava_includes]@
+#include "@(include)"
+@[end for]@
+
+// Ensure that a jlong is big enough to store raw pointers
+static_assert(sizeof(jlong) >= sizeof(std::intptr_t), "jlong must be able to store pointers");
+
+using rcljava_common::exceptions::rcljava_throw_exception;
+
+@{
+jni_package_name = package_name.replace('_', '_1')
+}@
+@
+@#######################################################################
+@# Handle messages
+@#######################################################################
+@{
+from rosidl_parser.definition import Message
+}@
+@[for message in content.get_elements_of_type(Message)]@
+@{
+TEMPLATE(
+ 'msg.cpp.em',
+ package_name=package_name,
+ jni_package_name=jni_package_name,
+ message=message,
+ include_directives=include_directives)
+}@
+@[end for]@
+@
+@#######################################################################
+@# Handle services
+@#######################################################################
+@{
+from rosidl_parser.definition import Service
+}@
+@[for service in content.get_elements_of_type(Service)]@
+@{
+TEMPLATE(
+ 'srv.cpp.em',
+ package_name=package_name,
+ jni_package_name=jni_package_name,
+ service=service,
+ include_directives=include_directives)
+}@
+@[end for]@
+@
+@#######################################################################
+@# Handle actions
+@#######################################################################
+@{
+from rosidl_parser.definition import Action
+}@
+@[for action in content.get_elements_of_type(Action)]@
+@{
+TEMPLATE(
+ 'action.cpp.em',
+ package_name=package_name,
+ jni_package_name=jni_package_name,
+ action=action,
+ include_directives=include_directives)
+}@
+@[end for]@
diff --git a/rosidl_generator_java/resource/idl.java.em b/rosidl_generator_java/resource/idl.java.em
new file mode 100644
index 00000000..f34d75c7
--- /dev/null
+++ b/rosidl_generator_java/resource/idl.java.em
@@ -0,0 +1,87 @@
+@#######################################################################
+@# EmPy template for generating .java files
+@#
+@# Context:
+@# - package_name (string)
+@# - interface_path (Path relative to the directory named after the package)
+@# - content (IdlContent, list of elements, e.g. Messages or Services)
+@# Additional context:
+@# - output_dir (Path)
+@# - template_basepath (Path)
+@#######################################################################
+@
+@#######################################################################
+@# Handle messages
+@#######################################################################
+@{
+import os
+
+from rosidl_cmake import expand_template
+from rosidl_parser.definition import Action
+from rosidl_parser.definition import Message
+from rosidl_parser.definition import Service
+
+data = {
+ 'package_name': package_name,
+ 'interface_path': interface_path,
+ 'output_dir': output_dir,
+ 'template_basepath': template_basepath,
+}
+
+for message in content.get_elements_of_type(Message):
+ data.update({'message': message})
+ type_name = message.structure.namespaced_type.name
+ namespaces = message.structure.namespaced_type.namespaces
+ output_file = os.path.join(output_dir, *namespaces[1:], type_name + '.java')
+ expand_template(
+ 'msg.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+}@
+@
+@#######################################################################
+@# Handle services
+@#######################################################################
+@{
+data = {
+ 'package_name': package_name,
+ 'interface_path': interface_path,
+ 'output_dir': output_dir,
+ 'template_basepath': template_basepath,
+}
+
+for service in content.get_elements_of_type(Service):
+ data.update({'service': service})
+ type_name = service.namespaced_type.name
+ namespaces = service.namespaced_type.namespaces
+ output_file = os.path.join(output_dir, *namespaces[1:], type_name + '.java')
+ expand_template(
+ 'srv.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+}@
+@
+@#######################################################################
+@# Handle actions
+@#######################################################################
+@{
+data = {
+ 'package_name': package_name,
+ 'interface_path': interface_path,
+ 'output_dir': output_dir,
+ 'template_basepath': template_basepath,
+}
+
+for action in content.get_elements_of_type(Action):
+ data.update({'action': action})
+ type_name = action.namespaced_type.name
+ namespaces = action.namespaced_type.namespaces
+ output_file = os.path.join(output_dir, *namespaces[1:], type_name + '.java')
+ expand_template(
+ 'action.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+}@
diff --git a/rosidl_generator_java/resource/msg.cpp.em b/rosidl_generator_java/resource/msg.cpp.em
index e1d449d4..6d1f7877 100644
--- a/rosidl_generator_java/resource/msg.cpp.em
+++ b/rosidl_generator_java/resource/msg.cpp.em
@@ -1,85 +1,26 @@
-// generated from rosidl_generator_java/resource/msg.cpp.em
-// generated code does not contain a copyright notice
-
-#include
-
-#include
-#include
-#include
-
-// Ensure that a jlong is big enough to store raw pointers
-static_assert(sizeof(jlong) >= sizeof(std::intptr_t), "jlong must be able to store pointers");
-
-#include "@(spec.base_type.pkg_name)/@(subfolder)/@(module_name).h"
-#include "rosidl_generator_c/message_type_support_struct.h"
-
-#include "rosidl_generator_c/string.h"
-#include "rosidl_generator_c/string_functions.h"
-
-#include "rosidl_generator_c/primitives_array.h"
-#include "rosidl_generator_c/primitives_array_functions.h"
-
-#include "rcljava_common/exceptions.h"
-#include "rcljava_common/signatures.h"
-
-@#JNI performance tips taken from http://planet.jboss.org/post/jni_performance_the_saga_continues
-
-using rcljava_common::exceptions::rcljava_throw_exception;
-
+@# Included from rosidl_generator_java/resource/idl.cpp.em
@{
-
from collections import defaultdict
-def get_normalized_type(type_, subfolder='msg'):
- return get_java_type(type_, use_primitives=False, subfolder=subfolder).replace('.', '__')
-
-def get_jni_type(type_, subfolder='msg'):
- return get_java_type(type_, use_primitives=False, subfolder=subfolder).replace('.', '/')
-
-constructor_signatures = defaultdict(lambda: "()V")
-constructor_signatures['java/lang/Boolean'] = "(Z)V"
-constructor_signatures['java/lang/Byte'] = "(B)V"
-constructor_signatures['java/lang/Character'] = "(C)V"
-constructor_signatures['java/lang/Double'] = "(D)V"
-constructor_signatures['java/lang/Float'] = "(F)V"
-constructor_signatures['java/lang/Integer'] = "(I)V"
-constructor_signatures['java/lang/Long'] = "(J)V"
-constructor_signatures['java/lang/Short'] = "(S)V"
-constructor_signatures['java/util/List'] = None
-
-value_methods = {}
-value_methods['java/lang/Boolean'] = ("booleanValue", "()Z")
-value_methods['java/lang/Byte'] = ("byteValue", "()B")
-value_methods['java/lang/Character'] = ("charValue", "()C")
-value_methods['java/lang/Double'] = ("doubleValue", "()D")
-value_methods['java/lang/Float'] = ("floatValue", "()F")
-value_methods['java/lang/Integer'] = ("intValue", "()I")
-value_methods['java/lang/Long'] = ("longValue", "()J")
-value_methods['java/lang/Short'] = ("shortValue", "()S")
-
-jni_signatures = {}
-jni_signatures['java/lang/Boolean'] = "Z"
-jni_signatures['java/lang/Byte'] = "B"
-jni_signatures['java/lang/Character'] = "C"
-jni_signatures['java/lang/Double'] = "D"
-jni_signatures['java/lang/Float'] = "F"
-jni_signatures['java/lang/Integer'] = "I"
-jni_signatures['java/lang/Long'] = "J"
-jni_signatures['java/lang/Short'] = "S"
-
-non_primitive_types = set()
-
-def get_constructor_signature(type_, subfolder='msg'):
- return constructor_signatures[get_jni_type(type_, subfolder=subfolder)]
-
-def get_value_method(type_, subfolder='msg'):
- return value_methods.get(get_jni_type(type_, subfolder=subfolder))
-
-def get_jni_signature(type_, subfolder='msg'):
- return jni_signatures.get(get_jni_type(type_, subfolder=subfolder))
-
-msg_normalized_type = get_normalized_type(spec.base_type, subfolder=subfolder)
-msg_jni_type = get_jni_type(spec.base_type, subfolder=subfolder)
+from rosidl_generator_c import basetype_to_c
+from rosidl_generator_c import idl_structure_type_to_c_include_prefix
+from rosidl_generator_java import constructor_signatures
+from rosidl_generator_java import get_java_type
+from rosidl_generator_java import get_jni_signature
+from rosidl_generator_java import get_jni_type
+from rosidl_generator_java import get_normalized_type
+from rosidl_generator_java import value_methods
+from rosidl_parser.definition import AbstractGenericString
+from rosidl_parser.definition import AbstractString
+from rosidl_parser.definition import AbstractWString
+from rosidl_parser.definition import AbstractNestedType
+from rosidl_parser.definition import AbstractSequence
+from rosidl_parser.definition import Array
+from rosidl_parser.definition import BasicType
+from rosidl_parser.definition import NamespacedType
+
+msg_normalized_type = '__'.join(message.structure.namespaced_type.namespaced_name())
+msg_jni_type = '/'.join(message.structure.namespaced_type.namespaced_name())
list_java_type = "java.util.List"
array_list_java_type = "java.util.ArrayList"
@@ -90,31 +31,49 @@ list_jni_type = "java/util/List"
array_list_normalized_type = "java__util__ArrayList"
array_list_jni_type = "java/util/ArrayList"
+# Collect JNI types and includes
cache = defaultdict(lambda: False)
-
cache[msg_normalized_type] = msg_jni_type
-
-# We do not cache strings because java.lang.String behaves differently
-
-unique_fields = set()
-
-for field in spec.fields:
- if field.type.is_array:
+namespaced_types = set()
+includes = set()
+for member in message.structure.members:
+ type_ = member.type
+ if isinstance(type_, AbstractNestedType):
cache[list_normalized_type] = list_jni_type
cache[array_list_normalized_type] = array_list_jni_type
-
- if not field.type.type == 'string':
- cache[get_normalized_type(field.type)] = get_jni_type(field.type)
-
- if not field.type.is_primitive_type():
- non_primitive_types.add(get_jni_type(field.type))
- unique_fields.add((field.type.pkg_name, field.type.type))
+ type_ = type_.value_type
+ if isinstance(type_, BasicType):
+ includes.add('rosidl_generator_c/primitives_sequence.h')
+ includes.add('rosidl_generator_c/primitives_sequence_functions.h')
+
+ # We do not cache strings because java.lang.String behaves differently
+ if not isinstance(type_, AbstractGenericString):
+ cache[get_normalized_type(type_)] = get_jni_type(type_)
+
+ if isinstance(type_, AbstractString):
+ includes.add('rosidl_generator_c/string.h')
+ includes.add('rosidl_generator_c/string_functions.h')
+
+ if isinstance(type_, AbstractWString):
+ includes.add('rosidl_generator_c/u16string.h')
+ includes.add('rosidl_generator_c/u16string_functions.h')
+
+ if isinstance(type_, NamespacedType):
+ namespaced_types.add(get_jni_type(type_))
+ includes.add(idl_structure_type_to_c_include_prefix(type_) + '.h')
}@
-
-@[for field_pkg_name, field_type in unique_fields]@
-#include "@(field_pkg_name)/msg/@(convert_camel_case_to_lower_case_underscore(field_type)).h"
-#include "@(field_pkg_name)/msg/@(convert_camel_case_to_lower_case_underscore(field_type))__functions.h"
+@[for include in includes]@
+@[ if include in include_directives]@
+// already included above
+// @
+@[ else]@
+@{include_directives.add(include)}@
+@[ end if]@
+#include "@(include)"
@[end for]@
+
+#include "@(idl_structure_type_to_c_include_prefix(message.structure.namespaced_type)).h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -126,15 +85,15 @@ JavaVM * g_vm = nullptr;
@[for normalized_type, jni_type in cache.items()]@
jclass _j@(normalized_type)_class_global = nullptr;
-@[if constructor_signatures[jni_type]]@
+@[ if constructor_signatures[jni_type]]@
jmethodID _j@(normalized_type)_constructor_global = nullptr;
-@[end if]@
+@[ end if]@
-@[ if value_methods.get(jni_type)]@
+@[ if value_methods.get(jni_type)]@
jmethodID _j@(normalized_type)_value_global = nullptr;
-@[ end if]@
+@[ end if]@
-@[ if jni_type in non_primitive_types]@
+@[ if jni_type in namespaced_types]@
jmethodID _j@(normalized_type)_from_java_converter_global = nullptr;
using _j@(normalized_type)_from_java_signature = @(normalized_type) * (*)(jobject, @(normalized_type) *);
jlong _j@(normalized_type)_from_java_converter_ptr_global = 0;
@@ -144,255 +103,283 @@ jmethodID _j@(normalized_type)_to_java_converter_global = nullptr;
using _j@(normalized_type)_to_java_signature = jobject (*)(@(normalized_type) *, jobject);
jlong _j@(normalized_type)_to_java_converter_ptr_global = 0;
_j@(normalized_type)_to_java_signature _j@(normalized_type)_to_java_function = nullptr;
-@[ end if]@
+@[ end if]@
@[end for]@
} // namespace
+@{
+from rosidl_generator_java import get_jni_mangled_name
+
+message_fqn = message.structure.namespaced_type.namespaced_name()
+underscore_separated_type_name = '_'.join(message_fqn)
+underscore_separated_jni_type_name = get_jni_mangled_name(message_fqn)
+}@
/*
- * Class: @(jni_package_name)_@(subfolder)_@(type_name)
+ * Class: @(underscore_separated_type_name)
* Method: getFromJavaConverter
* Signature: ()J
*/
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getFromJavaConverter
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getFromJavaConverter
(JNIEnv *, jclass);
/*
- * Class: @(jni_package_name)_@(subfolder)_@(type_name)
+ * Class: @(underscore_separated_type_name)
* Method: getToJavaConverter
* Signature: ()J
*/
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getToJavaConverter
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getToJavaConverter
(JNIEnv *, jclass);
/*
- * Class: @(jni_package_name)_@(subfolder)_@(type_name)
+ * Class: @(underscore_separated_type_name)
* Method: getTypeSupport
* Signature: ()J
*/
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getTypeSupport
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getTypeSupport
(JNIEnv *, jclass);
/*
- * Class: @(jni_package_name)_@(subfolder)_@(type_name)
+ * Class: @(underscore_separated_type_name)
* Method: getDestructor
* Signature: ()J
*/
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getDestructor
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getDestructor
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
-@# Avoid warnings about unused arguments if the message definition does not contain any fields
-@[if spec.fields]@
-@(msg_normalized_type) * @(spec.base_type.pkg_name)_@(type_name)__convert_from_java(jobject _jmessage_obj, @(msg_normalized_type) * ros_message)
+@# Avoid warnings about unused arguments if the message definition does not contain any members
+@[if message.structure.members]@
+@(msg_normalized_type) * @(underscore_separated_type_name)__convert_from_java(jobject _jmessage_obj, @(msg_normalized_type) * ros_message)
@[else]@
-@(msg_normalized_type) * @(spec.base_type.pkg_name)_@(type_name)__convert_from_java(jobject, @(msg_normalized_type) * ros_message)
+@(msg_normalized_type) * @(underscore_separated_type_name)__convert_from_java(jobject, @(msg_normalized_type) * ros_message)
@[end if]@
{
JNIEnv * env = nullptr;
// TODO(esteve): check return status
assert(g_vm != nullptr);
- g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6);
+ g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8);
assert(env != nullptr);
if (ros_message == nullptr) {
ros_message = @(msg_normalized_type)__create();
}
-@[for field in spec.fields]@
+@[for member in message.structure.members]@
@{
-normalized_type = get_normalized_type(field.type)
+normalized_type = get_normalized_type(member.type)
}@
-@[ if field.type.is_array]
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "L@(list_jni_type);");
- jobject _jlist_@(field.name)_object = env->GetObjectField(_jmessage_obj, _jfield_@(field.name)_fid);
-
- if (_jlist_@(field.name)_object != nullptr) {
- jmethodID _jlist_@(field.name)_get_mid = env->GetMethodID(_j@(list_normalized_type)_class_global, "get", "(I)Ljava/lang/Object;");
-@[ if field.type.array_size is None or field.type.is_upper_bound]@
- jmethodID _jlist_@(field.name)_size_mid = env->GetMethodID(_j@(list_normalized_type)_class_global, "size", "()I");
- jint _jlist_@(field.name)_size = env->CallIntMethod(_jlist_@(field.name)_object, _jlist_@(field.name)_size_mid);
-@[ if field.type.type == 'string']@
- if (!rosidl_generator_c__String__Array__init(&(ros_message->@(field.name)), _jlist_@(field.name)_size)) {
+@[ if isinstance(member.type, AbstractNestedType)]
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "L@(list_jni_type);");
+ jobject _jlist_@(member.name)_object = env->GetObjectField(_jmessage_obj, _jfield_@(member.name)_fid);
+
+ if (_jlist_@(member.name)_object != nullptr) {
+ jmethodID _jlist_@(member.name)_get_mid = env->GetMethodID(_j@(list_normalized_type)_class_global, "get", "(I)Ljava/lang/Object;");
+@[ if isinstance(member.type, AbstractSequence)]@
+ jmethodID _jlist_@(member.name)_size_mid = env->GetMethodID(_j@(list_normalized_type)_class_global, "size", "()I");
+ jint _jlist_@(member.name)_size = env->CallIntMethod(_jlist_@(member.name)_object, _jlist_@(member.name)_size_mid);
+@[ if isinstance(member.type.value_type, AbstractString)]@
+ if (!rosidl_generator_c__String__Sequence__init(&(ros_message->@(member.name)), _jlist_@(member.name)_size)) {
rcljava_throw_exception(env, "java/lang/IllegalStateException", "unable to create String__Array ros_message");
}
-@[ else]@
-@[ if field.type.is_primitive_type()]@
- if (!rosidl_generator_c__@(field.type.type)__Array__init(&(ros_message->@(field.name)), _jlist_@(field.name)_size)) {
- rcljava_throw_exception(env, "java/lang/IllegalStateException", "unable to create @(field.type.type)__Array ros_message");
+@[ elif isinstance(member.type.value_type, AbstractWString)]@
+ if (!rosidl_generator_c__U16String__Sequence__init(&(ros_message->@(member.name)), _jlist_@(member.name)_size)) {
+ rcljava_throw_exception(env, "java/lang/IllegalStateException", "unable to create U16String__Array ros_message");
}
-@[ else]@
- if (!@(field.type.pkg_name)__msg__@(field.type.type)__Array__init(&(ros_message->@(field.name)), _jlist_@(field.name)_size)) {
- rcljava_throw_exception(env, "java/lang/IllegalStateException", "unable to create @(field.type.type)__Array ros_message");
+@[ else]@
+@[ if isinstance(member.type.value_type, BasicType)]@
+ if (!rosidl_generator_c__@(member.type.value_type.typename)__Sequence__init(&(ros_message->@(member.name)), _jlist_@(member.name)_size)) {
+ rcljava_throw_exception(env, "java/lang/IllegalStateException", "unable to create @(member.type.value_type)__Array ros_message");
}
-
-@[ end if]@
-@[ end if]@
- auto _dest_@(field.name) = ros_message->@(field.name).data;
@[ else]@
- jint _jlist_@(field.name)_size = @(field.type.array_size);
+ if (!@('__'.join(member.type.value_type.namespaced_name()))__Sequence__init(&(ros_message->@(member.name)), _jlist_@(member.name)_size)) {
+ rcljava_throw_exception(env, "java/lang/IllegalStateException", "unable to create @(member.type.value_type)__Array ros_message");
+ }
- auto _dest_@(field.name) = ros_message->@(field.name);
@[ end if]@
+@[ end if]@
+ auto _dest_@(member.name) = ros_message->@(member.name).data;
+@[ else]@
+ jint _jlist_@(member.name)_size = @(member.type.size);
+
+ auto _dest_@(member.name) = ros_message->@(member.name);
+@[ end if]@
- for (jint i = 0; i < _jlist_@(field.name)_size; ++i) {
- auto element = env->CallObjectMethod(_jlist_@(field.name)_object, _jlist_@(field.name)_get_mid, i);
-@[ if field.type.is_primitive_type()]@
-@[ if field.type.type == 'string']@
- jstring _jfield_@(field.name)_value = static_cast(element);
- if (_jfield_@(field.name)_value != nullptr) {
- const char * _str@(field.name) = env->GetStringUTFChars(_jfield_@(field.name)_value, 0);
+ for (jint i = 0; i < _jlist_@(member.name)_size; ++i) {
+ auto element = env->CallObjectMethod(_jlist_@(member.name)_object, _jlist_@(member.name)_get_mid, i);
+@[ if isinstance(member.type.value_type, AbstractString)]@
+ jstring _jfield_@(member.name)_value = static_cast(element);
+ if (_jfield_@(member.name)_value != nullptr) {
+ const char * _str@(member.name) = env->GetStringUTFChars(_jfield_@(member.name)_value, 0);
rosidl_generator_c__String__assign(
- &_dest_@(field.name)[i], _str@(field.name));
- env->ReleaseStringUTFChars(_jfield_@(field.name)_value, _str@(field.name));
+ &_dest_@(member.name)[i], _str@(member.name));
+ env->ReleaseStringUTFChars(_jfield_@(member.name)_value, _str@(member.name));
+ }
+@[ elif isinstance(member.type.value_type, AbstractWString)]@
+ jstring _jfield_@(member.name)_value = static_cast(element);
+ if (_jfield_@(member.name)_value != nullptr) {
+ const jchar * _str@(member.name) = env->GetStringChars(_jfield_@(member.name)_value, 0);
+ rosidl_generator_c__U16String__assign(
+ &_dest_@(member.name)[i], _str@(member.name));
+ env->ReleaseStringChars(_jfield_@(member.name)_value, _str@(member.name));
}
-@[ else]@
+@[ elif isinstance(member.type.value_type, BasicType)]@
@{
-call_method_name = 'Call%sMethod' % get_java_type(field.type, use_primitives=True).capitalize()
+call_method_name = 'Call%sMethod' % get_java_type(member.type.value_type, use_primitives=True).capitalize()
}@
- _dest_@(field.name)[i] = env->@(call_method_name)(element, _j@(normalized_type)_value_global);
-@[ end if]@
-@[ else]@
- _dest_@(field.name)[i] = *_j@(normalized_type)_from_java_function(element, nullptr);
-@[ end if]@
+ _dest_@(member.name)[i] = env->@(call_method_name)(element, _j@(normalized_type)_value_global);
+@[ else]@
+ _dest_@(member.name)[i] = *_j@(normalized_type)_from_java_function(element, nullptr);
+@[ end if]@
env->DeleteLocalRef(element);
}
}
-@[ else]@
-@[ if field.type.is_primitive_type()]@
-@[ if field.type.type == 'string']@
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "Ljava/lang/String;");
- jstring _jvalue@(field.name) = static_cast(env->GetObjectField(_jmessage_obj, _jfield_@(field.name)_fid));
-
- if (_jvalue@(field.name) != nullptr) {
- const char * _str@(field.name) = env->GetStringUTFChars(_jvalue@(field.name), 0);
+@[ else]@
+@[ if isinstance(member.type, AbstractGenericString)]@
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "Ljava/lang/String;");
+ jstring _jvalue@(member.name) = static_cast(env->GetObjectField(_jmessage_obj, _jfield_@(member.name)_fid));
+
+ if (_jvalue@(member.name) != nullptr) {
+@[ if isinstance(member.type, AbstractString)]@
+ const char * _str@(member.name) = env->GetStringUTFChars(_jvalue@(member.name), 0);
rosidl_generator_c__String__assign(
- &ros_message->@(field.name), _str@(field.name));
- env->ReleaseStringUTFChars(_jvalue@(field.name), _str@(field.name));
+ &ros_message->@(member.name), _str@(member.name));
+ env->ReleaseStringUTFChars(_jvalue@(member.name), _str@(member.name));
+@[ else]@
+ const jchar * _str@(member.name) = env->GetStringChars(_jvalue@(member.name), 0);
+ rosidl_generator_c__U16String__assign(
+ &ros_message->@(member.name), _str@(member.name));
+ env->ReleaseStringChars(_jvalue@(member.name), _str@(member.name));
+@[ end if]@
}
-@[ else]@
+@[ elif isinstance(member.type, BasicType)]@
@{
-jni_signature = get_jni_signature(field.type)
-get_method_name = 'Get%sField' % get_java_type(field.type, use_primitives=True).capitalize()
+jni_signature = get_jni_signature(member.type)
+get_method_name = 'Get%sField' % get_java_type(member.type, use_primitives=True).capitalize()
}@
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "@(jni_signature)");
- ros_message->@(field.name) = env->@(get_method_name)(_jmessage_obj, _jfield_@(field.name)_fid);
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "@(jni_signature)");
+ ros_message->@(member.name) = env->@(get_method_name)(_jmessage_obj, _jfield_@(member.name)_fid);
-@[ end if]@
-@[ else]@
- auto _jfield_@(field.name)_fid = env->GetFieldID(
- _j@(msg_normalized_type)_class_global, "@(field.name)", "L@(field.type.pkg_name)/msg/@(field.type.type);");
- assert(_jfield_@(field.name)_fid != nullptr);
+@[ else]@
+ auto _jfield_@(member.name)_fid = env->GetFieldID(
+ _j@(msg_normalized_type)_class_global, "@(member.name)", "L@('/'.join(member.type.namespaced_name()));");
+ assert(_jfield_@(member.name)_fid != nullptr);
- jobject _jfield_@(field.name)_obj = env->GetObjectField(_jmessage_obj, _jfield_@(field.name)_fid);
+ jobject _jfield_@(member.name)_obj = env->GetObjectField(_jmessage_obj, _jfield_@(member.name)_fid);
- if (_jfield_@(field.name)_obj != nullptr) {
- ros_message->@(field.name) = *_j@(normalized_type)_from_java_function(_jfield_@(field.name)_obj, nullptr);
+ if (_jfield_@(member.name)_obj != nullptr) {
+ ros_message->@(member.name) = *_j@(normalized_type)_from_java_function(_jfield_@(member.name)_obj, nullptr);
}
- env->DeleteLocalRef(_jfield_@(field.name)_obj);
-@[ end if]@
+ env->DeleteLocalRef(_jfield_@(member.name)_obj);
@[ end if]@
+@[ end if]@
@[end for]@
assert(ros_message != nullptr);
return ros_message;
}
@# Avoid warnings about unused arguments if the message definition does not contain any fields
-@[if spec.fields]@
-jobject @(spec.base_type.pkg_name)_@(type_name)__convert_to_java(@(msg_normalized_type) * _ros_message, jobject _jmessage_obj)
+@[if message.structure.members]@
+jobject @(underscore_separated_type_name)__convert_to_java(@(msg_normalized_type) * _ros_message, jobject _jmessage_obj)
@[else]@
-jobject @(spec.base_type.pkg_name)_@(type_name)__convert_to_java(@(msg_normalized_type) *, jobject _jmessage_obj)
+jobject @(underscore_separated_type_name)__convert_to_java(@(msg_normalized_type) *, jobject _jmessage_obj)
@[end if]@
{
JNIEnv * env = nullptr;
// TODO(esteve): check return status
assert(g_vm != nullptr);
- g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6);
+ g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8);
assert(env != nullptr);
if (_jmessage_obj == nullptr) {
_jmessage_obj = env->NewObject(_j@(msg_normalized_type)_class_global, _j@(msg_normalized_type)_constructor_global);
}
-@[for field in spec.fields]@
+@[for member in message.structure.members]@
@{
-normalized_type = get_normalized_type(field.type)
+normalized_type = get_normalized_type(member.type)
}@
-@[ if field.type.is_array]@
-@[ if field.type.is_primitive_type()]@
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "L@(list_jni_type);");
- jobject _jarray_list_@(field.name)_obj = env->NewObject(_j@(array_list_normalized_type)_class_global, _j@(array_list_normalized_type)_constructor_global);
-@[ if field.type.array_size and not field.type.is_upper_bound]@
- for (size_t i = 0; i < @(field.type.array_size); ++i) {
- auto _ros_@(field.name)_element = _ros_message->@(field.name)[i];
-@[ else]@
- for (size_t i = 0; i < _ros_message->@(field.name).size; ++i) {
- auto _ros_@(field.name)_element = _ros_message->@(field.name).data[i];
-@[ end if]@
-@[ if field.type.type == 'string']@
- jobject _jlist_@(field.name)_element = nullptr;
- if (_ros_@(field.name)_element.data != nullptr) {
- _jlist_@(field.name)_element = env->NewStringUTF(_ros_@(field.name)_element.data);
+@[ if isinstance(member.type, AbstractNestedType)]@
+@[ if isinstance(member.type.value_type, (BasicType, AbstractGenericString))]@
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "L@(list_jni_type);");
+ jobject _jarray_list_@(member.name)_obj = env->NewObject(_j@(array_list_normalized_type)_class_global, _j@(array_list_normalized_type)_constructor_global);
+@[ if isinstance(member.type, Array)]@
+ for (size_t i = 0; i < @(member.type.size); ++i) {
+ auto _ros_@(member.name)_element = _ros_message->@(member.name)[i];
+@[ else]@
+ for (size_t i = 0; i < _ros_message->@(member.name).size; ++i) {
+ auto _ros_@(member.name)_element = _ros_message->@(member.name).data[i];
+@[ end if]@
+@[ if isinstance(member.type.value_type, AbstractGenericString)]@
+ jobject _jlist_@(member.name)_element = nullptr;
+ if (_ros_@(member.name)_element.data != nullptr) {
+@[ if isinstance(member.type.value_type, AbstractString)]@
+ _jlist_@(member.name)_element = env->NewStringUTF(_ros_@(member.name)_element.data);
+@[ else]@
+ _jlist_@(member.name)_element = env->NewString(_ros_@(member.name)_element.data, _ros_@(member.name)_element.size);
+@[ end if]@
}
-@[ else]@
- jobject _jlist_@(field.name)_element = env->NewObject(
- _j@(normalized_type)_class_global, _j@(normalized_type)_constructor_global, _ros_@(field.name)_element);
-@[ end if]@
+@[ else]@
+ jobject _jlist_@(member.name)_element = env->NewObject(
+ _j@(normalized_type)_class_global, _j@(normalized_type)_constructor_global, _ros_@(member.name)_element);
+@[ end if]@
// TODO(esteve): replace ArrayList with a jobjectArray to initialize the array beforehand
- jmethodID _jlist_@(field.name)_add_mid = env->GetMethodID(
+ jmethodID _jlist_@(member.name)_add_mid = env->GetMethodID(
_j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z");
- if (_jlist_@(field.name)_element != nullptr) {
- jboolean _jlist_@(field.name)_add_result = env->CallBooleanMethod(_jarray_list_@(field.name)_obj, _jlist_@(field.name)_add_mid, _jlist_@(field.name)_element);
- assert(_jlist_@(field.name)_add_result);
+ if (_jlist_@(member.name)_element != nullptr) {
+ jboolean _jlist_@(member.name)_add_result = env->CallBooleanMethod(_jarray_list_@(member.name)_obj, _jlist_@(member.name)_add_mid, _jlist_@(member.name)_element);
+ assert(_jlist_@(member.name)_add_result);
}
}
-@[ else]@
+@[ else]@
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "L@(list_jni_type);");
- jobject _jarray_list_@(field.name)_obj = env->NewObject(_j@(array_list_normalized_type)_class_global, _j@(array_list_normalized_type)_constructor_global);
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "L@(list_jni_type);");
+ jobject _jarray_list_@(member.name)_obj = env->NewObject(_j@(array_list_normalized_type)_class_global, _j@(array_list_normalized_type)_constructor_global);
-@[ if field.type.array_size and not field.type.is_upper_bound]@
- for (size_t i = 0; i < @(field.type.array_size); ++i) {
- jobject _jlist_@(field.name)_element = _j@(normalized_type)_to_java_function(&(_ros_message->@(field.name)[i]), nullptr);
-@[ else]@
- for (size_t i = 0; i < _ros_message->@(field.name).size; ++i) {
- jobject _jlist_@(field.name)_element = _j@(normalized_type)_to_java_function(&(_ros_message->@(field.name).data[i]), nullptr);
-@[ end if]@
+@[ if isinstance(member.type, Array)]@
+ for (size_t i = 0; i < @(member.type.size); ++i) {
+ jobject _jlist_@(member.name)_element = _j@(normalized_type)_to_java_function(&(_ros_message->@(member.name)[i]), nullptr);
+@[ else]@
+ for (size_t i = 0; i < _ros_message->@(member.name).size; ++i) {
+ jobject _jlist_@(member.name)_element = _j@(normalized_type)_to_java_function(&(_ros_message->@(member.name).data[i]), nullptr);
+@[ end if]@
// TODO(esteve): replace ArrayList with a jobjectArray to initialize the array beforehand
- jmethodID _jlist_@(field.name)_add_mid = env->GetMethodID(_j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z");
- if (_jlist_@(field.name)_element != nullptr) {
- jboolean _jlist_@(field.name)_add_result = env->CallBooleanMethod(_jarray_list_@(field.name)_obj, _jlist_@(field.name)_add_mid, _jlist_@(field.name)_element);
- assert(_jlist_@(field.name)_add_result);
+ jmethodID _jlist_@(member.name)_add_mid = env->GetMethodID(_j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z");
+ if (_jlist_@(member.name)_element != nullptr) {
+ jboolean _jlist_@(member.name)_add_result = env->CallBooleanMethod(_jarray_list_@(member.name)_obj, _jlist_@(member.name)_add_mid, _jlist_@(member.name)_element);
+ assert(_jlist_@(member.name)_add_result);
}
}
-@[ end if]@
- env->SetObjectField(_jmessage_obj, _jfield_@(field.name)_fid, _jarray_list_@(field.name)_obj);
- env->DeleteLocalRef(_jarray_list_@(field.name)_obj);
-@[ else]@
-@[ if field.type.is_primitive_type()]@
-@[ if field.type.type == 'string']@
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "Ljava/lang/String;");
- if (_ros_message->@(field.name).data != nullptr) {
- env->SetObjectField(_jmessage_obj, _jfield_@(field.name)_fid, env->NewStringUTF(_ros_message->@(field.name).data));
+@[ end if]@
+ env->SetObjectField(_jmessage_obj, _jfield_@(member.name)_fid, _jarray_list_@(member.name)_obj);
+ env->DeleteLocalRef(_jarray_list_@(member.name)_obj);
+@[ else]@
+@[ if isinstance(member.type, AbstractGenericString)]@
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "Ljava/lang/String;");
+ if (_ros_message->@(member.name).data != nullptr) {
+@[ if isinstance(member.type, AbstractString)]@
+ env->SetObjectField(_jmessage_obj, _jfield_@(member.name)_fid, env->NewStringUTF(_ros_message->@(member.name).data));
+@[ else]@
+ env->SetObjectField(_jmessage_obj, _jfield_@(member.name)_fid, env->NewString(_ros_message->@(member.name).data, _ros_message->@(member.name).size));
+@[ end if]@
}
-@[ else]@
+@[ elif isinstance(member.type, BasicType)]@
@{
-jni_signature = get_jni_signature(field.type)
-set_method_name = 'Set%sField' % get_java_type(field.type, use_primitives=True).capitalize()
+jni_signature = get_jni_signature(member.type)
+set_method_name = 'Set%sField' % get_java_type(member.type, use_primitives=True).capitalize()
}@
- auto _jfield_@(field.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(field.name)", "@(jni_signature)");
- env->@(set_method_name)(_jmessage_obj, _jfield_@(field.name)_fid, _ros_message->@(field.name));
-@[ end if]@
-@[ else]@
- auto _jfield_@(field.name)_fid = env->GetFieldID(
- _j@(msg_normalized_type)_class_global, "@(field.name)", "L@(field.type.pkg_name)/msg/@(field.type.type);");
- assert(_jfield_@(field.name)_fid != nullptr);
+ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "@(jni_signature)");
+ env->@(set_method_name)(_jmessage_obj, _jfield_@(member.name)_fid, _ros_message->@(member.name));
+@[ else]@
+ auto _jfield_@(member.name)_fid = env->GetFieldID(
+ _j@(msg_normalized_type)_class_global, "@(member.name)", "L@('/'.join(member.type.namespaced_name()));");
+ assert(_jfield_@(member.name)_fid != nullptr);
- jobject _jfield_@(field.name)_obj = _j@(normalized_type)_to_java_function(&(_ros_message->@(field.name)), nullptr);
+ jobject _jfield_@(member.name)_obj = _j@(normalized_type)_to_java_function(&(_ros_message->@(member.name)), nullptr);
- env->SetObjectField(_jmessage_obj, _jfield_@(field.name)_fid, _jfield_@(field.name)_obj);
-@[ end if]@
+ env->SetObjectField(_jmessage_obj, _jfield_@(member.name)_fid, _jfield_@(member.name)_obj);
@[ end if]@
+@[ end if]@
@[end for]@
assert(_jmessage_obj != nullptr);
return _jmessage_obj;
@@ -406,7 +393,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void *)
}
JNIEnv * env;
- if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) {
+ if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8) != JNI_OK) {
return JNI_ERR;
} else {
@[for normalized_type, jni_type in cache.items()]@
@@ -415,20 +402,20 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void *)
_j@(normalized_type)_class_global = static_cast(env->NewGlobalRef(_j@(normalized_type)_class_local));
env->DeleteLocalRef(_j@(normalized_type)_class_local);
assert(_j@(normalized_type)_class_global != nullptr);
-@[if constructor_signatures[jni_type]]@
+@[ if constructor_signatures[jni_type]]@
_j@(normalized_type)_constructor_global = env->GetMethodID(_j@(normalized_type)_class_global, "", "@(constructor_signatures[jni_type])");
assert(_j@(normalized_type)_constructor_global != nullptr);
-@[end if]@
+@[ end if]@
@{
value_method = value_methods.get(jni_type)
if value_method:
value_method_name, value_method_signature = value_method
}@
-@[ if value_method]@
+@[ if value_method]@
_j@(normalized_type)_value_global = env->GetMethodID(_j@(normalized_type)_class_global, "@(value_method_name)", "@(value_method_signature)");
assert(_j@(normalized_type)_value_global != nullptr);
-@[ end if]@
-@[ if jni_type in non_primitive_types]@
+@[ end if]@
+@[ if jni_type in namespaced_types]@
_j@(normalized_type)_from_java_converter_global = env->GetStaticMethodID(
_j@(normalized_type)_class_global, "getFromJavaConverter", "()J");
assert(_j@(normalized_type)_from_java_converter_global != nullptr);
@@ -452,10 +439,10 @@ if value_method:
_j@(normalized_type)_to_java_function =
reinterpret_cast<_j@(normalized_type)_to_java_signature>(_j@(normalized_type)_to_java_converter_ptr_global);
assert(_j@(normalized_type)_to_java_function != nullptr);
-@[ end if]@
+@[ end if]@
@[end for]@
}
- return JNI_VERSION_1_6;
+ return JNI_VERSION_1_8;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM * vm, void *)
@@ -464,18 +451,18 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM * vm, void *)
assert(g_vm == vm);
JNIEnv * env;
- if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) == JNI_OK) {
+ if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8) == JNI_OK) {
@[for normalized_type, jni_type in cache.items()]@
if (_j@(normalized_type)_class_global != nullptr) {
env->DeleteGlobalRef(_j@(normalized_type)_class_global);
_j@(normalized_type)_class_global = nullptr;
-@[ if constructor_signatures[jni_type]]@
+@[ if constructor_signatures[jni_type]]@
_j@(normalized_type)_constructor_global = nullptr;
-@[ end if]@
-@[ if value_methods.get(jni_type)]@
+@[ end if]@
+@[ if value_methods.get(jni_type)]@
_j@(normalized_type)_value_global = nullptr;
-@[ end if]@
-@[ if jni_type in non_primitive_types]@
+@[ end if]@
+@[ if jni_type in namespaced_types]@
_j@(normalized_type)_from_java_converter_global = nullptr;
_j@(normalized_type)_from_java_converter_ptr_global = 0;
_j@(normalized_type)_from_java_function = nullptr;
@@ -483,31 +470,31 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM * vm, void *)
_j@(normalized_type)_to_java_converter_global = nullptr;
_j@(normalized_type)_to_java_converter_ptr_global = 0;
_j@(normalized_type)_to_java_function = nullptr;
-@[ end if]@
+@[ end if]@
}
@[end for]@
}
}
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getFromJavaConverter(JNIEnv *, jclass)
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getFromJavaConverter(JNIEnv *, jclass)
{
- jlong ptr = reinterpret_cast(&@(spec.base_type.pkg_name)_@(type_name)__convert_from_java);
+ jlong ptr = reinterpret_cast(&@(underscore_separated_type_name)__convert_from_java);
return ptr;
}
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getToJavaConverter(JNIEnv *, jclass)
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getToJavaConverter(JNIEnv *, jclass)
{
- jlong ptr = reinterpret_cast(@(spec.base_type.pkg_name)_@(type_name)__convert_to_java);
+ jlong ptr = reinterpret_cast(@(underscore_separated_type_name)__convert_to_java);
return ptr;
}
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getTypeSupport(JNIEnv *, jclass)
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getTypeSupport(JNIEnv *, jclass)
{
- jlong ptr = reinterpret_cast(ROSIDL_GET_MSG_TYPE_SUPPORT(@(spec.base_type.pkg_name), @(subfolder), @(spec.msg_name)));
+ jlong ptr = reinterpret_cast(ROSIDL_GET_MSG_TYPE_SUPPORT(@(','.join(message.structure.namespaced_type.namespaced_name()))));
return ptr;
}
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getDestructor(JNIEnv *, jclass)
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getDestructor(JNIEnv *, jclass)
{
jlong ptr = reinterpret_cast(@(msg_normalized_type)__destroy);
return ptr;
diff --git a/rosidl_generator_java/resource/msg.java.em b/rosidl_generator_java/resource/msg.java.em
index 4409c1f3..cb6e1b3a 100644
--- a/rosidl_generator_java/resource/msg.java.em
+++ b/rosidl_generator_java/resource/msg.java.em
@@ -1,18 +1,41 @@
-package @(package_name).@(subfolder);
-
-import org.ros2.rcljava.common.JNIUtils;
-import org.ros2.rcljava.interfaces.MessageDefinition;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
+@# Generation triggered from rosidl_generator_java/resource/idl.java.em
+// generated from rosidl_generator_java/resource/msg.java.em
+// with input from @(package_name):@(interface_path)
+// generated code does not contain a copyright notice
+
+package @(package_name + '.' + interface_path.parts[0]);
+@{
+from rosidl_generator_java import convert_lower_case_underscore_to_camel_case
+from rosidl_generator_java import get_java_type
+from rosidl_generator_java import primitive_value_to_java
+from rosidl_generator_java import value_to_java
+from rosidl_parser.definition import AbstractGenericString
+from rosidl_parser.definition import AbstractNestedType
+from rosidl_parser.definition import Array
+from rosidl_parser.definition import BasicType
+from rosidl_parser.definition import BoundedSequence
+from rosidl_parser.definition import NamespacedType
+
+type_name = message.structure.namespaced_type.name
+
+message_imports = [
+ 'org.apache.commons.lang3.builder.EqualsBuilder',
+ 'org.apache.commons.lang3.builder.HashCodeBuilder',
+ 'org.ros2.rcljava.common.JNIUtils',
+ 'org.ros2.rcljava.interfaces.MessageDefinition',
+ 'org.slf4j.Logger',
+ 'org.slf4j.LoggerFactory',
+]
+}@
+@[for message_import in message_imports]@
+import @(message_import);
+@[end for]@
-@[for field in spec.fields]@
-@[ if not field.type.is_primitive_type()]@
-import @(field.type.pkg_name).msg.@(field.type.type);
-@[ end if]@
+@[for member in message.structure.members]@
+@[ if isinstance(member.type, NamespacedType)]@
+// Member '@(member.name)'
+import @('.'.join(member.type.namespaced_name()));
+@[ end if]@
@[end for]@
public final class @(type_name) implements MessageDefinition {
@@ -49,85 +72,84 @@ public final class @(type_name) implements MessageDefinition {
return @(type_name).getTypeSupport();
}
-@[for constant in spec.constants]@
- public static final @(get_builtin_java_type(constant.type)) @(constant.name) = @(constant_value_to_java(constant.type, constant.value));
+@[for constant in message.constants]@
+ public static final @(get_java_type(constant.type)) @(constant.name) = @(primitive_value_to_java(constant.type, constant.value));
@[end for]@
-@[for field in spec.fields]@
-
-@[ if field.type.is_array]@
-@[ if field.default_value is not None]@
- private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name) = java.util.Arrays.asList(new @(get_java_type(field.type, use_primitives=False))[] @(value_to_java(field.type, field.default_value)));
-@[ else]@
-@[ if field.type.array_size]@
- private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name);
-@[ else]@
- private java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name) = new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>();
-@[ end if]@
-@[ end if]@
-
- public final @(type_name) set@(convert_lower_case_underscore_to_camel_case(field.name))(final java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name)) {
-@[ if field.type.array_size]@
-@[ if field.type.is_upper_bound]@
- if(@(field.name).size() > @(field.type.array_size)) {
- throw new IllegalArgumentException("List too big, maximum size allowed: @(field.type.array_size)");
-@[ else]@
- if(@(field.name).size() != @(field.type.array_size)) {
- throw new IllegalArgumentException("Invalid size for fixed array, must be exactly: @(field.type.array_size)");
-@[ end if]@
+@[for member in message.structure.members]@
+
+@[ if isinstance(member.type, AbstractNestedType)]@
+@[ if member.has_annotation('default')]@
+ private java.util.List<@(get_java_type(member.type, use_primitives=False))> @(member.name) = java.util.Arrays.asList(new @(get_java_type(member.type, use_primitives=False))[] @(value_to_java(member.type, member.get_annotation_value('default')['value'])));
+@[ else]@
+@[ if isinstance(member.type, Array)]@
+ private java.util.List<@(get_java_type(member.type, use_primitives=False))> @(member.name);
+@[ else]@
+ private java.util.List<@(get_java_type(member.type, use_primitives=False))> @(member.name) = new java.util.ArrayList<@(get_java_type(member.type, use_primitives=False))>();
+@[ end if]@
+@[ end if]@
+
+ public final @(type_name) set@(convert_lower_case_underscore_to_camel_case(member.name))(final java.util.List<@(get_java_type(member.type, use_primitives=False))> @(member.name)) {
+@[ if isinstance(member.type, BoundedSequence)]@
+ if(@(member.name).size() > @(member.type.maximum_size)) {
+ throw new IllegalArgumentException("List too big, maximum size allowed: @(member.type.maximum_size)");
+ }
+@[ elif isinstance(member.type, Array)]@
+ if(@(member.name).size() != @(member.type.size)) {
+ throw new IllegalArgumentException("Invalid size for fixed array, must be exactly: @(member.type.size)");
}
-@[ end if]@
- this.@(field.name) = @(field.name);
+@[ end if]@
+ this.@(member.name) = @(member.name);
return this;
}
-@[ if field.type.is_primitive_type()]@
- public final @(type_name) set@(convert_lower_case_underscore_to_camel_case(field.name))(final @(get_java_type(field.type, use_primitives=True))[] @(field.name)) {
- java.util.List<@(get_java_type(field.type, use_primitives=False))> @(field.name)_tmp = new java.util.ArrayList<@(get_java_type(field.type, use_primitives=False))>();
- for(@(get_java_type(field.type, use_primitives=True)) @(field.name)_value : @(field.name)) {
- @(field.name)_tmp.add(@(field.name)_value);
+@[ if isinstance(member.type.value_type, (BasicType, AbstractGenericString))]@
+ public final @(type_name) set@(convert_lower_case_underscore_to_camel_case(member.name))(final @(get_java_type(member.type, use_primitives=True))[] @(member.name)) {
+ java.util.List<@(get_java_type(member.type, use_primitives=False))> @(member.name)_tmp = new java.util.ArrayList<@(get_java_type(member.type, use_primitives=False))>();
+ for(@(get_java_type(member.type, use_primitives=True)) @(member.name)_value : @(member.name)) {
+ @(member.name)_tmp.add(@(member.name)_value);
}
- return set@(convert_lower_case_underscore_to_camel_case(field.name))(@(field.name)_tmp);
+ return set@(convert_lower_case_underscore_to_camel_case(member.name))(@(member.name)_tmp);
}
-@[ end if]@
+@[ end if]@
- public final java.util.List<@(get_java_type(field.type, use_primitives=False))> get@(convert_lower_case_underscore_to_camel_case(field.name))() {
- return this.@(field.name);
+ public final java.util.List<@(get_java_type(member.type, use_primitives=False))> get@(convert_lower_case_underscore_to_camel_case(member.name))() {
+ return this.@(member.name);
}
+@[ else]@
+@[ if member.has_annotation('default')]@
+ private @(get_java_type(member.type)) @(member.name) = @(value_to_java(member.type, member.get_annotation_value('default')['value']));
@[ else]@
-@[ if field.default_value is not None]@
- private @(get_java_type(field.type)) @(field.name) = @(value_to_java(field.type, field.default_value));
-@[ else]@
-@[ if field.type.type == 'string']@
- private @(get_java_type(field.type)) @(field.name) = "";
-@[ elif field.type.is_primitive_type()]@
- private @(get_java_type(field.type)) @(field.name);
-@[ else]@
- private @(get_java_type(field.type)) @(field.name) = new @(get_java_type(field.type))();
-@[ end if]@
-@[ end if]@
-
- public @(type_name) set@(convert_lower_case_underscore_to_camel_case(field.name))(final @(get_java_type(field.type)) @(field.name)) {
-@[ if field.type.string_upper_bound]@
- if(@(field.name).length() > @(field.type.string_upper_bound)) {
- throw new IllegalArgumentException("String too long, maximum size allowed: @(field.type.string_upper_bound)");
+@[ if isinstance(member.type, AbstractGenericString)]@
+ private @(get_java_type(member.type)) @(member.name) = "";
+@[ elif isinstance(member.type, BasicType)]@
+ private @(get_java_type(member.type)) @(member.name);
+@[ else]@
+ private @(get_java_type(member.type)) @(member.name) = new @(get_java_type(member.type))();
+@[ end if]@
+@[ end if]@
+
+ public @(type_name) set@(convert_lower_case_underscore_to_camel_case(member.name))(final @(get_java_type(member.type)) @(member.name)) {
+@[ if isinstance(member.type, AbstractGenericString) and member.type.has_maximum_size()]@
+ if(@(member.name).length() > @(member.type.maximum_size)) {
+ throw new IllegalArgumentException("String too long, maximum size allowed: @(member.type.maximum_size)");
}
-@[ end if]@
+@[ end if]@
- this.@(field.name) = @(field.name);
+ this.@(member.name) = @(member.name);
return this;
}
- public @(get_java_type(field.type)) get@(convert_lower_case_underscore_to_camel_case(field.name))() {
- return this.@(field.name);
+ public @(get_java_type(member.type)) get@(convert_lower_case_underscore_to_camel_case(member.name))() {
+ return this.@(member.name);
}
-@[ end if]@
+@[ end if]@
@[end for]@
public int hashCode() {
return new HashCodeBuilder(17, 37)
-@[for field in spec.fields]@
- .append(this.@(field.name))
+@[for member in message.structure.members]@
+ .append(this.@(member.name))
@[end for]@
.toHashCode();
}
@@ -140,8 +162,8 @@ public final class @(type_name) implements MessageDefinition {
}
@(type_name) rhs = (@(type_name)) obj;
return new EqualsBuilder()
-@[for field in spec.fields]@
- .append(this.@(field.name), rhs.@(field.name))
+@[for member in message.structure.members]@
+ .append(this.@(member.name), rhs.@(member.name))
@[end for]@
.isEquals();
}
diff --git a/rosidl_generator_java/resource/srv.cpp.em b/rosidl_generator_java/resource/srv.cpp.em
index 71014762..5c2d2d0b 100644
--- a/rosidl_generator_java/resource/srv.cpp.em
+++ b/rosidl_generator_java/resource/srv.cpp.em
@@ -1,29 +1,48 @@
-// generated from rosidl_generator_java/resource/srv.cpp.em
-// generated code does not contain a copyright notice
+@# Included from rosidl_generator_java/resource/idl.cpp.em
+@{
+from rosidl_generator_c import idl_structure_type_to_c_include_prefix
-#include
+service_includes = [
+ 'rosidl_generator_c/service_type_support_struct.h',
+]
+}@
+@[for include in service_includes]@
+@[ if include in include_directives]@
+// already included above
+// @
+@[ else]@
+@{include_directives.add(include)}@
+@[ end if]@
+#include "@(include)"
+@[end for]@
-#include "rosidl_generator_c/service_type_support_struct.h"
-#include "@(spec.pkg_name)/@(subfolder)/@(module_name).h"
+#include "@(idl_structure_type_to_c_include_prefix(service.namespaced_type)).h"
#ifdef __cplusplus
extern "C" {
#endif
+@{
+from rosidl_generator_java import get_jni_mangled_name
+
+service_fqn = service.namespaced_type.namespaced_name()
+underscore_separated_type_name = '_'.join(service_fqn)
+underscore_separated_jni_type_name = get_jni_mangled_name(service_fqn)
+}@
/*
- * Class: @(jni_package_name)_@(subfolder)_@(type_name)
+ * Class: @(underscore_separated_type_name)
* Method: getServiceTypeSupport
* Signature: ()J
*/
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getServiceTypeSupport(JNIEnv *, jclass);
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getServiceTypeSupport(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
-JNIEXPORT jlong JNICALL Java_@(jni_package_name)_@(subfolder)_@(jni_type_name)_getServiceTypeSupport(JNIEnv *, jclass)
+JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getServiceTypeSupport(JNIEnv *, jclass)
{
const rosidl_service_type_support_t * ts = ROSIDL_GET_SRV_TYPE_SUPPORT(
- @(spec.pkg_name), @(spec.srv_name));
+ @(','.join(service_fqn)));
return reinterpret_cast(ts);
}
diff --git a/rosidl_generator_java/resource/srv.java.em b/rosidl_generator_java/resource/srv.java.em
index d7e992f4..9be7a6a7 100644
--- a/rosidl_generator_java/resource/srv.java.em
+++ b/rosidl_generator_java/resource/srv.java.em
@@ -1,10 +1,51 @@
-package @(package_name).@(subfolder);
+@# Generation triggered from rosidl_generator_java/resource/idl.java.em
+// generated from rosidl_generator_java/resource/srv.java.em
+// with input from @(package_name):@(interface_path)
+// generated code does not contain a copyright notice
-import org.ros2.rcljava.common.JNIUtils;
-import org.ros2.rcljava.interfaces.ServiceDefinition;
+package @(package_name + '.' + interface_path.parts[0]);
+@{
+import os
+from rosidl_cmake import expand_template
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+namespaces = service.namespaced_type.namespaces
+type_name = service.namespaced_type.name
+request_type_name = service.request_message.structure.namespaced_type.name
+response_type_name = service.response_message.structure.namespaced_type.name
+
+data = {
+ 'package_name': package_name,
+ 'interface_path': interface_path,
+ 'output_dir': output_dir,
+ 'template_basepath': template_basepath,
+}
+data.update({'message': service.request_message})
+output_file = os.path.join(output_dir, *namespaces[1:], request_type_name + '.java')
+expand_template(
+ 'msg.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+
+data.update({'message': service.response_message})
+output_file = os.path.join(output_dir, *namespaces[1:], response_type_name + '.java')
+expand_template(
+ 'msg.java.em',
+ data,
+ output_file,
+ template_basepath=template_basepath)
+
+service_imports = [
+ 'org.ros2.rcljava.common.JNIUtils',
+ 'org.ros2.rcljava.interfaces.ServiceDefinition',
+ 'org.slf4j.Logger',
+ 'org.slf4j.LoggerFactory',
+]
+}@
+
+@[for service_import in service_imports]@
+import @(service_import);
+@[end for]@
public class @(type_name) implements ServiceDefinition {
diff --git a/rosidl_generator_java/rosidl_generator_java/__init__.py b/rosidl_generator_java/rosidl_generator_java/__init__.py
index 8d9163f3..7941ab69 100644
--- a/rosidl_generator_java/rosidl_generator_java/__init__.py
+++ b/rosidl_generator_java/rosidl_generator_java/__init__.py
@@ -1,4 +1,5 @@
# Copyright 2016-2017 Esteve Fernandez
+# Copyright 2019 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,15 +13,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from ast import literal_eval
from collections import defaultdict
-import os
+import pathlib
-from rosidl_cmake import convert_camel_case_to_lower_case_underscore
-from rosidl_cmake import expand_template
-from rosidl_cmake import get_newest_modification_time
+from rosidl_cmake import generate_files
from rosidl_cmake import read_generator_arguments
-from rosidl_parser import parse_message_file
-from rosidl_parser import parse_service_file
+from rosidl_parser.definition import AbstractGenericString
+from rosidl_parser.definition import AbstractNestedType
+from rosidl_parser.definition import BASIC_TYPES
+from rosidl_parser.definition import BasicType
+from rosidl_parser.definition import NamespacedType
# Taken from http://stackoverflow.com/a/6425628
@@ -28,201 +31,176 @@ def convert_lower_case_underscore_to_camel_case(word):
return ''.join(x.capitalize() or '_' for x in word.split('_'))
-def generate_java(generator_arguments_file, typesupport_impl, typesupport_impls):
+def generate_java(generator_arguments_file, typesupport_impls):
args = read_generator_arguments(generator_arguments_file)
- typesupport_impls = typesupport_impls.split(';')
-
- template_dir = args['template_dir']
- type_support_impl_by_filename = {
- '%s.ep.{0}.cpp'.format(impl): impl
- for impl in typesupport_impls
- }
- mapping_msgs = {
- os.path.join(template_dir, 'msg.java.em'): ['%s.java'],
- os.path.join(template_dir, 'msg.cpp.em'): type_support_impl_by_filename.keys(),
+ additional_context = {
+ 'output_dir': pathlib.Path(args['output_dir']),
+ 'template_basepath': pathlib.Path(args['template_dir']),
}
-
- mapping_srvs = {
- os.path.join(template_dir, 'srv.java.em'): ['%s.java'],
- os.path.join(template_dir, 'srv.cpp.em'): type_support_impl_by_filename.keys(),
+ mapping = {
+ 'idl.java.em': '_%s.java',
}
-
- for template_file in mapping_msgs.keys():
- assert os.path.exists(template_file), \
- 'Messages template file %s not found' % template_file
- for template_file in mapping_srvs.keys():
- assert os.path.exists(template_file), \
- 'Services template file %s not found' % template_file
-
- functions = {'get_java_type': get_java_type, }
- latest_target_timestamp = get_newest_modification_time(args['target_dependencies'])
-
- modules = defaultdict(list)
- for ros_interface_file in args['ros_interface_files']:
- extension = os.path.splitext(ros_interface_file)[1]
- subfolder = os.path.basename(os.path.dirname(ros_interface_file))
- if extension == '.msg':
- spec = parse_message_file(args['package_name'], ros_interface_file)
- mapping = mapping_msgs
- type_name = spec.base_type.type
- elif extension == '.srv':
- spec = parse_service_file(args['package_name'], ros_interface_file)
- mapping = mapping_srvs
- type_name = spec.srv_name
- else:
- continue
-
- module_name = convert_camel_case_to_lower_case_underscore(type_name)
- modules[subfolder].append((module_name, type_name))
- package_name = args['package_name']
- jni_package_name = package_name.replace('_', '_1')
- jni_type_name = type_name.replace('_', '_1')
- for template_file, generated_filenames in mapping.items():
- for generated_filename in generated_filenames:
- data = {
- 'constant_value_to_java': constant_value_to_java,
- 'value_to_java': value_to_java,
- 'convert_camel_case_to_lower_case_underscore':
- convert_camel_case_to_lower_case_underscore,
- 'convert_lower_case_underscore_to_camel_case':
- convert_lower_case_underscore_to_camel_case,
- 'get_builtin_java_type': get_builtin_java_type,
- 'module_name': module_name,
- 'package_name': package_name,
- 'jni_package_name': jni_package_name,
- 'jni_type_name': jni_type_name,
- 'spec': spec,
- 'subfolder': subfolder,
- 'typesupport_impl': type_support_impl_by_filename.get(generated_filename, ''),
- 'typesupport_impls': typesupport_impls,
- 'type_name': type_name,
- }
- data.update(functions)
- generated_file = os.path.join(args['output_dir'], subfolder,
- generated_filename % type_name)
- expand_template(
- template_file, data, generated_file, minimum_timestamp=latest_target_timestamp)
-
+ generate_files(
+ generator_arguments_file, mapping, additional_context=additional_context, keep_case=True)
+
+ for impl in typesupport_impls:
+ mapping = {
+ 'idl.cpp.em': '%s.ep.{0}.cpp'.format(impl),
+ }
+ generate_files(
+ generator_arguments_file,
+ mapping,
+ additional_context=additional_context,
+ keep_case=True)
return 0
def escape_string(s):
s = s.replace('\\', '\\\\')
- s = s.replace("'", "\\'")
+ s = s.replace('"', '\\"')
return s
+def escape_wstring(s):
+ return escape_string(s)
+
+
def value_to_java(type_, value):
- assert type_.is_primitive_type()
- assert value is not None
+ assert not isinstance(type_, NamespacedType), \
+ "Could not convert non-basic type '{}' to Java".format(type_)
+ assert value is not None, "Value for for type '{}' must not be None".format(type_)
- if not type_.is_array:
+ if not isinstance(type_, AbstractNestedType):
return primitive_value_to_java(type_, value)
java_values = []
- for single_value in value:
- java_value = primitive_value_to_java(type_, single_value)
+ for single_value in literal_eval(value):
+ java_value = primitive_value_to_java(type_.value_type, single_value)
java_values.append(java_value)
return '{%s}' % ', '.join(java_values)
def primitive_value_to_java(type_, value):
- assert type_.is_primitive_type()
- assert value is not None
+ assert isinstance(type_, (BasicType, AbstractGenericString)), \
+ "Could not convert non-basic type '{}' to Java".format(type_)
+ assert value is not None, "Value for for type '{}' must not be None".format(type_)
- if type_.type == 'bool':
- return 'true' if value else 'false'
-
- if type_.type in [
- 'byte',
- 'char',
- 'int8',
- 'uint8',
- 'int16',
- 'uint16',
- 'int32',
- 'uint32',
- 'int64',
- 'uint64',
- 'float64',
- ]:
- return str(value)
-
- if type_.type == 'float32':
- return '%sf' % value
-
- if type_.type == 'string':
+ if isinstance(type_, AbstractGenericString):
return '"%s"' % escape_string(value)
- assert False, "unknown primitive type '%s'" % type_
-
-
-def constant_value_to_java(type_, value):
- assert value is not None
-
- if type_ == 'bool':
+ if type_.typename == 'boolean':
return 'true' if value else 'false'
- if type_ in [
- 'byte',
- 'char',
- 'int8',
- 'uint8',
- 'int16',
- 'uint16',
- 'int32',
- 'uint32',
- 'int64',
- 'uint64',
- 'float64',
- ]:
- return str(value)
-
- if type_ == 'float32':
+ if type_.typename == 'float':
return '%sf' % value
- if type_ == 'string':
- return '"%s"' % escape_string(value)
-
- assert False, "unknown constant type '%s'" % type_
-
+ if type_.typename in ('octet', 'uint8', 'int8'):
+ # literal is treated as an integer so we must cast
+ return '(byte) %s' % value
-def get_builtin_java_type(type_, use_primitives=True):
- if type_ == 'bool':
- return 'boolean' if use_primitives else 'java.lang.Boolean'
+ if type_.typename in ('uint16', 'int16'):
+ # literal is treated as an integer so we must cast
+ return '(short) %s' % value
- if type_ == 'byte':
- return 'byte' if use_primitives else 'java.lang.Byte'
+ # Java doesn't support unsigned literals (values over 2^31-1)
+ # Instead we should convert to the corresponding negative number
+ if type_.typename == 'uint32' and int(value) > 2**31-1:
+ negative_value = int(value) - 2**32
+ return str(negative_value)
- if type_ == 'char':
- return 'char' if use_primitives else 'java.lang.Character'
+ if type_.typename in ('uint64', 'int64'):
+ # Java doesn't support unsigned literals (values over 2^63-1)
+ # Instead we should convert to the corresponding negative number
+ if type_.typename == 'uint64' and int(value) > 2**63-1:
+ value = int(value) - 2**64
+ return '%sL' % value
- if type_ == 'float32':
- return 'float' if use_primitives else 'java.lang.Float'
-
- if type_ == 'float64':
- return 'double' if use_primitives else 'java.lang.Double'
-
- if type_ in ['int8', 'uint8']:
- return 'byte' if use_primitives else 'java.lang.Byte'
-
- if type_ in ['int16', 'uint16']:
- return 'short' if use_primitives else 'java.lang.Short'
-
- if type_ in ['int32', 'uint32']:
- return 'int' if use_primitives else 'java.lang.Integer'
-
- if type_ in ['int64', 'uint64']:
- return 'long' if use_primitives else 'java.lang.Long'
+ if type_.typename in BASIC_TYPES:
+ return str(value)
- if type_ == 'string':
+ assert False, "unknown primitive type '%s'" % type_.typename
+
+
+# Map IDL types to Java primitive types
+# Maps to a tuple: (primitive, class type)
+IDL_TYPE_TO_JAVA_PRIMITIVE = {
+ 'boolean': ('boolean', 'java.lang.Boolean'),
+ 'char': ('char', 'java.lang.Char'),
+ 'octet': ('byte', 'java.lang.Byte'),
+ 'float': ('float', 'java.lang.Float'),
+ 'double': ('double', 'java.lang.Double'),
+ 'long double': ('double', 'java.lang.Double'),
+ 'uint8': ('byte', 'java.lang.Byte'),
+ 'int8': ('byte', 'java.lang.Byte'),
+ 'uint16': ('short', 'java.lang.Short'),
+ 'int16': ('short', 'java.lang.Short'),
+ 'uint32': ('int', 'java.lang.Integer'),
+ 'int32': ('int', 'java.lang.Integer'),
+ 'uint64': ('long', 'java.lang.Long'),
+ 'int64': ('long', 'java.lang.Long'),
+}
+
+
+def get_java_type(type_, use_primitives=True):
+ if isinstance(type_, AbstractNestedType):
+ type_ = type_.value_type
+ if isinstance(type_, NamespacedType):
+ return '.'.join(type_.namespaced_name())
+ if isinstance(type_, BasicType):
+ return IDL_TYPE_TO_JAVA_PRIMITIVE[type_.typename][0 if use_primitives else 1]
+ if isinstance(type_, AbstractGenericString):
return 'java.lang.String'
assert False, "unknown type '%s'" % type_
-def get_java_type(type_, use_primitives=True, subfolder='msg'):
- if not type_.is_primitive_type():
- return '%s.%s.%s' % (type_.pkg_name, subfolder, type_.type)
-
- return get_builtin_java_type(type_.type, use_primitives=use_primitives)
+def get_normalized_type(type_):
+ return get_java_type(type_, use_primitives=False).replace('.', '__')
+
+
+def get_jni_type(type_):
+ return get_java_type(type_, use_primitives=False).replace('.', '/')
+
+
+# JNI performance tips taken from http://planet.jboss.org/post/jni_performance_the_saga_continues
+constructor_signatures = defaultdict(lambda: '()V')
+constructor_signatures['java/lang/Boolean'] = '(Z)V'
+constructor_signatures['java/lang/Byte'] = '(B)V'
+constructor_signatures['java/lang/Character'] = '(C)V'
+constructor_signatures['java/lang/Double'] = '(D)V'
+constructor_signatures['java/lang/Float'] = '(F)V'
+constructor_signatures['java/lang/Integer'] = '(I)V'
+constructor_signatures['java/lang/Long'] = '(J)V'
+constructor_signatures['java/lang/Short'] = '(S)V'
+constructor_signatures['java/util/List'] = None
+
+value_methods = {}
+value_methods['java/lang/Boolean'] = ('booleanValue', '()Z')
+value_methods['java/lang/Byte'] = ('byteValue', '()B')
+value_methods['java/lang/Character'] = ('charValue', '()C')
+value_methods['java/lang/Double'] = ('doubleValue', '()D')
+value_methods['java/lang/Float'] = ('floatValue', '()F')
+value_methods['java/lang/Integer'] = ('intValue', '()I')
+value_methods['java/lang/Long'] = ('longValue', '()J')
+value_methods['java/lang/Short'] = ('shortValue', '()S')
+
+jni_signatures = {}
+jni_signatures['java/lang/Boolean'] = 'Z'
+jni_signatures['java/lang/Byte'] = 'B'
+jni_signatures['java/lang/Character'] = 'C'
+jni_signatures['java/lang/Double'] = 'D'
+jni_signatures['java/lang/Float'] = 'F'
+jni_signatures['java/lang/Integer'] = 'I'
+jni_signatures['java/lang/Long'] = 'J'
+jni_signatures['java/lang/Short'] = 'S'
+
+
+def get_jni_signature(type_):
+ global jni_signatures
+ return jni_signatures.get(get_jni_type(type_))
+
+
+def get_jni_mangled_name(fully_qualified_name):
+ # JNI name mangling:
+ # https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names
+ return fully_qualified_name[0].replace('_', '_1') + '_' + '_'.join(fully_qualified_name[1:])
diff --git a/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java b/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java
index 03a5011d..d1b0fada 100644
--- a/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java
+++ b/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java
@@ -68,12 +68,12 @@ public final void testByte() {
@Test
public final void testChar() {
- char expected1 = 'a';
+ byte expected1 = 'a';
rosidl_generator_java.msg.Char charOne = new rosidl_generator_java.msg.Char();
charOne.setEmptyChar(expected1);
assertEquals(expected1, charOne.getEmptyChar());
- char expected2 = 'b';
+ byte expected2 = 'b';
rosidl_generator_java.msg.Char charTwo = new rosidl_generator_java.msg.Char();
charTwo.setEmptyChar(expected2);
assertEquals(expected2, charTwo.getEmptyChar());