diff --git a/library/server/wsf/router/documentation/wsf_router_self_documentation_handler.e b/library/server/wsf/router/documentation/wsf_router_self_documentation_handler.e
new file mode 100644
index 00000000..3d9c844f
--- /dev/null
+++ b/library/server/wsf/router/documentation/wsf_router_self_documentation_handler.e
@@ -0,0 +1,58 @@
+note
+ description: "[
+ Handler based on a STARTS_WITH handler to respond a
+ WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE message
+
+ This is a self documentation for WSF_ROUTER.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WSF_ROUTER_SELF_DOCUMENTATION_HANDLER
+
+inherit
+ WSF_STARTS_WITH_HANDLER
+ redefine
+ on_mapped
+ end
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_router: WSF_ROUTER)
+ do
+ router := a_router
+ end
+
+ router: WSF_ROUTER
+
+ resource: detachable STRING
+
+feature {WSF_ROUTER} -- Mapping
+
+ on_mapped (a_mapping: WSF_ROUTER_MAPPING; a_rqst_methods: detachable WSF_ROUTER_METHODS)
+ -- Callback called when a router map a route to Current handler
+ do
+ if attached {WSF_STARTS_WITH_MAPPING} a_mapping as m then
+ resource := m.uri
+ end
+ end
+
+feature -- Execution
+
+ execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ m: WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE
+ do
+ if attached resource as l_resource then
+ create m.make (req, router, l_resource)
+ else
+ create m.make (req, router, Void)
+ end
+ res.send (m)
+ end
+
+end
diff --git a/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e b/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e
new file mode 100644
index 00000000..d583dd6e
--- /dev/null
+++ b/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e
@@ -0,0 +1,216 @@
+note
+ description: "[
+ Response message to send a self documentation of the WSF_ROUTER
+ This is using in addition WSF_SELF_DOCUMENTED_ROUTER_MAPPING and WSF_SELF_DOCUMENTED_HANDLER
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ WSF_ROUTER_SELF_DOCUMENTATION_MESSAGE
+
+inherit
+ WSF_RESPONSE_MESSAGE
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (req: WSF_REQUEST; a_router: WSF_ROUTER; a_resource: detachable STRING)
+ local
+
+ do
+ request := req
+ router := a_router
+ if attached a_router.base_url as l_base_url then
+ resource := l_base_url.twin
+ else
+ create resource.make_empty
+ end
+ if a_resource /= Void then
+ resource.append (a_resource)
+ end
+ end
+
+ request: WSF_REQUEST
+
+ router: WSF_ROUTER
+
+ resource: STRING_8
+
+feature {WSF_RESPONSE} -- Output
+
+ send_to (res: WSF_RESPONSE)
+ -- Send Current message to `res'
+ --
+ -- This feature should be called via `{WSF_RESPONSE}.send (obj)'
+ -- where `obj' is the current object
+ local
+ h: HTTP_HEADER
+ l_description: STRING_8
+ l_base_url: STRING_8
+ l_api_resource: detachable STRING_8
+ do
+ create h.make
+ h.put_content_type_text_html
+ create l_description.make (1024)
+ l_description.append ("")
+ l_description.append ("
")
+ l_description.append ("Documentation")
+ l_description.append ("[
+
+ ]")
+
+ l_description.append ("")
+
+ l_description.append ("Documentation
%N")
+
+ if attached router.base_url as u then
+ l_base_url := u
+ else
+ create l_base_url.make_empty
+ end
+
+ debug
+ l_description.append ("Meta
")
+ l_description.append ("- PATH_INFO=" + request.path_info + "
")
+ l_description.append ("- QUERY_STRING=" + request.query_string + "
")
+ l_description.append ("- REQUEST_URI=" + request.request_uri + "
")
+ l_description.append ("- SCRIPT_NAME=" + request.script_name + "
")
+ l_description.append ("- HOME=" + request.script_url ("/") + "
")
+ if not l_base_url.is_empty then
+ l_description.append ("- Base URL=" + l_base_url + "
")
+ end
+ l_description.append ("
")
+ end
+
+ if attached request.path_info as l_path then
+ if l_path.starts_with (resource) then
+ l_api_resource := l_path.substring (resource.count + 1, l_path.count)
+ if l_api_resource.is_empty then
+ l_api_resource := Void
+ end
+ end
+ end
+
+ if l_api_resource /= Void then
+ l_description.append ("Index
")
+ if attached router.item_associated_with_resource (l_api_resource, Void) as l_api_item then
+ l_description.append ("Information related to %"" + l_api_resource + "%"
")
+ append_documentation_to (l_description, l_api_item.mapping, l_api_item.request_methods)
+ l_description.append ("
")
+ end
+ else
+ l_description.append ("Router
")
+ across
+ router as c
+ loop
+ append_documentation_to (l_description, c.item.mapping, c.item.request_methods)
+ end
+ l_description.append ("
")
+ end
+
+
+ l_description.append ("%N")
+ l_description.append ("")
+
+ h.put_content_length (l_description.count)
+ h.put_current_date
+ res.set_status_code ({HTTP_STATUS_CODE}.ok)
+ res.put_header_text (h.string)
+ res.put_string (l_description)
+ end
+
+ append_documentation_to (s: STRING_8; m: WSF_ROUTER_MAPPING; meths: detachable WSF_ROUTER_METHODS)
+ local
+ l_url: detachable STRING_8
+ l_base_url: detachable READABLE_STRING_8
+ hdl: WSF_HANDLER
+ do
+ l_base_url := router.base_url
+ if l_base_url = Void then
+ l_base_url := ""
+ end
+
+ l_url := Void
+ s.append ("")
+ s.append ("")
+ s.append ("")
+ s.append (m.associated_resource)
+ s.append ("")
+
+ if attached {WSF_SELF_DOCUMENTED_ROUTER_MAPPING} m as l_doc_mapping then
+ s.append (" " + html_encoder.encoded_string (l_doc_mapping.documentation) + " ")
+ else
+ debug
+ s.append (" " + m.generating_type.out + " ")
+ end
+ end
+ if meths /= Void then
+ s.append (" [ ")
+ across
+ meths as rq
+ loop
+ if l_url /= Void and then rq.item.is_case_insensitive_equal ("GET") then
+ s.append ("" + rq.item + "")
+ else
+ s.append (rq.item)
+ end
+ if not rq.is_last then
+ s.append (",")
+ end
+ s.append (" ")
+ end
+ s.append ("]")
+ end
+
+ hdl := m.handler
+ if attached {WSF_SELF_DOCUMENTED_HANDLER} hdl as l_doc_handler and then attached l_doc_handler.documentation as l_doc then
+ s.append ("%N")
+ s.append (html_encoder.encoded_string (l_doc))
+ s.append ("%N
%N")
+ else
+ debug
+ s.append ("%N")
+ s.append (hdl.generating_type.out)
+ s.append ("%N
%N")
+ end
+ end
+ if attached {WSF_ROUTING_HANDLER} hdl as l_routing_hdl then
+ s.append ("%N%N")
+ across
+ l_routing_hdl.router as c
+ loop
+ append_documentation_to (s, c.item.mapping, c.item.request_methods)
+ end
+ s.append ("%N
%N")
+ end
+ s.append ("%N")
+ end
+
+feature {NONE} -- Implementation
+
+ doc_url (a_api: STRING_8): STRING_8
+ do
+ Result := request.script_url (resource + url_encoder.encoded_string (a_api))
+ end
+
+ html_encoder: HTML_ENCODER
+ once
+ create Result
+ end
+
+ url_encoder: URL_ENCODER
+ once
+ create Result
+ end
+
+end
diff --git a/library/server/wsf/router/documentation/wsf_self_documented_handler.e b/library/server/wsf/router/documentation/wsf_self_documented_handler.e
new file mode 100644
index 00000000..666b2454
--- /dev/null
+++ b/library/server/wsf/router/documentation/wsf_self_documented_handler.e
@@ -0,0 +1,16 @@
+note
+ description: "Summary description for {WSF_SELF_DOCUMENTED_HANDLER}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_SELF_DOCUMENTED_HANDLER
+
+feature -- Documentation
+
+ documentation: detachable READABLE_STRING_32
+ deferred
+ end
+
+end
diff --git a/library/server/wsf/router/documentation/wsf_self_documented_router_mapping.e b/library/server/wsf/router/documentation/wsf_self_documented_router_mapping.e
new file mode 100644
index 00000000..daafb07d
--- /dev/null
+++ b/library/server/wsf/router/documentation/wsf_self_documented_router_mapping.e
@@ -0,0 +1,16 @@
+note
+ description: "Summary description for {WSF_SELF_DOCUMENTED_ROUTER_MAPPING}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ WSF_SELF_DOCUMENTED_ROUTER_MAPPING
+
+feature -- Documentation
+
+ documentation: READABLE_STRING_32
+ deferred
+ end
+
+end
diff --git a/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping.e b/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping.e
index 133da322..35eec54b 100644
--- a/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping.e
+++ b/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping.e
@@ -23,10 +23,20 @@ feature {NONE} -- Initialization
feature -- Access
+ associated_resource: READABLE_STRING_8
+ -- Associated resource
+ do
+ Result := uri
+ end
+
handler: WSF_STARTS_WITH_HANDLER
uri: READABLE_STRING_8
+feature -- Documentation
+
+ documentation: STRING_32 = "Starts-With-URI"
+
feature -- Status
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
diff --git a/library/server/wsf/router/support/uri/wsf_uri_mapping.e b/library/server/wsf/router/support/uri/wsf_uri_mapping.e
index e7dd6a70..4bd74ce1 100644
--- a/library/server/wsf/router/support/uri/wsf_uri_mapping.e
+++ b/library/server/wsf/router/support/uri/wsf_uri_mapping.e
@@ -10,6 +10,8 @@ class
inherit
WSF_ROUTER_MAPPING
+ WSF_SELF_DOCUMENTED_ROUTER_MAPPING
+
create
make,
make_trailing_slash_ignored
@@ -30,12 +32,22 @@ feature {NONE} -- Initialization
feature -- Access
+ associated_resource: READABLE_STRING_8
+ -- Associated resource
+ do
+ Result := uri
+ end
+
handler: WSF_URI_HANDLER
uri: READABLE_STRING_8
trailing_slash_ignored: BOOLEAN
+feature -- Documentation
+
+ documentation: STRING_32 = "Is-URI"
+
feature -- Status
routed_handler (req: WSF_REQUEST; res: WSF_RESPONSE; a_router: WSF_ROUTER): detachable WSF_HANDLER
diff --git a/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping.e b/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping.e
index 2f222cd4..a8cee792 100644
--- a/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping.e
+++ b/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping.e
@@ -10,6 +10,10 @@ class
inherit
WSF_ROUTER_MAPPING
+ WSF_SELF_DOCUMENTED_ROUTER_MAPPING
+
+ DEBUG_OUTPUT
+
create
make,
make_from_template
@@ -29,10 +33,28 @@ feature {NONE} -- Initialization
feature -- Access
+ associated_resource: READABLE_STRING_8
+ -- Associated resource
+ do
+ Result := template.template
+ end
+
handler: WSF_URI_TEMPLATE_HANDLER
template: URI_TEMPLATE
+feature -- Documentation
+
+ documentation: STRING_32 = "Match-URI-Template"
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ Result := "URI-template: " + template.template
+ end
+
feature -- Element change
set_handler (h: like handler)
diff --git a/library/server/wsf/router/support/uri_template_with_context/wsf_uri_template_context_mapping.e b/library/server/wsf/router/support/uri_template_with_context/wsf_uri_template_context_mapping.e
index fff3b931..9f76d416 100644
--- a/library/server/wsf/router/support/uri_template_with_context/wsf_uri_template_context_mapping.e
+++ b/library/server/wsf/router/support/uri_template_with_context/wsf_uri_template_context_mapping.e
@@ -10,6 +10,8 @@ class
inherit
WSF_ROUTER_CONTEXT_MAPPING [C]
+ WSF_SELF_DOCUMENTED_ROUTER_MAPPING
+
DEBUG_OUTPUT
create
@@ -31,10 +33,20 @@ feature {NONE} -- Initialization
feature -- Access
+ associated_resource: READABLE_STRING_8
+ -- Associated resource
+ do
+ Result := template.template
+ end
+
handler: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]
template: URI_TEMPLATE
+feature -- Documentation
+
+ documentation: STRING_32 = "Is-URI"
+
feature -- Status report
debug_output: STRING
diff --git a/library/server/wsf/router/wsf_router.e b/library/server/wsf/router/wsf_router.e
index fdfa0f22..dda16aa0 100644
--- a/library/server/wsf/router/wsf_router.e
+++ b/library/server/wsf/router/wsf_router.e
@@ -114,6 +114,64 @@ feature -- Access
end
end
+feature -- Status report
+
+ has_item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): BOOLEAN
+ local
+ m: WSF_ROUTER_MAPPING
+ ok: BOOLEAN
+ do
+ across
+ mappings as c
+ loop
+ m := c.item.mapping
+ ok := True
+ if rqst_methods /= Void then
+ if attached c.item.request_methods as l_item_rqst_methods then
+ ok := across rqst_methods as mtd some is_matching_request_methods (mtd.item, l_item_rqst_methods) end
+ else
+ ok := True
+ end
+ end
+ if ok then
+ if attached {WSF_ROUTING_HANDLER} m.handler as l_routing then
+ Result := l_routing.router.has_item_associated_with_resource (a_resource, rqst_methods)
+ elseif m.associated_resource.same_string (a_resource) then
+ Result := True
+ end
+ end
+ end
+ end
+
+ item_associated_with_resource (a_resource: READABLE_STRING_8; rqst_methods: detachable WSF_ROUTER_METHODS): detachable WSF_ROUTER_ITEM
+ local
+ m: WSF_ROUTER_MAPPING
+ ok: BOOLEAN
+ do
+ across
+ mappings as c
+ until
+ Result /= Void
+ loop
+ m := c.item.mapping
+ ok := True
+ if rqst_methods /= Void then
+ if attached c.item.request_methods as l_item_rqst_methods then
+ ok := across rqst_methods as mtd some is_matching_request_methods (mtd.item, l_item_rqst_methods) end
+ else
+ ok := True
+ end
+ end
+ if ok then
+ if attached {WSF_ROUTING_HANDLER} m.handler as l_routing then
+ Result := l_routing.router.item_associated_with_resource (a_resource, rqst_methods)
+ elseif m.associated_resource.same_string (a_resource) then
+ Result := c.item
+ end
+ end
+ end
+ end
+
feature -- Hook
execute_before (a_mapping: WSF_ROUTER_MAPPING)
diff --git a/library/server/wsf/router/wsf_router_mapping.e b/library/server/wsf/router/wsf_router_mapping.e
index 81884134..b8c8243b 100644
--- a/library/server/wsf/router/wsf_router_mapping.e
+++ b/library/server/wsf/router/wsf_router_mapping.e
@@ -13,7 +13,12 @@ feature {NONE} -- Initialization
deferred
end
-feature -- Access
+feature -- Access
+
+ associated_resource: READABLE_STRING_8
+ -- Associated resource
+ deferred
+ end
handler: WSF_HANDLER
-- Handler associated with Current mapping.