fixing issue with URI TEMPLATE matcher

This commit is contained in:
Jocelyn Fiat
2011-07-22 13:12:03 +02:00
parent 11baeefe1c
commit e1ef4c390e
3 changed files with 132 additions and 57 deletions

View File

@@ -13,6 +13,11 @@ note
class class
URI_TEMPLATE URI_TEMPLATE
inherit
HASHABLE
DEBUG_OUTPUT
create create
make make
@@ -23,17 +28,47 @@ feature {NONE} -- Initialization
template := s template := s
end end
make_with_handler (s: STRING; a_handler: detachable URI_TEMPLATE_HANDLER)
do
make (s)
analyze (a_handler)
end
feature -- Access feature -- Access
template: STRING template: STRING
-- URI string representation -- URI string representation
feature -- Status report
debug_output: STRING
-- String that should be displayed in debugger to represent `Current'.
do
create Result.make_from_string (template)
end
feature -- Access
hash_code: INTEGER
-- Hash code value
do
Result := template.hash_code
end
feature -- Structures
variable_names: LIST [STRING]
do
analyze (Void)
if attached expansion_parts as l_x_parts then
create {ARRAYED_LIST [STRING]} Result.make (l_x_parts.count)
from
l_x_parts.start
until
l_x_parts.after
loop
Result.append (l_x_parts.item.variable_names)
l_x_parts.forth
end
else
create {ARRAYED_LIST [STRING]} Result.make (0)
end
end
path_variable_names: LIST [STRING] path_variable_names: LIST [STRING]
do do
analyze (Void) analyze (Void)
@@ -77,6 +112,7 @@ feature -- Access
feature -- Builder feature -- Builder
string (a_ht: HASH_TABLE [detachable ANY, STRING]): STRING string (a_ht: HASH_TABLE [detachable ANY, STRING]): STRING
-- Expanded template using variable from `a_ht'
local local
tpl: like template tpl: like template
exp: URI_TEMPLATE_EXPRESSION exp: URI_TEMPLATE_EXPRESSION
@@ -109,12 +145,7 @@ feature -- Builder
end end
end end
url_encoder: URL_ENCODER feature -- Match
once
create Result
end
feature -- Analyze
match (a_uri: STRING): detachable URI_TEMPLATE_MATCH_RESULT match (a_uri: STRING): detachable URI_TEMPLATE_MATCH_RESULT
local local
@@ -126,6 +157,7 @@ feature -- Analyze
vn, s,t: STRING vn, s,t: STRING
vv: STRING vv: STRING
l_vars, l_path_vars, l_query_vars: HASH_TABLE [STRING, STRING] l_vars, l_path_vars, l_query_vars: HASH_TABLE [STRING, STRING]
l_uri_count: INTEGER
do do
--| Extract expansion parts "\\{([^\\}]*)\\}" --| Extract expansion parts "\\{([^\\}]*)\\}"
analyze (Void) analyze (Void)
@@ -133,8 +165,12 @@ feature -- Analyze
create l_path_vars.make (l_x_parts.count) create l_path_vars.make (l_x_parts.count)
create l_query_vars.make (l_x_parts.count) create l_query_vars.make (l_x_parts.count)
l_vars := l_path_vars l_vars := l_path_vars
tpl := template
b := True b := True
l_uri_count := a_uri.count
tpl := template
if l_x_parts.is_empty then
b := a_uri.substring (1, tpl.count).same_string (tpl)
else
from from
l_x_parts.start l_x_parts.start
p := 1 p := 1
@@ -153,32 +189,43 @@ feature -- Analyze
p := q + vn.count + 2 p := q + vn.count + 2
end end
--| Check related variable --| Check related variable
if not vn.is_empty then if b and then not vn.is_empty then
if exp.is_query then if exp.is_query then
l_vars := l_query_vars l_vars := l_query_vars
else else
l_vars := l_path_vars l_vars := l_path_vars
end end
if q + l_offset <= l_uri_count then
inspect vn[1] inspect vn[1]
when '?' then when '?' then
import_form_style_parameters_into (a_uri.substring (q + l_offset + 1, a_uri.count), l_vars) import_form_style_parameters_into (a_uri.substring (q + l_offset + 1, l_uri_count), l_vars)
when ';' then when ';' then
import_path_style_parameters_into (a_uri.substring (q + l_offset, a_uri.count), l_vars) import_path_style_parameters_into (a_uri.substring (q + l_offset, l_uri_count), l_vars)
else else
vv := next_path_variable_value (a_uri, q + l_offset) vv := next_path_variable_value (a_uri, q + l_offset)
l_vars.force (vv, vn) l_vars.force (vv, vn)
l_offset := l_offset + vv.count - (vn.count + 2) l_offset := l_offset + vv.count - (vn.count + 2)
end end
else
b := exp.is_query --| query are optional
end
end end
l_x_parts.forth l_x_parts.forth
end end
end
if b then if b then
create Result.make (l_path_vars, l_query_vars) create Result.make (l_path_vars, l_query_vars)
end end
end end
end end
feature {NONE} -- Internal Access
expansion_parts: detachable LIST [URI_TEMPLATE_EXPRESSION]
-- Expansion parts
feature {NONE} -- Implementation
analyze (a_handler: detachable URI_TEMPLATE_HANDLER) analyze (a_handler: detachable URI_TEMPLATE_HANDLER)
local local
l_x_parts: like expansion_parts l_x_parts: like expansion_parts
@@ -233,11 +280,6 @@ feature -- Analyze
end end
end end
feature {NONE} -- Implementation
expansion_parts: detachable LIST [URI_TEMPLATE_EXPRESSION]
-- Expansion parts
import_path_style_parameters_into (a_content: STRING; res: HASH_TABLE [STRING, STRING]) import_path_style_parameters_into (a_content: STRING; res: HASH_TABLE [STRING, STRING])
require require
a_content_attached: a_content /= Void a_content_attached: a_content /= Void
@@ -313,9 +355,9 @@ feature {NONE} -- Implementation
Result := a_uri.substring (a_index, p) Result := a_uri.substring (a_index, p)
end end
comma_separated_variable_names (s: STRING): LIST [STRING] url_encoder: URL_ENCODER
do once
Result := s.split (',') create Result
end end
note note

View File

@@ -8,7 +8,8 @@ class
URI_TEMPLATE_MATCH_RESULT URI_TEMPLATE_MATCH_RESULT
create create
make make,
make_empty
feature {NONE} -- Initialization feature {NONE} -- Initialization
@@ -18,10 +19,27 @@ feature {NONE} -- Initialization
query_variables := q query_variables := q
end end
make_empty
do
make (create {like path_variables}.make (0), create {like query_variables}.make (0))
end
feature -- Access feature -- Access
variable (n: STRING): detachable STRING
-- Value related to variable name `n'
do
Result := query_variables.item (n)
if Result = Void then
Result := path_variables.item (n)
end
end
path_variables: HASH_TABLE [STRING, STRING] path_variables: HASH_TABLE [STRING, STRING]
-- Variables being part of the path segments
query_variables: HASH_TABLE [STRING, STRING] query_variables: HASH_TABLE [STRING, STRING]
-- Variables being part of the query segments (i.e: after the ? )
;note ;note
copyright: "2011-2011, Eiffel Software and others" copyright: "2011-2011, Eiffel Software and others"

View File

@@ -30,8 +30,15 @@ feature -- Test routines
tpl: URI_TEMPLATE tpl: URI_TEMPLATE
do do
create tpl.make ("api/foo/{foo_id}/{?id,extra}") create tpl.make ("api/foo/{foo_id}/{?id,extra}")
uri_template_match (tpl, "api/foo/bar/", <<["foo_id", "bar"]>>, <<>>)
uri_template_match (tpl, "api/foo/bar/?id=123", <<["foo_id", "bar"]>>, <<["id", "123"]>>) uri_template_match (tpl, "api/foo/bar/?id=123", <<["foo_id", "bar"]>>, <<["id", "123"]>>)
uri_template_match (tpl, "api/foo/bar/?id=123&extra=test", <<["foo_id", "bar"]>>, <<["id", "123"], ["extra", "test"]>>) uri_template_match (tpl, "api/foo/bar/?id=123&extra=test", <<["foo_id", "bar"]>>, <<["id", "123"], ["extra", "test"]>>)
uri_template_match (tpl, "api/foo/bar/?id=123&extra=test&one=more", <<["foo_id", "bar"]>>, <<["id", "123"], ["extra", "test"]>>)
uri_template_mismatch (tpl, "")
uri_template_mismatch (tpl, "/")
uri_template_mismatch (tpl, "foo/bar/?id=123")
uri_template_mismatch (tpl, "/api/foo/bar/")
uri_template_mismatch (tpl, "api/foo/bar")
create tpl.make ("weather/{state}/{city}?forecast={day}") create tpl.make ("weather/{state}/{city}?forecast={day}")
uri_template_match (tpl, "weather/California/Goleta?forecast=today", <<["state", "California"], ["city", "Goleta"]>>, <<["day", "today"]>>) uri_template_match (tpl, "weather/California/Goleta?forecast=today", <<["state", "California"], ["city", "Goleta"]>>, <<["day", "today"]>>)
@@ -563,6 +570,14 @@ feature -- Test routines
assert ("query variables matched", matched) assert ("query variables matched", matched)
end end
uri_template_mismatch (a_uri_template: URI_TEMPLATE; a_uri: STRING)
local
l_match: detachable URI_TEMPLATE_MATCH_RESULT
do
l_match := a_uri_template.match (a_uri)
assert ("uri %"" + a_uri + "%" does not match template %"" + a_uri_template.template + "%"", l_match = Void)
end
uri_template_match (a_uri_template: URI_TEMPLATE; a_uri: STRING; path_res: ARRAY [TUPLE [name: STRING; value: STRING]]; query_res: ARRAY [TUPLE [name: STRING; value: STRING]]) uri_template_match (a_uri_template: URI_TEMPLATE; a_uri: STRING; path_res: ARRAY [TUPLE [name: STRING; value: STRING]]; query_res: ARRAY [TUPLE [name: STRING; value: STRING]])
local local
b: BOOLEAN b: BOOLEAN
@@ -584,7 +599,7 @@ feature -- Test routines
assert ("uri matched path variables", b) assert ("uri matched path variables", b)
end end
if attached l_match.query_variables as query_ht then if attached l_match.query_variables as query_ht then
b := query_ht.count = query_res.count b := query_ht.count >= query_res.count
from from
i := query_res.lower i := query_res.lower
until until