code: public String substitute(List<String> values) throws IllegalArgumentException {
          if (values == null) {
              throw new IllegalArgumentException("values is null");
          }
          Iterator<String> iter = values.iterator();
          StringBuilder sb = new StringBuilder();
          for (UriChunk chunk : uriChunks) {
              if (chunk instanceof Variable) {
                  Variable var = (Variable) chunk;
                  if (iter.hasNext()) {
                      String value = iter.next();
                      if (!var.matches(value)) {
                          throw new IllegalArgumentException("Value '" + value + "' does not match variable "
                                                             + var.getName() + " with pattern "
                                                             + var.getPattern());
                      }
                      sb.append(value);
                  } else {
                      sb.append(var);
                  }
              } else {
                  sb.append(chunk);
              }
          }
          return sb.toString();
      }
docs: Substitutes template variables with listed values. List of values is counterpart for
  {@link #getVariables() list of variables}. When list of value is shorter than variables substitution
  is partial. When variable has pattern, value must fit to pattern, otherwise
  {@link IllegalArgumentException} is thrown.
  <p>
  Example1: for template "/{a}/{b}/{a}" {@link #getVariables()} returns "[a, b, a]"; providing here list
  of value "[foo, bar, baz]" results with "/foo/bar/baz".
  <p>
  Example2: for template "/{a}/{b}/{a}" providing list of values "[foo]" results with "/foo/{b}/{a}".
  
  @param values values for variables
  @return template with bound variables.
  @throws IllegalArgumentException when values is null, any value does not match pattern etc.