public class PathTemplate
Represents a path template.
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.
Static Fields
HOSTNAME_VAR
public static final String HOSTNAME_VAR
A constant identifying the special variable used for endpoint bindings in the result of #matchFromFullName(String). It may also contain protocol string, if its provided in the input.
Type | Description |
String |
Static Methods
create(String template)
public static PathTemplate create(String template)
Creates a path template from a string. The string must satisfy the syntax of path templates of the API platform; see HttpRule's proto source.
Name | Description |
template | String |
Type | Description |
PathTemplate |
createWithoutUrlEncoding(String template)
public static PathTemplate createWithoutUrlEncoding(String template)
Creates a path template from a string. The string must satisfy the syntax of path templates of the API platform; see HttpRule's proto source. Url encoding of template variables is disabled.
Name | Description |
template | String |
Type | Description |
PathTemplate |
Methods
decode(String path)
public List<String> decode(String path)
Matches the template into a list of positional values. The template must not be build from named bindings, but only contain wildcards. For each wildcard in the template, a value is returned at corresponding position in the list.
Name | Description |
path | String |
Type | Description |
List<String> |
encode(String[] values)
public String encode(String[] values)
Instantiates the template from the given positional parameters. The template must not be build from named bindings, but only contain wildcards. Each parameter position corresponds to a wildcard of the according position in the template.
Name | Description |
values | String[] |
Type | Description |
String |
endsWithCustomVerb()
public boolean endsWithCustomVerb()
Returns true of this template ends with a custom verb.
Type | Description |
boolean |
endsWithLiteral()
public boolean endsWithLiteral()
Returns true of this template ends with a literal.
Type | Description |
boolean |
equals(Object obj)
public boolean equals(Object obj)
Name | Description |
obj | Object |
Type | Description |
boolean |
hashCode()
public int hashCode()
Type | Description |
int |
instantiate(String[] keysAndValues)
public String instantiate(String[] keysAndValues)
Shortcut for #instantiate(Map) with a vararg parameter for keys and values.
Name | Description |
keysAndValues | String[] |
Type | Description |
String |
instantiate(Map<String,String> values)
public String instantiate(Map<String,String> values)
Instantiate the template based on the given variable assignment. Performs proper URL escaping of variable assignments.
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.
Name | Description |
values | Map<String,String> |
Type | Description |
String |
instantiatePartial(Map<String,String> values)
public String instantiatePartial(Map<String,String> values)
Same like #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.
Name | Description |
values | Map<String,String> |
Type | Description |
String |
match(String path)
public Map<String,String> match(String path)
Matches the path, returning a map from variable names to matched values. All matched values will be properly unescaped using URL encoding rules. If the path does not match the template, null is returned.
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 method).
Name | Description |
path | String |
Type | Description |
Map<String,String> |
matchFromFullName(String path)
public 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. Example:
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);
Name | Description |
path | String |
Type | Description |
Map<String,String> |
matches(String path)
public boolean matches(String path)
Returns true if the template matches the path.
Name | Description |
path | String |
Type | Description |
boolean |
parentTemplate()
public PathTemplate parentTemplate()
Returns a template for the parent of this template.
Type | Description |
PathTemplate |
parse(String path)
public TemplatedResourceName parse(String path)
Creates a resource name from this template and a path.
Name | Description |
path | String |
Type | Description |
TemplatedResourceName |
singleVar()
public String singleVar()
Returns the name of a singleton variable used by this template. If the template does not contain a single variable, returns null.
Type | Description |
String |
subTemplate(String varName)
public PathTemplate subTemplate(String varName)
Returns a path template for the sub-path of the given variable. Example:
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 ('*').
Name | Description |
varName | String |
Type | Description |
PathTemplate |
toRawString()
public String toRawString()
Returns a raw version of the template as a string. This renders the template in its internal, normalized form.
Type | Description |
String |
toString()
public String toString()
Returns a pretty version of the template as a string.
Type | Description |
String |
validate(String path, String exceptionMessagePrefix)
public void validate(String path, String exceptionMessagePrefix)
Throws a ValidationException if the template doesn't match the path. The exceptionMessagePrefix parameter will be prepended to the ValidationException message.
Name | Description |
path | String |
exceptionMessagePrefix | String |
validatedMatch(String path, String exceptionMessagePrefix)
public Map<String,String> validatedMatch(String path, String exceptionMessagePrefix)
Matches the path, returning a map from variable names to matched values. All matched values will be properly unescaped using URL encoding rules. If the path does not match the template, throws a ValidationException. The exceptionMessagePrefix parameter will be prepended to the ValidationException message.
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 method).
Name | Description |
path | String |
exceptionMessagePrefix | String |
Type | Description |
Map<String,String> |
vars()
public Set<String> vars()
Returns the set of variable names used in the template.
Type | Description |
Set<String> |
withoutVars()
public PathTemplate withoutVars()
Returns a template where all variable bindings have been replaced by wildcards, but which is equivalent regards matching to this one.
Type | Description |
PathTemplate |