jakarta.ws.rs.core.UriBuilder Maven / Gradle / Ivy
Show all versions of jaxrs-ri Show documentation
/*
* Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package jakarta.ws.rs.core;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Map;
import jakarta.ws.rs.ext.RuntimeDelegate;
/**
* URI template-aware utility class for building URIs from their components. See {@link jakarta.ws.rs.Path#value} for an
* explanation of URI templates.
*
*
* Builder methods perform contextual encoding of characters not permitted in the corresponding URI component following
* the rules of the
* application/x-www-form-urlencoded media type
* for query parameters and RFC 3986 for all other components. Note that
* only characters not permitted in a particular component are subject to encoding so, e.g., a path supplied to one of
* the {@code path} methods may contain matrix parameters or multiple path segments since the separators are legal
* characters and will not be encoded. Percent encoded values are also recognized where allowed and will not be double
* encoded.
*
*
*
* URI templates are allowed in most components of a URI but their value is restricted to a particular component. E.g.
*
UriBuilder.fromPath("{arg1}").build("foo#bar");
would result in encoding of the
* '#' such that the resulting URI is "foo%23bar". To create a URI "foo#bar" use
* UriBuilder.fromPath("{arg1}").fragment("{arg2}").build("foo", "bar")
instead.
* URI template names and delimiters are never encoded but their values are encoded when a URI is built. Template
* parameter regular expressions are ignored when building a URI, i.e. no validation is performed.
*
* @author Paul Sandoz
* @author Marc Hadley
* @see java.net.URI
* @see jakarta.ws.rs.Path
* @since 1.0
*/
public abstract class UriBuilder {
/**
* Protected constructor, use one of the static fromXxx(...)
methods to obtain an instance.
*/
protected UriBuilder() {
}
/**
* Creates a new instance of UriBuilder.
*
* @return a new instance of UriBuilder.
* @since 3.0
*/
public static UriBuilder newInstance() {
return RuntimeDelegate.getInstance().createUriBuilder();
}
/**
* Create a new instance initialized from an existing URI.
*
* @param uri a URI that will be used to initialize the UriBuilder.
* @return a new UriBuilder.
* @throws IllegalArgumentException if uri is {@code null}.
*/
public static UriBuilder fromUri(final URI uri) {
return newInstance().uri(uri);
}
/**
* Create a new instance initialized from an existing URI.
*
* @param uriTemplate a URI template that will be used to initialize the UriBuilder, may contain URI parameters.
* @return a new UriBuilder.
* @throws IllegalArgumentException if {@code uriTemplate} is not a valid URI template or is {@code null}.
*/
public static UriBuilder fromUri(final String uriTemplate) {
return newInstance().uri(uriTemplate);
}
/**
* Create a new instance initialized from a Link.
*
* @param link a Link that will be used to initialize the UriBuilder, only its URI is used.
* @return a new UriBuilder
* @throws IllegalArgumentException if link is {@code null}
* @since 2.0
*/
public static UriBuilder fromLink(final Link link) {
if (link == null) {
throw new IllegalArgumentException("The provider 'link' parameter value is 'null'.");
}
return UriBuilder.fromUri(link.getUri());
}
/**
* Create a new instance representing a relative URI initialized from a URI path.
*
* @param path a URI path that will be used to initialize the UriBuilder, may contain URI template parameters.
* @return a new UriBuilder.
* @throws IllegalArgumentException if path is {@code null}.
*/
public static UriBuilder fromPath(final String path) throws IllegalArgumentException {
return newInstance().path(path);
}
/**
* Create a new instance representing a relative URI initialized from a root resource class.
*
* @param resource a root resource whose {@link jakarta.ws.rs.Path} value will be used to initialize the UriBuilder.
* @return a new UriBuilder.
* @throws IllegalArgumentException if resource is not annotated with {@link jakarta.ws.rs.Path} or resource is
* {@code null}.
*/
public static UriBuilder fromResource(final Class> resource) {
return newInstance().path(resource);
}
/**
* Create a new instance representing a relative URI initialized from a {@link jakarta.ws.rs.Path}-annotated method.
*
* This method can only be used in cases where there is a single method with the specified name that is annotated with
* {@link jakarta.ws.rs.Path}.
*
* @param resource the resource containing the method.
* @param method the name of the method whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if resource or method is {@code null}, or there is more than or less than one
* variant of the method annotated with {@link jakarta.ws.rs.Path}.
* @since 2.0
*/
public static UriBuilder fromMethod(final Class> resource, final String method) {
return newInstance().path(resource, method);
}
/**
* Create a copy of the UriBuilder preserving its state. This is a more efficient means of creating a copy than
* constructing a new UriBuilder from a URI returned by the {@link #build(Object...)} method.
*
* @return a copy of the UriBuilder.
*/
@SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
@Override
public abstract UriBuilder clone();
/**
* Copies the non-null components of the supplied URI to the UriBuilder replacing any existing values for those
* components.
*
* @param uri the URI to copy components from.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the {@code uri} parameter is {@code null}.
*/
public abstract UriBuilder uri(URI uri);
/**
* Parses the {@code uriTemplate} string and copies the parsed components of the supplied URI to the UriBuilder
* replacing any existing values for those components.
*
* @param uriTemplate a URI template that will be used to initialize the UriBuilder, may contain URI parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if {@code uriTemplate} is not a valid URI template or is {@code null}.
* @since 2.0
*/
public abstract UriBuilder uri(String uriTemplate);
/**
* Set the URI scheme.
*
* @param scheme the URI scheme, may contain URI template parameters. A {@code null} value will unset the URI scheme,
* but will not unset the any scheme-specific-part components.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if scheme is invalid.
*/
public abstract UriBuilder scheme(String scheme);
/**
* Set the URI scheme-specific-part (see {@link java.net.URI}). This method will overwrite any existing values for
* authority, user-info, host, port and path.
*
* @param ssp the URI scheme-specific-part, may contain URI template parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if ssp cannot be parsed or is {@code null}.
*/
public abstract UriBuilder schemeSpecificPart(String ssp);
/**
* Set the URI user-info.
*
* @param ui the URI user-info, may contain URI template parameters. A {@code null} value will unset userInfo component
* of the URI.
* @return the updated UriBuilder.
*/
public abstract UriBuilder userInfo(String ui);
/**
* Set the URI host.
*
* @param host the URI host, may contain URI template parameters. A {@code null} value will unset the host component of
* the URI, but will not unset other authority component parts ({@link #userInfo(String) user info} or {@link #port(int)
* port}).
* @return the updated UriBuilder.
* @throws IllegalArgumentException if host is invalid.
*/
public abstract UriBuilder host(String host);
/**
* Set the URI port.
*
* @param port the URI port, a value of -1 will unset an explicit port.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if port is invalid.
*/
public abstract UriBuilder port(int port);
/**
* Set the URI path. This method will overwrite any existing path and associated matrix parameters. Existing '/'
* characters are preserved thus a single value can represent multiple URI path segments.
*
* @param path the path, may contain URI template parameters. A {@code null} value will unset the path component of the
* URI.
* @return the updated UriBuilder.
*/
public abstract UriBuilder replacePath(String path);
/**
* Append path to the existing path. When constructing the final path, a '/' separator will be inserted between the
* existing path and the supplied path if necessary. Existing '/' characters are preserved thus a single value can
* represent multiple URI path segments.
*
* @param path the path, may contain URI template parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if path is {@code null}.
*/
public abstract UriBuilder path(String path);
/**
* Append the path from a Path-annotated class to the existing path. When constructing the final path, a '/' separator
* will be inserted between the existing path and the supplied path if necessary.
*
* @param resource a resource whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if resource is {@code null}, or if resource is not annotated with
* {@link jakarta.ws.rs.Path}.
*/
public abstract UriBuilder path(Class resource);
/**
* Append the path from a Path-annotated method to the existing path. When constructing the final path, a '/' separator
* will be inserted between the existing path and the supplied path if necessary. This method is a convenience shortcut
* to {@code path(Method)}, it can only be used in cases where there is a single method with the specified name that is
* annotated with {@link jakarta.ws.rs.Path}.
*
* @param resource the resource containing the method.
* @param method the name of the method whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if resource or method is {@code null}, or there is more than or less than one
* variant of the method annotated with {@link jakarta.ws.rs.Path}.
*/
public abstract UriBuilder path(Class resource, String method);
/**
* Append the path from a {@link jakarta.ws.rs.Path}-annotated method to the existing path. When constructing the final
* path, a '/' separator will be inserted between the existing path and the supplied path if necessary.
*
* @param method a method whose {@link jakarta.ws.rs.Path} value will be used to obtain the path to append to the existing
* path.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if method is {@code null} or is not annotated with a {@link jakarta.ws.rs.Path}.
*/
public abstract UriBuilder path(Method method);
/**
* Append path segments to the existing path. When constructing the final path, a '/' separator will be inserted between
* the existing path and the first path segment if necessary and each supplied segment will also be separated by '/'.
* Existing '/' characters are encoded thus a single value can only represent a single URI path segment.
*
* @param segments the path segment values, each may contain URI template parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if segments or any element of segments is {@code null}.
*/
public abstract UriBuilder segment(String... segments);
/**
* Set the matrix parameters of the current final segment of the current URI path. This method will overwrite any
* existing matrix parameters on the current final segment of the current URI path. Note that the matrix parameters are
* tied to a particular path segment; subsequent addition of path segments will not affect their position in the URI
* path.
*
* @param matrix the matrix parameters, may contain URI template parameters. A {@code null} value will remove all matrix
* parameters of the current final segment of the current URI path.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if matrix cannot be parsed.
* @see Matrix URIs
*/
public abstract UriBuilder replaceMatrix(String matrix);
/**
* Append a matrix parameter to the existing set of matrix parameters of the current final segment of the URI path. If
* multiple values are supplied the parameter will be added once per value. Note that the matrix parameters are tied to
* a particular path segment; subsequent addition of path segments will not affect their position in the URI path.
*
* @param name the matrix parameter name, may contain URI template parameters.
* @param values the matrix parameter value(s), each object will be converted. to a {@code String} using its
* {@code toString()} method. Stringified values may contain URI template parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if name or values is {@code null}.
* @see Matrix URIs
*/
public abstract UriBuilder matrixParam(String name, Object... values);
/**
* Replace the existing value(s) of a matrix parameter on the current final segment of the URI path. If multiple values
* are supplied the parameter will be added once per value. Note that the matrix parameters are tied to a particular
* path segment; subsequent addition of path segments will not affect their position in the URI path.
*
* @param name the matrix parameter name, may contain URI template parameters.
* @param values the matrix parameter value(s), each object will be converted. to a {@code String} using its
* {@code toString()} method. Stringified values may contain URI template parameters. If {@code values} is empty or
* {@code null} then all current values of the parameter are removed.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if name is {@code null}.
* @see Matrix URIs
*/
public abstract UriBuilder replaceMatrixParam(String name, Object... values);
/**
* Set the URI query string. This method will overwrite any existing query parameters.
*
* @param query the URI query string, may contain URI template parameters. A {@code null} value will remove all query
* parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if query cannot be parsed.
*/
public abstract UriBuilder replaceQuery(String query);
/**
* Append a query parameter to the existing set of query parameters. If multiple values are supplied the parameter will
* be added once per value.
*
* @param name the query parameter name, may contain URI template parameters.
* @param values the query parameter value(s), each object will be converted to a {@code String} using its
* {@code toString()} method. Stringified values may contain URI template parameters.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if name or values is {@code null}.
*/
public abstract UriBuilder queryParam(String name, Object... values);
/**
* Replace the existing value(s) of a query parameter. If multiple values are supplied the parameter will be added once
* per value.
*
* @param name the query parameter name, may contain URI template parameters.
* @param values the query parameter value(s), each object will be converted to a {@code String} using its
* {@code toString()} method. Stringified values may contain URI template parameters. If {@code values} is empty or
* {@code null} then all current values of the parameter are removed.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if name is {@code null}.
*/
public abstract UriBuilder replaceQueryParam(String name, Object... values);
/**
* Set the URI fragment.
*
* @param fragment the URI fragment, may contain URI template parameters. A {@code null} value will remove any existing
* fragment.
* @return the updated UriBuilder.
*/
public abstract UriBuilder fragment(String fragment);
/**
* Resolve a URI template with a given {@code name} in this {@code UriBuilder} instance using a supplied value.
*
* In case a {@code null} template name or value is entered a {@link IllegalArgumentException} is thrown.
*
* @param name name of the URI template.
* @param value value to be used to resolve the template.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the resolved template name or value is {@code null}.
* @since 2.0
*/
public abstract UriBuilder resolveTemplate(String name, Object value);
/**
* Resolve a URI template with a given {@code name} in this {@code UriBuilder} instance using a supplied value.
*
* In case a {@code null} template name or value is entered a {@link IllegalArgumentException} is thrown.
*
* @param name name of the URI template.
* @param value value to be used to resolve the template.
* @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in template values will be encoded if
* the template is placed in the URI path component, otherwise the slash characters will not be encoded in path
* templates.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the resolved template name or value is {@code null}.
* @since 2.0
*/
public abstract UriBuilder resolveTemplate(String name, Object value, boolean encodeSlashInPath);
/**
* Resolve a URI template with a given {@code name} in this {@code UriBuilder} instance using a supplied encoded value.
*
* A template with a matching name will be replaced by the supplied value. Value is converted to {@code String} using
* its {@code toString()} method and is then encoded to match the rules of the URI component to which they pertain. All
* % characters in the stringified values that are not followed by two hexadecimal numbers will be encoded.
*
* In case a {@code null} template name or encoded value is entered a {@link IllegalArgumentException} is thrown.
*
* @param name name of the URI template.
* @param value encoded value to be used to resolve the template.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the resolved template name or encoded value is {@code null}.
* @since 2.0
*/
public abstract UriBuilder resolveTemplateFromEncoded(String name, Object value);
/**
* Resolve one or more URI templates in this {@code UriBuilder} instance using supplied name-value pairs.
*
* A call to the method with an empty parameter map is ignored.
*
* @param templateValues a map of URI template names and their values.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the name-value map or any of the names or values in the map is {@code null}.
* @since 2.0
*/
public abstract UriBuilder resolveTemplates(Map templateValues);
/**
* Resolve one or more URI templates in this {@code UriBuilder} instance using supplied name-value pairs.
*
* A call to the method with an empty parameter map is ignored.
*
* @param templateValues a map of URI template names and their values.
* @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in template values will be encoded if
* the template is placed in the URI path component, otherwise the slash characters will not be encoded in path
* templates.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the name-value map or any of the names or values in the map is {@code null}.
* @since 2.0
*/
public abstract UriBuilder resolveTemplates(Map templateValues, boolean encodeSlashInPath)
throws IllegalArgumentException;
/**
* Resolve one or more URI templates in this {@code UriBuilder} instance using supplied name-value pairs.
*
* All templates with their name matching one of the keys in the supplied map will be replaced by the value in the
* supplied map. Values are converted to {@code String} using their {@code toString()} method and are then encoded to
* match the rules of the URI component to which they pertain. All % characters in the stringified values that are not
* followed by two hexadecimal numbers will be encoded.
*
* A call to the method with an empty parameter map is ignored.
*
* @param templateValues a map of URI template names and their values.
* @return the updated UriBuilder.
* @throws IllegalArgumentException if the name-value map or any of the names or values in the map is {@code null}.
* @since 2.0
*/
public abstract UriBuilder resolveTemplatesFromEncoded(Map templateValues);
/**
* Build a URI.
*
* Any URI template parameters will be replaced by the value in the supplied map. Values are converted to {@code String}
* using their {@code toString()} method and are then encoded to match the rules of the URI component to which they
* pertain. All {@code '%'} characters in the stringified values will be encoded. The state of the builder is
* unaffected; this method may be called multiple times on the same builder instance.
*
* NOTE: By default all {@code '/'} characters in the stringified values will be encoded in path templates, i.e. the
* result is identical to invoking {@link #buildFromMap(java.util.Map, boolean) buildFromMap(valueMap, true)}. To
* override this behavior use {@code buildFromMap(valueMap, false)} instead.
*
*
* @param values a map of URI template parameter names and values.
* @return the URI built from the UriBuilder.
* @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a template
* parameter value is {@code null}.
* @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder.
* @see #buildFromMap(java.util.Map, boolean)
* @see #buildFromEncodedMap(java.util.Map)
*/
public abstract URI buildFromMap(Map values);
/**
* Build a URI.
*
* Any URI template parameters will be replaced by the value in the supplied map. Values are converted to {@code String}
* using their {@code toString()} method and are then encoded to match the rules of the URI component to which they
* pertain. All {@code '%'} characters in the stringified values will be encoded. The state of the builder is
* unaffected; this method may be called multiple times on the same builder instance.
*
* The {@code encodeSlashInPath} parameter may be used to override the default encoding of {@code '/'} characters in the
* stringified template values in cases when the template is part of the URI path component when using the
* {@link #buildFromMap(java.util.Map)} method. If the {@code encodeSlashInPath} parameter is set to {@code true}
* (default), the slash ({@code '/'}) characters in parameter values will be encoded if the template is placed in the
* URI path component. If set to {@code false} the default encoding behavior is overridden an slash characters in
* template values will not be encoded when used to substitute path templates.
*
*
* @param values a map of URI template parameter names and values.
* @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in parameter values will be encoded if
* the template is placed in the URI path component, otherwise the slash characters will not be encoded in path
* templates.
* @return the URI built from the UriBuilder.
* @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a template
* parameter value is {@code null}.
* @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder.
* @see #buildFromMap(java.util.Map)
* @see #buildFromEncodedMap(java.util.Map)
*/
public abstract URI buildFromMap(Map values, boolean encodeSlashInPath)
throws IllegalArgumentException, UriBuilderException;
/**
* Build a URI.
*
* Any URI template parameters will be replaced by the value in the supplied map. Values are converted to {@code String}
* using their {@code toString()} method and are then encoded to match the rules of the URI component to which they
* pertain. All % characters in the stringified values that are not followed by two hexadecimal numbers will be encoded.
* The state of the builder is unaffected; this method may be called multiple times on the same builder instance.
*
* @param values a map of URI template parameter names and values.
* @return the URI built from the UriBuilder.
* @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a template
* parameter value is {@code null}.
* @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder.
* @see #buildFromMap(java.util.Map)
* @see #buildFromMap(java.util.Map, boolean)
* @since 2.0
*/
public abstract URI buildFromEncodedMap(Map values)
throws IllegalArgumentException, UriBuilderException;
/**
* Build a URI, using the supplied values in order to replace any URI template parameters. Values are converted to
* {@code String} using their {@code toString()} method and are then encoded to match the rules of the URI component to
* which they pertain. All '%' characters in the stringified values will be encoded. The state of the builder is
* unaffected; this method may be called multiple times on the same builder instance.
*
* All instances of the same template parameter will be replaced by the same value that corresponds to the position of
* the first instance of the template parameter. e.g. the template "{a}/{b}/{a}" with values {"x", "y", "z"} will result
* in the the URI "x/y/x", not "x/y/z".
*
*
* NOTE: By default all {@code '/'} characters in the stringified values will be encoded in path templates, i.e. the
* result is identical to invoking {@link #build(Object[], boolean)} build(values, true)}. To override this behavior use
* {@code build(values, false)} instead.
*
*
* @param values a list of URI template parameter values.
* @return the URI built from the UriBuilder.
* @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a value is
* {@code null}.
* @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder.
* @see #build(Object[], boolean)
* @see #buildFromEncoded(Object...)
*/
public abstract URI build(Object... values)
throws IllegalArgumentException, UriBuilderException;
/**
* Build a URI, using the supplied values in order to replace any URI template parameters. Values are converted to
* {@code String} using their {@code toString()} method and are then encoded to match the rules of the URI component to
* which they pertain. All '%' characters in the stringified values will be encoded. The state of the builder is
* unaffected; this method may be called multiple times on the same builder instance.
*
* All instances of the same template parameter will be replaced by the same value that corresponds to the position of
* the first instance of the template parameter. e.g. the template "{a}/{b}/{a}" with values {"x", "y", "z"} will result
* in the the URI "x/y/x", not "x/y/z".
*
*
* The {@code encodeSlashInPath} parameter may be used to override the default encoding of {@code '/'} characters in the
* stringified template values in cases when the template is part of the URI path component when using the
* {@link #build(Object[])} method. If the {@code encodeSlashInPath} parameter is set to {@code true} (default), the
* slash ({@code '/'}) characters in parameter values will be encoded if the template is placed in the URI path
* component. If set to {@code false} the default encoding behavior is overridden an slash characters in template values
* will not be encoded when used to substitute path templates.
*
*
* @param values a list of URI template parameter values.
* @param encodeSlashInPath if {@code true}, the slash ({@code '/'}) characters in parameter values will be encoded if
* the template is placed in the URI path component, otherwise the slash characters will not be encoded in path
* templates.
* @return the URI built from the UriBuilder.
* @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a value is
* {@code null}.
* @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder.
* @see #build(Object[])
* @see #buildFromEncoded(Object...)
* @since 2.0
*/
public abstract URI build(Object[] values, boolean encodeSlashInPath)
throws IllegalArgumentException, UriBuilderException;
/**
* Build a URI. Any URI templates parameters will be replaced with the supplied values in order. Values are converted to
* {@code String} using their {@code toString()} method and are then encoded to match the rules of the URI component to
* which they pertain. All % characters in the stringified values that are not followed by two hexadecimal numbers will
* be encoded. The state of the builder is unaffected; this method may be called multiple times on the same builder
* instance.
*
* All instances of the same template parameter will be replaced by the same value that corresponds to the position of
* the first instance of the template parameter. e.g. the template "{a}/{b}/{a}" with values {"x", "y", "z"} will result
* in the the URI "x/y/x", not "x/y/z".
*
* @param values a list of URI template parameter values.
* @return the URI built from the UriBuilder.
* @throws IllegalArgumentException if there are any URI template parameters without a supplied value, or if a value is
* {@code null}.
* @throws UriBuilderException if a URI cannot be constructed based on the current state of the builder.
* @see #build(Object[])
* @see #build(Object[], boolean)
*/
public abstract URI buildFromEncoded(Object... values)
throws IllegalArgumentException, UriBuilderException;
/**
* Get the URI template string represented by this URI builder.
*
* @return the URI template string for this URI builder.
* @since 2.0
*/
public abstract String toTemplate();
}