docs: public String substitute(Map<String, ? extends Object> valuesMap,
                               Set<String> encodePathSlashVars,
                               boolean allowUnresolved) throws IllegalArgumentException {
          if (valuesMap == null) {
              throw new IllegalArgumentException("valuesMap is null");
          }
          StringBuilder sb = new StringBuilder();
          for (UriChunk chunk : uriChunks) {
              if (chunk instanceof Variable) {
                  Variable var = (Variable) chunk;
                  Object value = valuesMap.get(var.getName());
                  if (value != null) {
                      String sval = value.toString();
                      if (!var.matches(sval)) {
                          throw new IllegalArgumentException("Value '" + sval + "' does not match variable "
                                                             + var.getName() + " with pattern "
                                                             + var.getPattern());
                      }
                      if (encodePathSlashVars.contains(var.getName())) {
                          sval = sval.replaceAll("/", "%2F");
                      }
                      sb.append(sval);
                  } else if (allowUnresolved) {
                      sb.append(chunk);
                  } else {
                      throw new IllegalArgumentException("Template variable " + var.getName()
                                                         + " has no matching value");
                  }
              } else {
                  sb.append(chunk);
              }
          }
          return sb.toString();
      }