Skip to content

Commit 9787870

Browse files
ivanpaunojacobperron
authored andcommitted
Add getClientNamesAndTypes by Node (osrf#37)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
1 parent 43e9d32 commit 9787870

File tree

5 files changed

+159
-0
lines changed

5 files changed

+159
-0
lines changed

rcljava/include/org_ros2_rcljava_node_NodeImpl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ JNIEXPORT void
164164
JNICALL Java_org_ros2_rcljava_node_NodeImpl_nativeGetServiceNamesAndTypesByNode(
165165
JNIEnv *, jclass, jlong, jstring, jstring, jobject);
166166

167+
/*
168+
* Class: org_ros2_rcljava_node_NodeImpl
169+
* Method: nativeGetClientNamesAndTypesByNode
170+
* Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/util/Collection;)V
171+
*/
172+
JNIEXPORT void
173+
JNICALL Java_org_ros2_rcljava_node_NodeImpl_nativeGetClientNamesAndTypesByNode(
174+
JNIEnv *, jclass, jlong, jstring, jstring, jobject);
175+
167176
#ifdef __cplusplus
168177
}
169178
#endif

rcljava/src/main/cpp/org_ros2_rcljava_node_NodeImpl.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,3 +599,39 @@ JNIEXPORT void JNICALL Java_org_ros2_rcljava_node_NodeImpl_nativeGetServiceNames
599599
RCLJAVA_COMMON_THROW_FROM_RCL(env, ret, "failed to get service names and types");
600600
fill_jnames_and_types(env, service_names_and_types, jnames_and_types);
601601
}
602+
603+
JNIEXPORT void JNICALL Java_org_ros2_rcljava_node_NodeImpl_nativeGetClientNamesAndTypesByNode(
604+
JNIEnv * env, jclass, jlong handle, jstring jname, jstring jnamespace, jobject jnames_and_types)
605+
{
606+
rcl_node_t * node = reinterpret_cast<rcl_node_t *>(handle);
607+
if (!node) {
608+
rcljava_throw_exception(env, "java/lang/IllegalArgumentException", "node handle is NULL");
609+
return;
610+
}
611+
612+
const char * name = env->GetStringUTFChars(jname, NULL);
613+
auto release_jname = rcpputils::make_scope_exit(
614+
[jname, name, env]() {env->ReleaseStringUTFChars(jname, name);});
615+
const char * namespace_ = env->GetStringUTFChars(jnamespace, NULL);
616+
auto release_jnamespace = rcpputils::make_scope_exit(
617+
[jnamespace, namespace_, env]() {env->ReleaseStringUTFChars(jnamespace, namespace_);});
618+
rcl_allocator_t allocator = rcl_get_default_allocator();
619+
rcl_names_and_types_t client_names_and_types = rcl_get_zero_initialized_names_and_types();
620+
auto fini_names_and_types = rcpputils::make_scope_exit(
621+
[pnames_and_types = &client_names_and_types, env]() {
622+
rcl_ret_t ret = rcl_names_and_types_fini(pnames_and_types);
623+
if (!env->ExceptionCheck() && RCL_RET_OK != ret) {
624+
rcljava_throw_rclexception(
625+
env, ret, "failed to fini client names and types structure");
626+
}
627+
});
628+
629+
rcl_ret_t ret = rcl_get_client_names_and_types_by_node(
630+
node,
631+
&allocator,
632+
name,
633+
namespace_,
634+
&client_names_and_types);
635+
RCLJAVA_COMMON_THROW_FROM_RCL(env, ret, "failed to get client names and types");
636+
fill_jnames_and_types(env, client_names_and_types, jnames_and_types);
637+
}

rcljava/src/main/java/org/ros2/rcljava/node/Node.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,4 +661,16 @@ Collection<NameAndTypes> getSubscriptionNamesAndTypesByNode(
661661
*/
662662
Collection<NameAndTypes> getServiceNamesAndTypesByNode(
663663
String nodeName, String nodeNamespace);
664+
665+
/**
666+
* Return the client names and types that were created from the node specified by the
667+
* given node name and namespace.
668+
* See @{link graph#NameAndTypes} for more information about the returned value.
669+
*
670+
* @param nodeName name of the node we want to know its clients.
671+
* @param nodeNamespace namespace of the node we want to know its clients.
672+
* @return the detected client names and types.
673+
*/
674+
Collection<NameAndTypes> getClientNamesAndTypesByNode(
675+
String nodeName, String nodeNamespace);
664676
}

rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,4 +864,15 @@ public final Collection<NameAndTypes> getServiceNamesAndTypesByNode(
864864

865865
private static native final Collection<NameAndTypes> nativeGetServiceNamesAndTypesByNode(
866866
long handle, String nodeName, String nodeNamespace, Collection<NameAndTypes> namesAndTypes);
867+
868+
public final Collection<NameAndTypes> getClientNamesAndTypesByNode(
869+
String nodeName, String nodeNamespace)
870+
{
871+
Collection<NameAndTypes> namesAndTypes = new ArrayList();
872+
nativeGetClientNamesAndTypesByNode(this.handle, nodeName, nodeNamespace, namesAndTypes);
873+
return namesAndTypes;
874+
}
875+
876+
private static native final Collection<NameAndTypes> nativeGetClientNamesAndTypesByNode(
877+
long handle, String nodeName, String nodeNamespace, Collection<NameAndTypes> namesAndTypes);
867878
}

rcljava/src/test/java/org/ros2/rcljava/node/NodeTest.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,4 +1484,95 @@ public void accept(final Collection<NameAndTypes> local, Collection<NameAndTypes
14841484
client.dispose();
14851485
remoteNode.dispose();
14861486
}
1487+
1488+
@Test
1489+
public final void testGetClientNamesAndTypesByNode() throws Exception {
1490+
final Node remoteNode = RCLJava.createNode("test_get_client_names_and_types_remote_node");
1491+
Client<rcljava.srv.AddTwoInts> client1 = node.<rcljava.srv.AddTwoInts>createClient(
1492+
rcljava.srv.AddTwoInts.class, "test_get_client_names_and_types_one");
1493+
Client<rcljava.srv.AddTwoInts> client2 = node.<rcljava.srv.AddTwoInts>createClient(
1494+
rcljava.srv.AddTwoInts.class, "test_get_client_names_and_types_two");
1495+
Client<rcljava.srv.AddTwoInts> client3 = remoteNode.<rcljava.srv.AddTwoInts>createClient(
1496+
rcljava.srv.AddTwoInts.class, "test_get_client_names_and_types_two");
1497+
Client<rcljava.srv.AddTwoInts> client4 = remoteNode.<rcljava.srv.AddTwoInts>createClient(
1498+
rcljava.srv.AddTwoInts.class, "test_get_client_names_and_types_three");
1499+
Service<rcljava.srv.AddTwoInts> service = node.<rcljava.srv.AddTwoInts>createService(
1500+
rcljava.srv.AddTwoInts.class, "test_get_client_names_and_types_this_should_not_appear",
1501+
new TriConsumer<
1502+
RMWRequestId, rcljava.srv.AddTwoInts_Request, rcljava.srv.AddTwoInts_Response>()
1503+
{
1504+
public final void accept(
1505+
final RMWRequestId header,
1506+
final rcljava.srv.AddTwoInts_Request request,
1507+
final rcljava.srv.AddTwoInts_Response response)
1508+
{}
1509+
});
1510+
1511+
BiConsumer<Collection<NameAndTypes>, Collection<NameAndTypes>> validateNameAndTypes =
1512+
new BiConsumer<Collection<NameAndTypes>, Collection<NameAndTypes>>() {
1513+
public void accept(final Collection<NameAndTypes> local, Collection<NameAndTypes> remote) {
1514+
// TODO(ivanpauno): Using assertj may help a lot here https://assertj.github.io/doc/.
1515+
assertEquals(local.size(), 2);
1516+
assertTrue(
1517+
"client 'test_get_client_names_and_types_one' was not discovered for local node",
1518+
local.contains(
1519+
new NameAndTypes(
1520+
"/test_get_client_names_and_types_one",
1521+
new ArrayList(Arrays.asList("rcljava/srv/AddTwoInts")))));
1522+
assertTrue(
1523+
"client 'test_get_client_names_and_types_two' was not discovered for local node",
1524+
local.contains(
1525+
new NameAndTypes(
1526+
"/test_get_client_names_and_types_two",
1527+
new ArrayList(Arrays.asList("rcljava/srv/AddTwoInts")))));
1528+
1529+
assertEquals(remote.size(), 2);
1530+
assertTrue(
1531+
"client 'test_get_client_names_and_types_two' was not discovered for remote node",
1532+
remote.contains(
1533+
new NameAndTypes(
1534+
"/test_get_client_names_and_types_two",
1535+
new ArrayList(Arrays.asList("rcljava/srv/AddTwoInts")))));
1536+
assertTrue(
1537+
"client 'test_get_client_names_and_types_three' was not discovered for remote node",
1538+
remote.contains(
1539+
new NameAndTypes(
1540+
"/test_get_client_names_and_types_three",
1541+
new ArrayList(Arrays.asList("rcljava/srv/AddTwoInts")))));
1542+
}
1543+
};
1544+
1545+
long start = System.currentTimeMillis();
1546+
boolean ok = false;
1547+
Collection<NameAndTypes> local = null;
1548+
Collection<NameAndTypes> remote = null;
1549+
do {
1550+
local = this.node.getClientNamesAndTypesByNode("test_node", "/");
1551+
remote = this.node.getClientNamesAndTypesByNode(
1552+
"test_get_client_names_and_types_remote_node", "/");
1553+
try {
1554+
validateNameAndTypes.accept(local, remote);
1555+
ok = true;
1556+
} catch (AssertionError err) {
1557+
// ignore here, it's going to be validated again at the end.
1558+
}
1559+
// TODO(ivanpauno): We could wait for the graph guard condition to be triggered if that
1560+
// would be available.
1561+
try {
1562+
TimeUnit.MILLISECONDS.sleep(100);
1563+
} catch (InterruptedException err) {
1564+
// ignore
1565+
}
1566+
} while (!ok && System.currentTimeMillis() < start + 1000);
1567+
assertNotNull(local);
1568+
assertNotNull(remote);
1569+
validateNameAndTypes.accept(local, remote);
1570+
1571+
client1.dispose();
1572+
client2.dispose();
1573+
client3.dispose();
1574+
client4.dispose();
1575+
service.dispose();
1576+
remoteNode.dispose();
1577+
}
14871578
}

0 commit comments

Comments
 (0)