docs: public static String canonize(String ipv6Address) throws IllegalArgumentException {
  
          if (ipv6Address == null) {
              return null;
          }
  
          // Definitely not an IPv6, return untouched input.
          if (!mayBeIPv6Address(ipv6Address)) {
              return ipv6Address;
          }
  
          // Length without zone ID (%zone) or IPv4 address
          int ipv6AddressLength = ipv6Address.length();
          if (isIPv4AddressInIPv6(ipv6Address)) {
              // IPv4 in IPv6
              // e.g. 0:0:0:0:0:FFFF:127.0.0.1
              int lastColonPos = ipv6Address.lastIndexOf(":");
              int lastColonsPos = ipv6Address.lastIndexOf("::");
              if (lastColonsPos >= 0 && lastColonPos == lastColonsPos + 1) {
                  // IPv6 part ends with two consecutive colons, last colon is part of IPv6 format.
                  // e.g. ::127.0.0.1
                  ipv6AddressLength = lastColonPos + 1;
              } else {
                  // IPv6 part ends with only one colon, last colon is not part of IPv6 format.
                  // e.g. ::FFFF:127.0.0.1
                  ipv6AddressLength = lastColonPos;
              }
          } else if (ipv6Address.contains(":") && ipv6Address.contains("%")) {
              // Zone ID
              // e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
              ipv6AddressLength = ipv6Address.lastIndexOf("%");
          }
  
          StringBuilder result = new StringBuilder();
          char [][] groups = new char[IPV6_LEN][MAX_GROUP_LENGTH];
          int groupCounter = 0;
          int charInGroupCounter = 0;
  
          // Index of the current zeroGroup, -1 means not found.
          int zeroGroupIndex = -1;
          int zeroGroupLength = 0;
  
          // maximum length zero group, if there is more then one, then first one
          int maxZeroGroupIndex = -1;
          int maxZeroGroupLength = 0;
  
          boolean isZero = true;
          boolean groupStart = true;
  
          /*
           *  Two consecutive colons, initial expansion.
           *  e.g. 2001:db8:0:0:1::1 -> 2001:db8:0:0:1:0:0:1
           */
          StringBuilder expanded = new StringBuilder(ipv6Address);
          int colonsPos = ipv6Address.indexOf("::");
          int length = ipv6AddressLength;
          int change = 0;
  
          if (colonsPos >= 0 && colonsPos < ipv6AddressLength - 2) {
              int colonCounter = 0;
              for (int i = 0; i < ipv6AddressLength; i++) {
                  if (ipv6Address.charAt(i) == ':') {
                      colonCounter++;
                  }
              }
  
              if (colonsPos == 0) {
                  expanded.insert(0, "0");
                  change = change + 1;
              }
  
              for (int i = 0; i < IPV6_LEN - colonCounter; i++) {
                  expanded.insert(colonsPos + 1, "0:");
                  change = change + 2;
              }
  
  
              if (colonsPos == ipv6AddressLength - 2) {
                  expanded.setCharAt(colonsPos + change + 1, '0');
              } else {
                  expanded.deleteCharAt(colonsPos + change + 1);
                  change = change - 1;
              }
              length = length + change;
          }
  
  
          // Processing one char at the time
          for (int charCounter = 0; charCounter < length; charCounter++) {
              char c = expanded.charAt(charCounter);
              if (c >= 'A' && c <= 'F') {
                  c = (char) (c + 32);
              }
              if (c != ':') {
                  groups[groupCounter][charInGroupCounter] = c;
                  if (!(groupStart && c == '0')) {
                      ++charInGroupCounter;
                      groupStart = false;
                  }
                  if (c != '0') {
                      isZero = false;
                  }
              }
              if (c == ':' || charCounter == (length - 1)) {
                  // We reached end of current group
                  if (isZero) {
                      ++zeroGroupLength;
                      if (zeroGroupIndex == -1) {
                          zeroGroupIndex = groupCounter;
                      }
                  }
  
                  if (!isZero || charCounter == (length - 1)) {
                      // We reached end of zero group
                      if (zeroGroupLength > maxZeroGroupLength) {
                          maxZeroGroupLength = zeroGroupLength;
                          maxZeroGroupIndex = zeroGroupIndex;
                      }
                      zeroGroupLength = 0;
                      zeroGroupIndex = -1;
                  }
                  ++groupCounter;
                  charInGroupCounter = 0;
                  isZero = true;
                  groupStart = true;
              }
          }
  
          int numberOfGroups = groupCounter;
  
          // Output results
          for (groupCounter = 0; groupCounter < numberOfGroups; groupCounter++) {
              if (maxZeroGroupLength <= 1 || groupCounter < maxZeroGroupIndex
                      || groupCounter >= maxZeroGroupIndex + maxZeroGroupLength) {
                  for (int j = 0; j < MAX_GROUP_LENGTH; j++) {
                      if (groups[groupCounter][j] != 0) {
                          result.append(groups[groupCounter][j]);
                      }
                  }
                  if (groupCounter < (numberOfGroups - 1)
                          && (groupCounter != maxZeroGroupIndex - 1
                                  || maxZeroGroupLength <= 1)) {
                      result.append(':');
                  }
              } else if (groupCounter == maxZeroGroupIndex) {
                  result.append("::");
              }
          }
  
          // Solve problem with three colons in IPv4 in IPv6 format
          // e.g. 0:0:0:0:0:0:127.0.0.1 -> :::127.0.0.1 -> ::127.0.0.1
          int resultLength = result.length();
          if (result.charAt(resultLength - 1) == ':' && ipv6AddressLength < ipv6Address.length()
                  && ipv6Address.charAt(ipv6AddressLength) == ':') {
              result.delete(resultLength - 1, resultLength);
          }
  
          /*
           * Append IPv4 from IPv4-in-IPv6 format or Zone ID
           */
          for (int i = ipv6AddressLength; i < ipv6Address.length(); i++) {
              result.append(ipv6Address.charAt(i));
          }
  
          return result.toString();
      }