@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()