VPP-413 DTOs generated by JVpp improvements:

- hashCode & equals
- toString

Change-Id: I5f8bc8868c216862a307dcc8f6b423f0ce29e7b5
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackApiTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackApiTest.java
index cfa2456..61c92b1 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackApiTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackApiTest.java
@@ -37,30 +37,29 @@
 
         @Override
         public void onGetNodeIndexReply(final GetNodeIndexReply msg) {
-            System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n",
-                msg.context, msg.nodeIndex);
+            System.out.printf("Received GetNodeIndexReply: %s\n", msg);
         }
 
         @Override
         public void onShowVersionReply(final ShowVersionReply msg) {
             System.out.printf("Received ShowVersionReply: context=%d, program=%s, version=%s, "
-                    + "buildDate=%s, buildDirectory=%s\n",
-                msg.context, new String(msg.program), new String(msg.version),
-                new String(msg.buildDate), new String(msg.buildDirectory));
+                            + "buildDate=%s, buildDirectory=%s\n",
+                    msg.context, new String(msg.program), new String(msg.version),
+                    new String(msg.buildDate), new String(msg.buildDirectory));
         }
 
         @Override
         public void onSwInterfaceDetails(final SwInterfaceDetails msg) {
             System.out.printf("Received SwInterfaceDetails: interfaceName=%s, l2AddressLength=%d, adminUpDown=%d, "
-                    + "linkUpDown=%d, linkSpeed=%d, linkMtu=%d\n",
-                new String(msg.interfaceName), msg.l2AddressLength, msg.adminUpDown,
-                msg.linkUpDown, msg.linkSpeed, (int) msg.linkMtu);
+                            + "linkUpDown=%d, linkSpeed=%d, linkMtu=%d\n",
+                    new String(msg.interfaceName), msg.l2AddressLength, msg.adminUpDown,
+                    msg.linkUpDown, msg.linkSpeed, (int) msg.linkMtu);
         }
 
         @Override
         public void onError(VppCallbackException ex) {
             System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n", ex.getMethodName(),
-                ex.getCtxId(), ex.getErrorCode());
+                    ex.getCtxId(), ex.getErrorCode());
         }
     }
 
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeNotificationTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeNotificationTest.java
index 542a561..a4b528a 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeNotificationTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeNotificationTest.java
@@ -37,23 +37,23 @@
         System.out.println("Successfully connected to VPP");
 
         final AutoCloseable notificationListenerReg =
-            jvppCallbackFacade.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback(
-                NotificationUtils::printNotification
-            );
+                jvppCallbackFacade.getNotificationRegistry().registerSwInterfaceSetFlagsNotificationCallback(
+                        NotificationUtils::printNotification
+                );
 
         jvppCallbackFacade.wantInterfaceEvents(NotificationUtils.getEnableInterfaceNotificationsReq(),
-            new WantInterfaceEventsCallback() {
-                @Override
-                public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) {
-                    System.out.println("Interface events started");
-                }
+                new WantInterfaceEventsCallback() {
+                    @Override
+                    public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) {
+                        System.out.println("Interface events started");
+                    }
 
-                @Override
-                public void onError(final VppCallbackException ex) {
-                    System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n",
-                        ex.getMethodName(), ex.getCtxId(), ex.getErrorCode());
-                }
-            });
+                    @Override
+                    public void onError(final VppCallbackException ex) {
+                        System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n",
+                                ex.getMethodName(), ex.getCtxId(), ex.getErrorCode());
+                    }
+                });
 
         System.out.println("Changing interface configuration");
         NotificationUtils.getChangeInterfaceState().send(jvpp);
@@ -61,18 +61,18 @@
         Thread.sleep(1000);
 
         jvppCallbackFacade.wantInterfaceEvents(NotificationUtils.getDisableInterfaceNotificationsReq(),
-            new WantInterfaceEventsCallback() {
-                @Override
-                public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) {
-                    System.out.println("Interface events stopped");
-                }
+                new WantInterfaceEventsCallback() {
+                    @Override
+                    public void onWantInterfaceEventsReply(final WantInterfaceEventsReply reply) {
+                        System.out.println("Interface events stopped");
+                    }
 
-                @Override
-                public void onError(final VppCallbackException ex) {
-                    System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n",
-                        ex.getMethodName(), ex.getCtxId(), ex.getErrorCode());
-                }
-            });
+                    @Override
+                    public void onError(final VppCallbackException ex) {
+                        System.out.printf("Received onError exception: call=%s, context=%d, retval=%d\n",
+                                ex.getMethodName(), ex.getCtxId(), ex.getErrorCode());
+                    }
+                });
 
         notificationListenerReg.close();
 
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeTest.java
index 7499502..63a399d 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackJVppFacadeTest.java
@@ -38,14 +38,14 @@
         @Override
         public void onShowVersionReply(final ShowVersionReply msg) {
             System.out.printf("ShowVersionCallback1 received ShowVersionReply: context=%d, program=%s,"
-                    + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program),
-                new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory));
+                            + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program),
+                    new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory));
         }
 
         @Override
         public void onError(VppCallbackException ex) {
             System.out.printf("Received onError exception in showVersionCallback1: call=%s, reply=%d, context=%d\n",
-                ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
+                    ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
         }
     };
 
@@ -53,14 +53,14 @@
         @Override
         public void onShowVersionReply(final ShowVersionReply msg) {
             System.out.printf("ShowVersionCallback2 received ShowVersionReply: context=%d, program=%s,"
-                    + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program),
-                new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory));
+                            + "version=%s, buildDate=%s, buildDirectory=%s\n", msg.context, new String(msg.program),
+                    new String(msg.version), new String(msg.buildDate), new String(msg.buildDirectory));
         }
 
         @Override
         public void onError(VppCallbackException ex) {
             System.out.printf("Received onError exception in showVersionCallback2: call=%s, reply=%d, context=%d\n",
-                ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
+                    ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
         }
 
     };
@@ -68,14 +68,13 @@
     private static GetNodeIndexCallback getNodeIndexCallback = new GetNodeIndexCallback() {
         @Override
         public void onGetNodeIndexReply(final GetNodeIndexReply msg) {
-            System.out.printf("Received GetNodeIndexReply: context=%d, nodeIndex=%d\n",
-                msg.context, msg.nodeIndex);
+            System.out.printf("Received GetNodeIndexReply: %s\n", msg);
         }
 
         @Override
         public void onError(VppCallbackException ex) {
             System.out.printf("Received onError exception in getNodeIndexCallback: call=%s, reply=%d, context=%d\n",
-                ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
+                    ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
         }
     };
 
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackNotificationApiTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackNotificationApiTest.java
index a11cce6..bb99fef 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackNotificationApiTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CallbackNotificationApiTest.java
@@ -36,11 +36,11 @@
 public class CallbackNotificationApiTest {
 
     private static class TestCallback implements SwInterfaceSetFlagsNotificationCallback,
-        WantInterfaceEventsCallback, SwInterfaceSetFlagsCallback {
+            WantInterfaceEventsCallback, SwInterfaceSetFlagsCallback {
 
         @Override
         public void onSwInterfaceSetFlagsNotification(
-            final SwInterfaceSetFlagsNotification msg) {
+                final SwInterfaceSetFlagsNotification msg) {
             printNotification(msg);
         }
 
@@ -57,7 +57,7 @@
         @Override
         public void onError(VppCallbackException ex) {
             System.out.printf("Received onError exception in getNodeIndexCallback: call=%s, reply=%d, context=%d\n",
-                ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
+                    ex.getMethodName(), ex.getErrorCode(), ex.getCtxId());
 
         }
     }
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/ControlPingTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/ControlPingTest.java
index 12ded2e..b411999 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/ControlPingTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/ControlPingTest.java
@@ -35,14 +35,13 @@
         registry.register(jvpp, new ControlPingCallback() {
             @Override
             public void onControlPingReply(final ControlPingReply reply) {
-                System.out.printf("Received ControlPingReply: context=%d, clientIndex=%d vpePid=%d\n",
-                    reply.context, reply.clientIndex, reply.vpePid);
+                System.out.printf("Received ControlPingReply: %s\n", reply);
             }
 
             @Override
             public void onError(VppCallbackException ex) {
                 System.out.printf("Received onError exception: call=%s, reply=%d, context=%d ", ex.getMethodName(),
-                    ex.getErrorCode(), ex.getCtxId());
+                        ex.getErrorCode(), ex.getCtxId());
             }
 
         });
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CreateSubInterfaceTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CreateSubInterfaceTest.java
index 9719a8c..a22aec6 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CreateSubInterfaceTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/CreateSubInterfaceTest.java
@@ -54,8 +54,8 @@
     private static void requireSingleIface(final SwInterfaceDetailsReplyDump response, final String ifaceName) {
         if (response.swInterfaceDetails.size() != 1) {
             throw new IllegalStateException(
-                String.format("Expected one interface matching filter %s but was %d", ifaceName,
-                    response.swInterfaceDetails.size()));
+                    String.format("Expected one interface matching filter %s but was %d", ifaceName,
+                            response.swInterfaceDetails.size()));
         }
     }
 
@@ -77,7 +77,7 @@
     }
 
     private static void print(CreateSubifReply reply) {
-        System.out.printf("CreateSubifReply: context=%d, swIfIndex=%d\n", reply.context, reply.swIfIndex);
+        System.out.printf("CreateSubifReply: %s\n", reply);
     }
 
     private static void testCreateSubInterface() throws Exception {
@@ -92,7 +92,7 @@
         final String ifaceName = "GigabitEthernet0/8/0";
 
         final SwInterfaceDetailsReplyDump swInterfaceDetails =
-            jvppFacade.swInterfaceDump(createSwInterfaceDumpRequest(ifaceName)).toCompletableFuture().get();
+                jvppFacade.swInterfaceDump(createSwInterfaceDumpRequest(ifaceName)).toCompletableFuture().get();
 
         requireNonNull(swInterfaceDetails, "swInterfaceDump returned null");
         requireNonNull(swInterfaceDetails.swInterfaceDetails, "swInterfaceDetails is null");
@@ -102,12 +102,12 @@
         final int subId = 1;
 
         final CreateSubifReply createSubifReply =
-            jvppFacade.createSubif(createSubifRequest(swIfIndex, subId)).toCompletableFuture().get();
+                jvppFacade.createSubif(createSubifRequest(swIfIndex, subId)).toCompletableFuture().get();
         print(createSubifReply);
 
         final String subIfaceName = "GigabitEthernet0/8/0." + subId;
         final SwInterfaceDetailsReplyDump subIface =
-            jvppFacade.swInterfaceDump(createSwInterfaceDumpRequest(subIfaceName)).toCompletableFuture().get();
+                jvppFacade.swInterfaceDump(createSwInterfaceDumpRequest(subIfaceName)).toCompletableFuture().get();
         requireNonNull(swInterfaceDetails, "swInterfaceDump returned null");
         requireNonNull(subIface.swInterfaceDetails, "swInterfaceDump returned null");
         requireSingleIface(swInterfaceDetails, ifaceName);
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/FutureApiNotificationTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/FutureApiNotificationTest.java
index 2decf6e..20f8ae4 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/FutureApiNotificationTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/FutureApiNotificationTest.java
@@ -38,8 +38,8 @@
         System.out.println("Successfully connected to VPP");
 
         final AutoCloseable notificationListenerReg =
-            jvppFacade.getNotificationRegistry()
-                .registerSwInterfaceSetFlagsNotificationCallback(NotificationUtils::printNotification);
+                jvppFacade.getNotificationRegistry()
+                        .registerSwInterfaceSetFlagsNotificationCallback(NotificationUtils::printNotification);
 
         jvppFacade.wantInterfaceEvents(getEnableInterfaceNotificationsReq()).toCompletableFuture().get();
         System.out.println("Interface events started");
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/L2AclTest.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/L2AclTest.java
index fc353f1..33716c3 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/L2AclTest.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/L2AclTest.java
@@ -16,7 +16,6 @@
 
 package org.openvpp.jvpp.core.test;
 
-import java.util.Arrays;
 import javax.xml.bind.DatatypeConverter;
 import org.openvpp.jvpp.JVpp;
 import org.openvpp.jvpp.JVppRegistry;
@@ -26,7 +25,6 @@
 import org.openvpp.jvpp.core.dto.ClassifyAddDelSessionReply;
 import org.openvpp.jvpp.core.dto.ClassifyAddDelTable;
 import org.openvpp.jvpp.core.dto.ClassifyAddDelTableReply;
-import org.openvpp.jvpp.core.dto.ClassifySessionDetails;
 import org.openvpp.jvpp.core.dto.ClassifySessionDetailsReplyDump;
 import org.openvpp.jvpp.core.dto.ClassifySessionDump;
 import org.openvpp.jvpp.core.dto.ClassifyTableByInterface;
@@ -65,8 +63,8 @@
         request.skipNVectors = 0;
         request.matchNVectors = 1;
         request.mask =
-            new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
-                (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00};
+                new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+                        (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00};
         return request;
     }
 
@@ -85,8 +83,8 @@
         request.advance = 0; // default
         // match 01:02:03:04:05:06 mac address
         request.match =
-            new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
-                (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
+                new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+                        (byte) 0x05, (byte) 0x06, 0x00, 0x00, 0x00, 0x00};
         return request;
     }
 
@@ -113,61 +111,38 @@
     }
 
     private static void print(ClassifyAddDelTableReply reply) {
-        System.out.printf("ClassifyAddDelTableReply: context=%d, "
-                + "newTableIndex=%d, skipNVectors=%d, matchNVectors=%d\n",
-            reply.context, reply.newTableIndex, reply.skipNVectors, reply.matchNVectors);
+        System.out.printf("ClassifyAddDelTableReply: %s\n", reply);
     }
 
     private static void print(ClassifyTableIdsReply reply) {
-        System.out.printf("ClassifyTableIdsReply: context=%d, count=%d, ids.length=%d\n",
-            reply.context, reply.count, reply.ids.length);
-        Arrays.stream(reply.ids).forEach(System.out::println);
+        System.out.printf("ClassifyTableIdsReply: %s\n", reply);
     }
 
     private static void print(final ClassifyTableInfoReply reply) {
-        final StringBuilder builder = new StringBuilder("ClassifyTableInfoReply:\n");
-        builder.append("context: ").append(reply.context).append('\n');
-        builder.append("tableId: ").append(reply.tableId).append('\n');
-        builder.append("nbuckets: ").append(reply.nbuckets).append('\n');
-        builder.append("matchNVectors: ").append(reply.matchNVectors).append('\n');
-        builder.append("skipNVectors: ").append(reply.skipNVectors).append('\n');
-        builder.append("activeSessions: ").append(reply.activeSessions).append('\n');
-        builder.append("nextTableIndex: ").append(reply.nextTableIndex).append('\n');
-        builder.append("missNextIndex: ").append(reply.missNextIndex).append('\n');
-        builder.append("maskLength: ").append(reply.maskLength).append('\n');
-        builder.append("mask: ").append(DatatypeConverter.printHexBinary(reply.mask)).append('\n');
-        System.out.println(builder.toString());
+        System.out.println(reply);
+        if (reply != null) {
+            System.out.println("Mask hex: " + DatatypeConverter.printHexBinary(reply.mask));
+        }
     }
 
     private static void print(ClassifyAddDelSessionReply reply) {
-        System.out.printf("ClassifyAddDelSessionReply: context=%d\n",
-            reply.context);
+        System.out.printf("ClassifyAddDelSessionReply: context=%s\n", reply);
     }
 
     private static void print(final ClassifySessionDetailsReplyDump reply) {
-        if (reply.classifySessionDetails == null) {
-            System.out.println("ClassifySessionDetailsReplyDump: classifySessionDetails == NULL");
-        }
-        for (final ClassifySessionDetails details : reply.classifySessionDetails) {
-            final StringBuilder builder = new StringBuilder("ClassifySessionDetails:\n");
-            builder.append("context: ").append(details.context).append('\n');
-            builder.append("tableId: ").append(details.tableId).append('\n');
-            builder.append("hitNextIndex: ").append(details.hitNextIndex).append('\n');
-            builder.append("advance: ").append(details.advance).append('\n');
-            builder.append("opaqueIndex: ").append(details.opaqueIndex).append('\n');
-            builder.append("matchLength: ").append(details.matchLength).append('\n');
-            builder.append("match: ").append(DatatypeConverter.printHexBinary(details.match)).append('\n');
-            System.out.println(builder.toString());
-        }
+        System.out.println(reply);
+        reply.classifySessionDetails.forEach(detail -> {
+            System.out.println(detail);
+            System.out.println("Match hex: " + DatatypeConverter.printHexBinary(detail.match));
+        });
     }
 
     private static void print(final InputAclSetInterfaceReply reply) {
-        System.out.printf("InputAclSetInterfaceReply: context=%d\n", reply.context);
+        System.out.printf("InputAclSetInterfaceReply: context=%s\n", reply);
     }
 
     private static void print(final ClassifyTableByInterfaceReply reply) {
-        System.out.printf("ClassifyAddDelTableReply: context=%d, swIfIndex=%d, l2TableId=%d, ip4TableId=%d,"
-            + "ip6TableId=%d\n", reply.context, reply.swIfIndex, reply.l2TableId, reply.ip4TableId, reply.ip6TableId);
+        System.out.printf("ClassifyAddDelTableReply: %s\n", reply);
     }
 
     private static void testL2Acl() throws Exception {
@@ -180,34 +155,34 @@
         Thread.sleep(1000);
 
         final ClassifyAddDelTableReply classifyAddDelTableReply =
-            jvppFacade.classifyAddDelTable(createClassifyTable()).toCompletableFuture().get();
+                jvppFacade.classifyAddDelTable(createClassifyTable()).toCompletableFuture().get();
         print(classifyAddDelTableReply);
 
         final ClassifyTableIdsReply classifyTableIdsReply =
-            jvppFacade.classifyTableIds(new ClassifyTableIds()).toCompletableFuture().get();
+                jvppFacade.classifyTableIds(new ClassifyTableIds()).toCompletableFuture().get();
         print(classifyTableIdsReply);
 
         final ClassifyTableInfoReply classifyTableInfoReply =
-            jvppFacade.classifyTableInfo(createClassifyTableInfoRequest(classifyAddDelTableReply.newTableIndex))
-                .toCompletableFuture().get();
+                jvppFacade.classifyTableInfo(createClassifyTableInfoRequest(classifyAddDelTableReply.newTableIndex))
+                        .toCompletableFuture().get();
         print(classifyTableInfoReply);
 
         final ClassifyAddDelSessionReply classifyAddDelSessionReply =
-            jvppFacade.classifyAddDelSession(createClassifySession(classifyAddDelTableReply.newTableIndex))
-                .toCompletableFuture().get();
+                jvppFacade.classifyAddDelSession(createClassifySession(classifyAddDelTableReply.newTableIndex))
+                        .toCompletableFuture().get();
         print(classifyAddDelSessionReply);
 
         final ClassifySessionDetailsReplyDump classifySessionDetailsReplyDump =
-            jvppFacade.classifySessionDump(createClassifySessionDumpRequest(classifyAddDelTableReply.newTableIndex))
-                .toCompletableFuture().get();
+                jvppFacade.classifySessionDump(createClassifySessionDumpRequest(classifyAddDelTableReply.newTableIndex))
+                        .toCompletableFuture().get();
         print(classifySessionDetailsReplyDump);
 
         final InputAclSetInterfaceReply inputAclSetInterfaceReply =
-            jvppFacade.inputAclSetInterface(aclSetInterface()).toCompletableFuture().get();
+                jvppFacade.inputAclSetInterface(aclSetInterface()).toCompletableFuture().get();
         print(inputAclSetInterfaceReply);
 
         final ClassifyTableByInterfaceReply classifyTableByInterfaceReply =
-            jvppFacade.classifyTableByInterface(createClassifyTableByInterfaceRequest()).toCompletableFuture().get();
+                jvppFacade.classifyTableByInterface(createClassifyTableByInterfaceRequest()).toCompletableFuture().get();
         print(classifyTableByInterfaceReply);
 
         System.out.println("Disconnecting...");
diff --git a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/NotificationUtils.java b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/NotificationUtils.java
index 2e4d810..02875bb 100644
--- a/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/NotificationUtils.java
+++ b/vpp-api/java/jvpp-core/org/openvpp/jvpp/core/test/NotificationUtils.java
@@ -26,8 +26,7 @@
     private NotificationUtils() {}
 
     static PrintStream printNotification(final SwInterfaceSetFlagsNotification msg) {
-        return System.out.printf("Received interface notification: ifc: %d, admin: %d, link: %d, deleted: %d\n",
-            msg.swIfIndex, msg.adminUpDown, msg.linkUpDown, msg.deleted);
+        return System.out.printf("Received interface notification: ifc: %s\n", msg);
     }
 
     static SwInterfaceSetFlags getChangeInterfaceState() {
diff --git a/vpp-api/java/jvpp-registry/org/openvpp/jvpp/dto/ControlPingReply.java b/vpp-api/java/jvpp-registry/org/openvpp/jvpp/dto/ControlPingReply.java
index e7efd85..6377fcd 100644
--- a/vpp-api/java/jvpp-registry/org/openvpp/jvpp/dto/ControlPingReply.java
+++ b/vpp-api/java/jvpp-registry/org/openvpp/jvpp/dto/ControlPingReply.java
@@ -16,6 +16,8 @@
 
 package org.openvpp.jvpp.dto;
 
+import java.util.Objects;
+
 /**
  * Represents reply DTO for control_ping message.
  */
@@ -25,6 +27,32 @@
     public int clientIndex;
     public int vpePid;
 
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        final ControlPingReply that = (ControlPingReply) o;
+        return context == that.context &&
+                clientIndex == that.clientIndex &&
+                vpePid == that.vpePid;
+    }
 
+    @Override
+    public int hashCode() {
+        return Objects.hash(context, clientIndex, vpePid);
+    }
+
+    @Override
+    public String toString() {
+        return "ControlPingReply{" +
+                "context=" + context +
+                ", clientIndex=" + clientIndex +
+                ", vpePid=" + vpePid +
+                '}';
+    }
 }
 
diff --git a/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py b/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py
index 785e47e..0f74a1d 100644
--- a/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py
+++ b/vpp-api/java/jvpp/gen/jvppgen/dto_gen.py
@@ -40,7 +40,7 @@
 send_template = Template("""    @Override
     public int send(final $base_package.JVpp jvpp) throws org.openvpp.jvpp.VppInvocationException {
         return (($plugin_package.JVpp${plugin_name})jvpp).$method_name($args);
-    }\n""")
+    }""")
 
 
 def generate_dtos(func_list, base_package, plugin_package, plugin_name, dto_package, inputfile):
@@ -58,15 +58,8 @@
         if util.is_ignored(func['name']) or util.is_control_ping(camel_case_dto_name):
             continue
 
-        fields = ""
-        for t in zip(func['types'], func['args']):
-            # for retval don't generate dto field in Reply
-            field_name = util.underscore_to_camelcase(t[1])
-            if util.is_reply(camel_case_dto_name) and util.is_retval_field(field_name):
-                continue
-            fields += field_template.substitute(type=util.jni_2_java_type_mapping[t[0]],
-                                                name=field_name)
-        methods = ""
+        fields = generate_dto_fields(camel_case_dto_name, func)
+        methods = generate_dto_base_methods(camel_case_dto_name, func)
         base_type = ""
 
         # Generate request/reply or dump/dumpReply even if structure can be used as notification
@@ -77,17 +70,17 @@
                 if util.is_details(camel_case_dto_name):
                     # FIXME assumption that dump calls end with "Dump" suffix. Not enforced in vpe.api
                     base_type += "JVppReply<%s.%s.%s>" % (plugin_package, dto_package, request_dto_name + "Dump")
-                    generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_package, camel_case_dto_name,
-                                            camel_case_method_name, func)
+                    generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_package,
+                                            camel_case_dto_name, camel_case_method_name, func)
                 else:
                     base_type += "JVppReply<%s.%s.%s>" % (plugin_package, dto_package, request_dto_name)
             else:
                 args = "" if fields is "" else "this"
-                methods = send_template.substitute(method_name=camel_case_method_name,
-                                                   base_package=base_package,
-                                                   plugin_package=plugin_package,
-                                                   plugin_name=plugin_name,
-                                                   args=args)
+                methods += send_template.substitute(method_name=camel_case_method_name,
+                                                    base_package=base_package,
+                                                    plugin_package=plugin_package,
+                                                    plugin_name=plugin_name,
+                                                    args=args)
                 if util.is_dump(camel_case_dto_name):
                     base_type += "JVppDump"
                     description = "dump request DTO"
@@ -95,24 +88,143 @@
                     base_type += "JVppRequest"
                     description = "request DTO"
 
-            write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func,
-                           inputfile, methods)
+            write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package,
+                           dto_path, fields, func, inputfile, methods)
 
         # for structures that are also used as notifications, generate dedicated notification DTO
         if util.is_notification(func["name"]):
             base_type = "JVppNotification"
             description = "notification DTO"
             camel_case_dto_name = util.add_notification_suffix(camel_case_dto_name)
-            methods = ""
             dto_path = os.path.join(dto_package, camel_case_dto_name + ".java")
-            write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func,
-                           inputfile, methods)
+            methods = generate_dto_base_methods(camel_case_dto_name, func)
+            write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package,
+                           dto_path, fields, func, inputfile, methods)
 
     flush_dump_reply_dtos(inputfile)
 
 
-def write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path, fields, func,
-                   inputfile, methods):
+def generate_dto_base_methods(camel_case_dto_name, func):
+    methods = generate_dto_hash(func)
+    methods += generate_dto_equals(camel_case_dto_name, func)
+    methods += generate_dto_tostring(camel_case_dto_name, func)
+    return methods
+
+
+def generate_dto_fields(camel_case_dto_name, func):
+    fields = ""
+    for t in zip(func['types'], func['args']):
+        # for retval don't generate dto field in Reply
+        field_name = util.underscore_to_camelcase(t[1])
+        if util.is_reply(camel_case_dto_name) and util.is_retval_field(field_name):
+            continue
+        fields += field_template.substitute(type=util.jni_2_java_type_mapping[t[0]],
+                                            name=field_name)
+    return fields
+
+
+tostring_field_template = Template("""                \"$field_name=\" + $field_name + ", " +\n""")
+tostring_array_field_template = Template("""                \"$field_name=\" + java.util.Arrays.toString($field_name) + ", " +\n""")
+tostring_template = Template("""    @Override
+    public String toString() {
+        return "$cls_name{" +
+$fields_tostring "}";
+    }\n\n""")
+
+
+def generate_dto_tostring(camel_case_dto_name, func):
+    tostring_fields = ""
+    for t in zip(func['types'], func['args']):
+
+        field_name = util.underscore_to_camelcase(t[1])
+        # for retval don't generate dto field in Reply
+        if util.is_retval_field(field_name):
+            continue
+
+        # handle array types
+        if util.is_array(util.jni_2_java_type_mapping[t[0]]):
+            tostring_fields += tostring_array_field_template.substitute(field_name=field_name)
+        else:
+            tostring_fields += tostring_field_template.substitute(field_name=field_name)
+
+    return tostring_template.substitute(cls_name=camel_case_dto_name,
+                                        fields_tostring=tostring_fields[:-8])
+
+
+equals_field_template = Template("""        if (!java.util.Objects.equals(this.$field_name, other.$field_name)) {
+            return false;
+        }\n""")
+equals_array_field_template = Template("""        if (!java.util.Arrays.equals(this.$field_name, other.$field_name)) {
+            return false;
+        }\n""")
+equals_template = Template("""    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final $cls_name other = ($cls_name) o;
+
+$comparisons
+        return true;
+    }\n\n""")
+
+
+def generate_dto_equals(camel_case_dto_name, func):
+    equals_fields = ""
+    for t in zip(func['types'], func['args']):
+        field_name = util.underscore_to_camelcase(t[1])
+        # for retval don't generate dto field in Reply
+        if util.is_retval_field(field_name):
+            continue
+
+        # handle array types
+        if util.is_array(util.jni_2_java_type_mapping[t[0]]):
+            equals_fields += equals_array_field_template.substitute(field_name=field_name)
+        else:
+            equals_fields += equals_field_template.substitute(field_name=field_name)
+
+    return equals_template.substitute(cls_name=camel_case_dto_name,
+                                      comparisons=equals_fields)
+
+
+hash_template = Template("""    @Override
+    public int hashCode() {
+        return java.util.Objects.hash($fields);
+    }\n\n""")
+hash_single_array_type_template = Template("""    @Override
+    public int hashCode() {
+        return java.util.Arrays.hashCode($fields);
+    }\n\n""")
+
+
+def generate_dto_hash(func):
+    hash_fields = ""
+
+    # Special handling for hashCode in case just a single array field is present. Cannot use Objects.equals since the
+    # array is mistaken for a varargs parameter. Instead use Arrays.hashCode in such case.
+    if len(func['args']) == 1:
+        single_type = func['types'][0]
+        single_type_name = func['args'][0]
+        if util.is_array(util.jni_2_java_type_mapping[single_type]):
+            return hash_single_array_type_template.substitute(fields=util.underscore_to_camelcase(single_type_name))
+
+    for t in zip(func['types'], func['args']):
+        field_name = util.underscore_to_camelcase(t[1])
+        # for retval don't generate dto field in Reply
+        if util.is_retval_field(field_name):
+            continue
+
+        hash_fields += field_name + ", "
+
+    return hash_template.substitute(fields=hash_fields[:-2])
+
+
+def write_dto_file(base_package, plugin_package, base_type, camel_case_dto_name, description, dto_package, dto_path,
+                   fields, func, inputfile, methods):
     dto_file = open(dto_path, 'w')
     dto_file.write(dto_template.substitute(inputfile=inputfile,
                                            description=description,
@@ -131,6 +243,7 @@
 dump_dto_suffix = "ReplyDump"
 dump_reply_artificial_dtos = {}
 
+
 # Returns request name or special one from unconventional_naming_rep_req map
 def get_request_name(camel_case_dto_name, func_name):
     return util.underscore_to_camelcase_upper(
@@ -157,26 +270,38 @@
         dto_file.close()
 
 
-def generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_package, camel_case_dto_name, camel_case_method_name,
-                            func):
+def generate_dump_reply_dto(request_dto_name, base_package, plugin_package, dto_package, camel_case_dto_name,
+                            camel_case_method_name, func):
     base_type = "JVppReplyDump<%s.%s.%s, %s.%s.%s>" % (
         plugin_package, dto_package, util.remove_reply_suffix(camel_case_dto_name) + "Dump",
         plugin_package, dto_package, camel_case_dto_name)
     fields = "    public java.util.List<%s> %s = new java.util.ArrayList<>();" % (camel_case_dto_name, camel_case_method_name)
     cls_name = camel_case_dto_name + dump_dto_suffix
+    # using artificial type for fields, just to bypass the is_array check in base methods generators
+    # the type is not really used
+    artificial_type = 'jstring'
 
     # In case of already existing artificial reply dump DTO, just update it
     # Used for sub-dump dtos
     if request_dto_name in dump_reply_artificial_dtos.keys():
-        dump_reply_artificial_dtos[request_dto_name]['fields'] = \
-            dump_reply_artificial_dtos[request_dto_name]['fields'] + '\n' + fields
+        dump_reply_artificial_dtos[request_dto_name]['fields'] += '\n' + fields
+        dump_reply_artificial_dtos[request_dto_name]['field_names'].append(func['name'])
+        dump_reply_artificial_dtos[request_dto_name]['field_types'].append(artificial_type)
+        methods = '\n' + generate_dto_base_methods(dump_reply_artificial_dtos[request_dto_name]['cls_name'],
+                                            {'args': dump_reply_artificial_dtos[request_dto_name]['field_names'],
+                                             'types': dump_reply_artificial_dtos[request_dto_name]['field_types']})
+        dump_reply_artificial_dtos[request_dto_name]['methods'] = methods
     else:
+        methods = '\n' + generate_dto_base_methods(cls_name, {'args': [func['name']],
+                                                              'types': [artificial_type]})
         dump_reply_artificial_dtos[request_dto_name] = ({'docs': util.api_message_to_javadoc(func),
                                                          'cls_name': cls_name,
                                                          'fields': fields,
-                                                         'methods': "",
+                                                         'field_names': [func['name']],
+                                                         'field_types': [artificial_type],
+                                                         # strip too many newlines at the end of base method block
+                                                         'methods': methods,
                                                          'plugin_package': plugin_package,
                                                          'base_package': base_package,
                                                          'base_type': base_type,
-                                                         'dto_package': dto_package,
-                                                         })
+                                                         'dto_package': dto_package})
diff --git a/vpp-api/java/jvpp/gen/jvppgen/util.py b/vpp-api/java/jvpp/gen/jvppgen/util.py
index 0018e01..712f178 100644
--- a/vpp-api/java/jvpp/gen/jvppgen/util.py
+++ b/vpp-api/java/jvpp/gen/jvppgen/util.py
@@ -45,6 +45,7 @@
 def is_details(name):
     return name.lower().endswith(reply_suffixes[1]) or name.lower().endswith(reply_suffixes[2])
 
+
 def is_retval_field(name):
     return name == 'retval'
 
@@ -184,6 +185,7 @@
 def is_control_ping(camel_case_name_with_suffix):
     return camel_case_name_with_suffix.lower().startswith("controlping");
 
+
 def api_message_to_javadoc(api_message):
     """ Converts vpe.api message description to javadoc """
     str = pprint.pformat(api_message, indent=4, width=120, depth=None)
@@ -196,3 +198,7 @@
 def add_notification_suffix(camel_case_dto_name):
     camel_case_dto_name += notification_dto_suffix
     return camel_case_dto_name
+
+
+def is_array(java_type_as_string):
+    return java_type_as_string.endswith("[]")