public String getInverseAddressFormat(String ipAddress) {

        ipAddress = StringUtils.trim(ipAddress);

        validateIpAddress(ipAddress);

        LOG.debug("Preparing inverse format for IP address [{}]", ipAddress);

        // Detect what type of address is provided (IPv4 or IPv6)
        if (isIp6Address(ipAddress)) {

            LOG.debug("[{}] is an IPv6 address", ipAddress);

            /* Build reverse IPv6 address string with correct ip6.arpa suffix.
             * All hex nibbles from the full address should be reversed (with dots in between)
             * and the ip6.arpa suffix added to the end.
             *
             * For example, the reverse format for the address 2604:a880:800:10::7a1:b001 is
             * 1.0.0.b.1.a.7.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.0.0.8.8.a.4.0.6.2.ip6.arpa
             * See https://www.dnscheck.co/ptr-record-monitor for more info. */

            // Parse the full address as an InetAddress to allow the full address bytes (16 bytes/128 bits) to be obtained.
            final byte[] addressBytes = InetAddresses.forString(ipAddress).getAddress();

            if (addressBytes.length > 16) {
                throw new IllegalArgumentException(String.format(Locale.ENGLISH, "[%s] is an invalid IPv6 address", ipAddress));
            }

            // Convert the raw address bytes to hex.
            final char[] resolvedHex = new char[addressBytes.length * 2];
            for (int i = 0; i < addressBytes.length; i++) {
                final int v = addressBytes[i] & 0xFF;
                resolvedHex[i * 2] = HEX_CHARS_ARRAY[v >>> 4];
                resolvedHex[i * 2 + 1] = HEX_CHARS_ARRAY[v & 0x0F];
            }

            final String fullHexAddress = new String(resolvedHex).toLowerCase(Locale.ENGLISH);
            final String[] reversedAndSplit = new StringBuilder(fullHexAddress).reverse().toString().split("");

            final String invertedAddress = Joiner.on(".").join(reversedAndSplit);

            LOG.debug("Inverted address [{}] built for [{}]", invertedAddress, ipAddress);

            return invertedAddress + IP_6_REVERSE_SUFFIX;
        } else {

            LOG.debug("[{}] is an IPv4 address", ipAddress);

            /* Build reverse IPv4 address string with correct in-addr.arpa suffix.
             * All octets should be reversed and the ip6.arpa suffix added to the end.
             *
             * For example, the reverse format for the address 10.20.30.40 is
             * 40.30.20.10.in-addr.arpa */
            final String[] octets = ipAddress.split("\\.");
            final String invertedAddress = octets[3] + "." + octets[2] + "." + octets[1] + "." + octets[0] + IP_4_REVERSE_SUFFIX;

            LOG.debug("Inverted address [{}] built for [{}]", invertedAddress, ipAddress);

            return invertedAddress;
        }
    }
@Test
    public void testReverseIpFormat() {

        DnsClient dnsClient = new DnsClient(5000);

        // Test IPv4 reverse format.
        assertEquals("40.30.20.10.in-addr.arpa.", dnsClient.getInverseAddressFormat("10.20.30.40"));

        // Test IPv6 reverse format.
        assertEquals("1.0.0.b.1.a.7.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.0.0.8.8.a.4.0.6.2.ip6.arpa.",
                     dnsClient.getInverseAddressFormat("2604:a880:800:10::7a1:b001"));
    }