- Type Parameters:
T - the type of mapped values
public class PathTrie<T>
extends Object
Stores URL path string and ID mappings for a longest match retrieval. The
mappings are configured with addEntry() method, while the idOf() method
performs the best match ID retrieval. A configured path is considered "best"
when it has the longest path prefix with the path presented for the idOf()
method.
An application ID associated with path "/" or "/*" is a default path.
If a path presented to idOf() doesn't match with anything else, then an
application ID associated with default path is returned.
Note about URL mappings:
1. Trailing "/" in a configured path denotes (as you might expect) a
sub-path. Any matching URL must be a "longer" match to be considered.
For example, consider a mapping "/foo/ -> 2". Now, an idOf("foo/bar/blah"),
idOf("/foo/") will return a match==2, but idOf("/foo") would not.
2. Note that trailing "/" and "/*" are equivalent.
3. A configured path that does not end with "/" or "/*" must be matched
exactly. For example, a mapping "/foo/bar -> 2" will only match with
path "/foo/bar", but not with "/foo/bar/" nor "/foo/bar/baz".
Implementation notes:
- Paths are stored in a tree structure to facilitate longest matching
prefix searches.
- Each node represents an individual name component in a path. Each leaf
node in a tree is guaranteed to have an ID configured as a value. This
guarantee does not hold for intermediate nodes. An intermediate node may
or may not contain a configured ID value. Only nodes that have an ID
configured will be considered being part of a successful longest-prefix
match. For example:
Mappings "/foo/bar/A -> 1" and "foo/bar/B -> 2" will result in a
following, where intermediate nodes "foo" and "bar" do not have an
associated application id.
[root]
|
foo
|
bar
/ \
A(1) B(2)
- To differentiate between sub-path matching vs. exact path matching, any
sub-path mappings are stored in a special node "/" under the relevant name
node. For example, consider mappings:
addEntry("/foo/bar", 1);
addEntry("/foo/bar/", 2);
This would result in a following tree:
[root]
|
"foo"
|
"bar" (= 1) <- matches "/foo/bar" only
|
"/" (= 2) <- matches any sub-path of "/foo/bar/..."