@BetaApi public class PathTemplate extends Object
Templates use the syntax of the API platform; see the protobuf of HttpRule for
details. A template consists of a sequence of literals, wildcards, and variable bindings,
where each binding can have a sub-path. A string representation can be parsed into an
instance of PathTemplate
, which can then be used to perform matching and instantiation.
Matching and instantiation deals with unescaping and escaping using URL encoding rules. For
example, if a template variable for a single segment is instantiated with a string like
"a/b"
, the slash will be escaped to "%2f"
. (Note that slash will not be escaped
for a multiple-segment variable, but other characters will). The literals in the template
itself are not escaped automatically, and must be already URL encoded.
Here is an example for a template using simple variables:
PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}"); assert template.matches("v2/shelves") == false; Map<String, String> values = template.match("v1/shelves/s1/books/b1"); Map<String, String> expectedValues = new HashMap<>(); expectedValues.put("shelf", "s1"); expectedValues.put("book", "b1"); assert values.equals(expectedValues); assert template.instantiate(values).equals("v1/shelves/s1/books/b1");Templates can use variables which match sub-paths. Example:
PathTemplate template = PathTemplate.create("v1/{name=shelves/*/books/*}"}; assert template.match("v1/shelves/books/b1") == null; Map<String, String> expectedValues = new HashMap<>(); expectedValues.put("name", "shelves/s1/books/b1"); assert template.match("v1/shelves/s1/books/b1").equals(expectedValues);Path templates can also be used with only wildcards. Each wildcard is associated with an implicit variable
$n
, where n is the zero-based position of the
wildcard. Example:
PathTemplate template = PathTemplate.create("shelves/*/books/*"}; assert template.match("shelves/books/b1") == null; Map<String, String> values = template.match("v1/shelves/s1/books/b1"); Map<String, String> expectedValues = new HashMap<>(); expectedValues.put("$0", s1"); expectedValues.put("$1", "b1"); assert values.equals(expectedValues);Paths input to matching can use URL relative syntax to indicate a host name by prefixing the host name, as in
//somewhere.io/some/path
. The host name is matched into the special
variable HOSTNAME_VAR
. Patterns are agnostic about host names, and the same pattern
can be used for URL relative syntax and simple path syntax:
PathTemplate template = PathTemplate.create("shelves/*"}; Map<String, String> expectedValues = new HashMap<>(); expectedValues.put(PathTemplate.HOSTNAME_VAR, "//somewhere.io"); expectedValues.put("$0", s1"); assert template.match("//somewhere.io/shelves/s1").equals(expectedValues); expectedValues.clear(); expectedValues.put("$0", s1"); assert template.match("shelves/s1").equals(expectedValues);For the representation of a resource name see
TemplatedResourceName
, which is based
on path templates.Modifier and Type | Field and Description |
---|---|
static String |
HOSTNAME_VAR
A constant identifying the special variable used for endpoint bindings in
the result of
matchFromFullName(String) . |
Modifier and Type | Method and Description |
---|---|
static PathTemplate |
create(String template)
Creates a path template from a string.
|
static PathTemplate |
createWithoutUrlEncoding(String template)
Creates a path template from a string.
|
List<String> |
decode(String path)
Matches the template into a list of positional values.
|
String |
encode(String... values)
Instantiates the template from the given positional parameters.
|
boolean |
endsWithCustomVerb()
Returns true of this template ends with a custom verb.
|
boolean |
endsWithLiteral()
Returns true of this template ends with a literal.
|
boolean |
equals(Object obj) |
int |
hashCode() |
String |
instantiate(Map<String,String> values)
Instantiate the template based on the given variable assignment.
|
String |
instantiate(String... keysAndValues)
Shortcut for
instantiate(Map) with a vararg parameter for keys and values. |
String |
instantiatePartial(Map<String,String> values)
Same like
instantiate(Map) but allows for unbound variables, which are substituted
using their original syntax. |
Map<String,String> |
match(String path)
Matches the path, returning a map from variable names to matched values.
|
boolean |
matches(String path)
Returns true if the template matches the path.
|
Map<String,String> |
matchFromFullName(String path)
Matches the path, where the first segment is interpreted as the host name regardless of whether
it starts with '//' or not.
|
PathTemplate |
parentTemplate()
Returns a template for the parent of this template.
|
TemplatedResourceName |
parse(String path)
Creates a resource name from this template and a path.
|
String |
singleVar()
Returns the name of a singleton variable used by this template.
|
PathTemplate |
subTemplate(String varName)
Returns a path template for the sub-path of the given variable.
|
String |
toRawString()
Returns a raw version of the template as a string.
|
String |
toString()
Returns a pretty version of the template as a string.
|
void |
validate(String path,
String exceptionMessagePrefix)
Throws a ValidationException if the template doesn't match the path.
|
Map<String,String> |
validatedMatch(String path,
String exceptionMessagePrefix)
Matches the path, returning a map from variable names to matched values.
|
Set<String> |
vars()
Returns the set of variable names used in the template.
|
PathTemplate |
withoutVars()
Returns a template where all variable bindings have been replaced by wildcards, but which is
equivalent regards matching to this one.
|
public static final String HOSTNAME_VAR
matchFromFullName(String)
.public static PathTemplate create(String template)
ValidationException
- if there are errors while parsing the template.public static PathTemplate createWithoutUrlEncoding(String template)
ValidationException
- if there are errors while parsing the template.public PathTemplate parentTemplate()
ValidationException
- if the template has no parent.public PathTemplate withoutVars()
public PathTemplate subTemplate(String varName)
PathTemplate template = PathTemplate.create("v1/{name=shelves/*/books/*}"); assert template.subTemplate("name").toString().equals("shelves/*/books/*");The returned template will never have named variables, but only wildcards, which are dealt with in matching and instantiation using '$n'-variables. See the documentation of
match(String)
and instantiate(Map)
, respectively.
For a variable which has no sub-path, this returns a path template with a single wildcard ('*').
ValidationException
- if the variable does not exist in the template.public boolean endsWithLiteral()
public boolean endsWithCustomVerb()
public TemplatedResourceName parse(String path)
ValidationException
- if the path does not match the template.@Nullable public String singleVar()
public void validate(String path, String exceptionMessagePrefix)
public Map<String,String> validatedMatch(String path, String exceptionMessagePrefix)
If the path starts with '//', the first segment will be interpreted as a host name and
stored in the variable HOSTNAME_VAR
.
See the PathTemplate
class documentation for examples.
For free wildcards in the template, the matching process creates variables named '$n', where 'n' is the wildcard's position in the template (starting at n=0). For example:
PathTemplate template = PathTemplate.create("shelves/*/books/*"); Map<String, String> expectedValues = new HashMap<>(); expectedValues.put("$0", "s1"); expectedValues.put("$1", "b1"); assert template.validatedMatch("shelves/s1/books/b2", "User exception string") .equals(expectedValues); expectedValues.clear(); expectedValues.put(HOSTNAME_VAR, "//somewhere.io"); expectedValues.put("$0", "s1"); expectedValues.put("$1", "b1"); assert template.validatedMatch("//somewhere.io/shelves/s1/books/b2", "User exception string") .equals(expectedValues);All matched values will be properly unescaped using URL encoding rules (so long as URL encoding has not been disabled by the
createWithoutUrlEncoding(java.lang.String)
method).public boolean matches(String path)
@Nullable public Map<String,String> match(String path)
If the path starts with '//', the first segment will be interpreted as a host name and
stored in the variable HOSTNAME_VAR
.
See the PathTemplate
class documentation for examples.
For free wildcards in the template, the matching process creates variables named '$n', where 'n' is the wildcard's position in the template (starting at n=0). For example:
PathTemplate template = PathTemplate.create("shelves/*/books/*"); Map<String, String> expectedValues = new HashMap<>(); expectedValues.put("$0", "s1"); expectedValues.put("$1", "b1"); assert template.match("shelves/s1/books/b2").equals(expectedValues); expectedValues.clear(); expectedValues.put(HOSTNAME_VAR, "//somewhere.io"); expectedValues.put("$0", "s1"); expectedValues.put("$1", "b1"); assert template.match("//somewhere.io/shelves/s1/books/b2").equals(expectedValues);All matched values will be properly unescaped using URL encoding rules (so long as URL encoding has not been disabled by the
createWithoutUrlEncoding(java.lang.String)
method).@Nullable public Map<String,String> matchFromFullName(String path)
Map<String, String> expectedValues = new HashMap<>(); expectedValues.put(HOSTNAME_VAR, "//somewhere.io"); expectedValues.put("name", "shelves/s1"); assert template("{name=shelves/*}").matchFromFullName("somewhere.io/shelves/s1") .equals(expectedValues);
public String instantiate(Map<String,String> values)
Note that free wildcards in the template must have bindings of '$n' variables, where 'n' is
the position of the wildcard (starting at 0). See the documentation of match(String)
for details.
ValidationException
- if a variable occurs in the template without a binding.public String instantiate(String... keysAndValues)
instantiate(Map)
with a vararg parameter for keys and values.public String instantiatePartial(Map<String,String> values)
instantiate(Map)
but allows for unbound variables, which are substituted
using their original syntax. Example: PathTemplate template = PathTemplate.create("v1/shelves/{shelf}/books/{book}"); Map<String, String> partialMap = new HashMap<>(); partialMap.put("shelf", "s1"); assert template.instantiatePartial(partialMap).equals("v1/shelves/s1/books/{book}");The result of this call can be used to create a new template.
public String encode(String... values)
public List<String> decode(String path)
public String toString()
public String toRawString()