Class renaming for content_negotiation

Splitted SERVER_CONTENT_NEGOTIATION in 4 differents classes for each kind of negotiation
Changed to use ITERABLE over LIST for supported variants arguments
Factorized some code for http parameter parsing such as q=1.0;note="blabla"  and so on
Integrated within EWF
This commit is contained in:
2013-10-18 16:18:22 +02:00
parent d376f99832
commit 88e6837222
25 changed files with 938 additions and 716 deletions
@@ -1,6 +1,6 @@
note
description: "[
{HTTP_ACCEPT_LANGUAGE_PARSER} is encharge to parse language tags defined as follow:
{HTTP_ACCEPT_LANGUAGE_UTILITIES} is in charge to parse language tags defined as follow:
Accept-Language = "Accept-Language" ":"
1#( language-l_range [ ";" "q" "=" qvalue ] )
@@ -15,13 +15,10 @@ note
EIS: "name=Accept-Language", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4", "protocol=uri"
class
HTTP_ACCEPT_LANGUAGE_PARSER
HTTP_ACCEPT_LANGUAGE_UTILITIES
inherit
HTTP_HEADER_PARSER
REFACTORING_HELPER
HTTP_HEADER_UTILITIES
feature -- Parser
@@ -68,29 +65,22 @@ feature -- Parser
Result := quality_from_list (a_language, accept_language_list (a_ranges))
end
best_match (a_supported: LIST [READABLE_STRING_8]; a_header_value: READABLE_STRING_8): READABLE_STRING_8
best_match (a_supported: ITERABLE [READABLE_STRING_8]; a_header_value: READABLE_STRING_8): READABLE_STRING_8
-- Choose the `parse_language' with the highest fitness score and quality ('q') from a list of candidates.
local
l_header_results: LIST [HTTP_ACCEPT_LANGUAGE]
l_weighted_matches: LIST [FITNESS_AND_QUALITY]
l_res: LIST [READABLE_STRING_8]
p_res: HTTP_ACCEPT_LANGUAGE
l_fitness_and_quality, l_first_one: detachable FITNESS_AND_QUALITY
s: READABLE_STRING_8
do
l_header_results := accept_language_list (a_header_value)
--| weighted matches
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (a_supported.count)
from
a_supported.start
until
a_supported.after
loop
l_fitness_and_quality := fitness_and_quality_from_list (a_supported.item_for_iteration, l_header_results)
l_fitness_and_quality.set_entity (entity_value (a_supported.item_for_iteration))
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (0)
across a_supported as ic loop
l_fitness_and_quality := fitness_and_quality_from_list (ic.item, l_header_results)
l_fitness_and_quality.set_entity (entity_value (ic.item))
l_weighted_matches.force (l_fitness_and_quality)
a_supported.forth
end
--| Keep only top quality+fitness types
@@ -177,7 +167,6 @@ feature {NONE} -- Implementation
l_target: HTTP_ACCEPT_LANGUAGE
l_target_type: READABLE_STRING_8
l_range: HTTP_ACCEPT_LANGUAGE
l_keys: LIST [READABLE_STRING_8]
l_param_matches: INTEGER
l_element: detachable READABLE_STRING_8
l_fitness: INTEGER
@@ -201,23 +190,21 @@ feature {NONE} -- Implementation
or l_target_type.same_string ("*")
)
then
from
l_param_matches := 0
l_keys := l_target.keys
l_keys.start
until
l_keys.after
loop
l_element := l_keys.item_for_iteration
if
not l_element.same_string ("q") and then
l_range.has_key (l_element) and then
(attached l_target.item (l_element) as t_item and attached l_range.item (l_element) as r_item) and then
t_item.same_string (r_item)
then
l_param_matches := l_param_matches + 1
l_param_matches := 0
if attached l_target.parameters as l_target_parameters then
across
l_target_parameters as ic
loop
l_element := ic.key
if
not l_element.same_string ("q") and then
l_range.has_parameter (l_element) and then
(attached ic.item as t_item and attached l_range.parameter (l_element) as r_item) and then
t_item.same_string (r_item)
then
l_param_matches := l_param_matches + 1
end
end
l_keys.forth
end
if l_range_type.same_string (l_target_type) then
l_fitness := 100
@@ -239,7 +226,7 @@ feature {NONE} -- Implementation
l_fitness := l_fitness + l_param_matches
if l_fitness > l_best_fitness then
l_best_fitness := l_fitness
l_element := l_range.item ("q")
l_element := l_range.parameter ("q")
if l_element /= Void then
l_best_fit_q := l_element.to_real_64.min (l_target_q)
else
@@ -1,6 +1,6 @@
note
description: "[
{HTTP_ACCEPT_MEDIA_TYPE_PARSER}. is encharge to parse Accept request-header field defined as follow:
{HTTP_ACCEPT_MEDIA_TYPE_UTILITIES}. is encharge to parse Accept request-header field defined as follow:
Accept = "Accept" ":"
#( media-range [ accept-params ] )
@@ -20,13 +20,10 @@
EIS: "name=Accept", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1", "protocol=uri"
class
HTTP_ACCEPT_MEDIA_TYPE_PARSER
HTTP_ACCEPT_MEDIA_TYPE_UTILITIES
inherit
HTTP_HEADER_PARSER
REFACTORING_HELPER
HTTP_HEADER_UTILITIES
feature -- Parser
@@ -81,7 +78,7 @@ feature -- Parser
Result := quality_from_list (a_mime_type, res)
end
best_match (supported: LIST [READABLE_STRING_8]; header: READABLE_STRING_8): READABLE_STRING_8
best_match (supported: ITERABLE [READABLE_STRING_8]; header: READABLE_STRING_8): READABLE_STRING_8
-- Choose the mime-type with the highest fitness score and quality ('q') from a list of candidates.
local
l_header_results: LIST [HTTP_MEDIA_TYPE]
@@ -105,17 +102,12 @@ feature -- Parser
l_res.forth
end
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (supported.count)
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} weighted_matches.make (0)
from
supported.start
until
supported.after
loop
fitness_and_quality := fitness_and_quality_from_list (supported.item_for_iteration, l_header_results)
fitness_and_quality.set_entity (entity_value (supported.item_for_iteration))
across supported as ic loop
fitness_and_quality := fitness_and_quality_from_list (ic.item, l_header_results)
fitness_and_quality.set_entity (entity_value (ic.item))
weighted_matches.force (fitness_and_quality)
supported.forth
end
--| Keep only top quality+fitness types
@@ -236,13 +228,9 @@ feature {NONE} -- Implementation
)
then
if attached target.parameters as l_keys then
from
param_matches := 0
l_keys.start
until
l_keys.after
loop
element := l_keys.key_for_iteration
param_matches := 0
across l_keys as ic loop
element := ic.key
if
not element.same_string ("q") and then
range.has_parameter (element) and then
@@ -251,7 +239,6 @@ feature {NONE} -- Implementation
then
param_matches := param_matches + 1
end
l_keys.forth
end
end
if l_range_type.same_string (l_target_type) then
@@ -9,56 +9,34 @@ note
EIS: "name=Encoding", "src=http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3", "protocol=uri"
class
HTTP_ANY_ACCEPT_HEADER_PARSER
HTTP_ANY_ACCEPT_HEADER_UTILITIES
inherit
HTTP_HEADER_PARSER
HTTP_HEADER_UTILITIES
feature -- Parser
header (a_header: READABLE_STRING_8): HTTP_ANY_ACCEPT_HEADER
header (a_header: READABLE_STRING_8): HTTP_ANY_ACCEPT
-- Parses `a_header' charset/encoding into its component parts.
-- For example, the charset 'iso-8889-5' would get parsed
-- into:
-- ('iso-8889-5', {'q':'1.0'})
local
l_parts: LIST [READABLE_STRING_8]
sub_parts: LIST [READABLE_STRING_8]
p: READABLE_STRING_8
i: INTEGER
l_header: READABLE_STRING_8
do
create Result.make
l_parts := a_header.split (';')
if l_parts.count = 1 then
Result.put ("1.0", "q")
else
from
i := 1
until
i > l_parts.count
loop
p := l_parts [i]
sub_parts := p.split ('=')
if sub_parts.count = 2 then
Result.put (trim (sub_parts [2]), trim (sub_parts [1]))
end
i := i + 1
end
create Result.make_from_string (a_header)
if Result.parameter ("q") = Void then
Result.put_parameter ("1.0", "q")
end
l_header := trim (l_parts [1])
Result.set_field (trim (l_header))
end
quality (a_field: READABLE_STRING_8; a_commons: READABLE_STRING_8): REAL_64
quality (a_field: READABLE_STRING_8; a_header: READABLE_STRING_8): REAL_64
-- Returns the quality 'q' of a charset/encoding when compared against the
-- a list of charsets/encodings/
local
l_commons: LIST [READABLE_STRING_8]
res: ARRAYED_LIST [HTTP_ANY_ACCEPT_HEADER]
p_res: HTTP_ANY_ACCEPT_HEADER
res: ARRAYED_LIST [HTTP_ANY_ACCEPT]
p_res: HTTP_ANY_ACCEPT
do
l_commons := a_commons.split (',')
l_commons := a_header.split (',')
from
create res.make (10)
l_commons.start
@@ -72,17 +50,17 @@ feature -- Parser
Result := quality_from_list (a_field, res)
end
best_match (a_supported: LIST [READABLE_STRING_8]; a_header: READABLE_STRING_8): READABLE_STRING_8
best_match (a_supported: ITERABLE [READABLE_STRING_8]; a_header: READABLE_STRING_8): READABLE_STRING_8
-- Choose the accept with the highest fitness score and quality ('q') from a list of candidates.
local
l_header_results: LIST [HTTP_ANY_ACCEPT_HEADER]
l_header_results: LIST [HTTP_ANY_ACCEPT]
l_weighted_matches: LIST [FITNESS_AND_QUALITY]
l_res: LIST [READABLE_STRING_8]
p_res: HTTP_ANY_ACCEPT_HEADER
p_res: HTTP_ANY_ACCEPT
l_fitness_and_quality, l_first_one: detachable FITNESS_AND_QUALITY
do
l_res := a_header.split (',')
create {ARRAYED_LIST [HTTP_ANY_ACCEPT_HEADER]} l_header_results.make (l_res.count)
create {ARRAYED_LIST [HTTP_ANY_ACCEPT]} l_header_results.make (l_res.count)
from
l_res.start
until
@@ -92,16 +70,11 @@ feature -- Parser
l_header_results.force (p_res)
l_res.forth
end
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (a_supported.count)
from
a_supported.start
until
a_supported.after
loop
l_fitness_and_quality := fitness_and_quality_from_list (a_supported.item_for_iteration, l_header_results)
l_fitness_and_quality.set_entity (entity_value (a_supported.item_for_iteration))
create {ARRAYED_LIST [FITNESS_AND_QUALITY]} l_weighted_matches.make (0)
across a_supported as ic loop
l_fitness_and_quality := fitness_and_quality_from_list (ic.item, l_header_results)
l_fitness_and_quality.set_entity (entity_value (ic.item))
l_weighted_matches.force (l_fitness_and_quality)
a_supported.forth
end
--| Keep only top quality+fitness types
@@ -150,7 +123,7 @@ feature -- Parser
until
l_header_results.after or l_fitness_and_quality /= Void
loop
if attached l_header_results.item.field as l_field then
if attached l_header_results.item.value as l_field then
from
l_weighted_matches.start
until
@@ -184,7 +157,7 @@ feature -- Parser
feature {NONE} -- Implementation
fitness_and_quality_from_list (a_field: READABLE_STRING_8; a_parsed_charsets: LIST [HTTP_ANY_ACCEPT_HEADER]): FITNESS_AND_QUALITY
fitness_and_quality_from_list (a_field: READABLE_STRING_8; a_parsed_charsets: LIST [HTTP_ANY_ACCEPT]): FITNESS_AND_QUALITY
-- Find the best match for a given charset/encoding against a list of charsets/encodings
-- that have already been parsed by parse_common. Returns a
-- tuple of the fitness value and the value of the 'q' quality parameter of
@@ -194,15 +167,15 @@ feature {NONE} -- Implementation
best_fitness: INTEGER
target_q: REAL_64
best_fit_q: REAL_64
target: HTTP_ANY_ACCEPT_HEADER
range: HTTP_ANY_ACCEPT_HEADER
target: HTTP_ANY_ACCEPT
range: HTTP_ANY_ACCEPT
element: detachable READABLE_STRING_8
l_fitness: INTEGER
do
best_fitness := -1
best_fit_q := 0.0
target := header (a_field)
if attached target.item ("q") as q and then q.is_double then
if attached target.parameter ("q") as q and then q.is_double then
target_q := q.to_double
if target_q < 0.0 then
target_q := 0.0
@@ -212,14 +185,14 @@ feature {NONE} -- Implementation
else
target_q := 1.0
end
if attached target.field as l_target_field then
if attached target.value as l_target_field then
from
a_parsed_charsets.start
until
a_parsed_charsets.after
loop
range := a_parsed_charsets.item_for_iteration
if attached range.field as l_range_common then
if attached range.value as l_range_common then
if l_target_field.same_string (l_range_common) or l_target_field.same_string ("*") or l_range_common.same_string ("*") then
if l_range_common.same_string (l_target_field) then
l_fitness := 100
@@ -228,7 +201,7 @@ feature {NONE} -- Implementation
end
if l_fitness > best_fitness then
best_fitness := l_fitness
element := range.item ("q")
element := range.parameter ("q")
if element /= Void then
best_fit_q := element.to_double.min (target_q)
else
@@ -243,7 +216,7 @@ feature {NONE} -- Implementation
create Result.make (best_fitness, best_fit_q)
end
quality_from_list (a_field: READABLE_STRING_8; a_parsed_common: LIST [HTTP_ANY_ACCEPT_HEADER]): REAL_64
quality_from_list (a_field: READABLE_STRING_8; a_parsed_common: LIST [HTTP_ANY_ACCEPT]): REAL_64
-- Find the best match for a given charset/encoding against a list of charsets/encodings that
-- have already been parsed by parse_charsets(). Returns the 'q' quality
-- parameter of the best match, 0 if no match was found. This function
@@ -252,7 +225,6 @@ feature {NONE} -- Implementation
Result := fitness_and_quality_from_list (a_field, a_parsed_common).quality
end
note
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
@@ -1,11 +1,14 @@
note
description: "Summary description for {HTTP_HEADER_PARSER}."
description: "Summary description for {HTTP_HEADER_UTILITIES}."
author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
HTTP_HEADER_PARSER
HTTP_HEADER_UTILITIES
inherit
REFACTORING_HELPER
feature {NONE} -- Helpers
@@ -16,13 +19,13 @@ feature {NONE} -- Helpers
do
p := a_str.index_of (';', 1)
if p > 0 then
Result := trim (a_str.substring (1, p - 1))
Result := trimmed_string (a_str.substring (1, p - 1))
else
Result := trim (a_str.string)
Result := trimmed_string (a_str.string)
end
end
trim (a_string: READABLE_STRING_8): STRING_8
trimmed_string (a_string: READABLE_STRING_8): STRING_8
-- trim whitespace from the beginning and end of a string
-- `a_string'
require