Changeset

11437:87a684df4b65

util.datamapper: Invent extension for using tag name as value Useful for certain enum-like uses where the element name is the relevant information, e.g. chat states.
author Kim Alvefur <zash@zash.se>
date Sat, 06 Mar 2021 23:14:23 +0100
parents 11436:5df9ffc25bb4
children 11438:b7807583de34
files spec/util_datamapper_spec.lua teal-src/util/datamapper.tl teal-src/util/jsonschema.tl util/datamapper.lua
diffstat 4 files changed, 42 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/spec/util_datamapper_spec.lua	Sun Mar 07 00:57:36 2021 +0100
+++ b/spec/util_datamapper_spec.lua	Sat Mar 06 23:14:23 2021 +0100
@@ -27,15 +27,20 @@
 					xml = {namespace = "urn:xmpp:delay"; name = "delay"};
 					properties = {stamp = attr(); from = attr(); reason = {type = "string"; xml = {text = true}}};
 				};
+				state = {
+					type = "string";
+					xml = {x_name_is_value = true; namespace = "http://jabber.org/protocol/chatstates"};
+				};
 			};
 		};
 
 		x = xml.parse [[
-			<message xmlns="jabber:client" xml:lang="en" to="a@test" from="b@test" type="chat" id="1">
-			<body>Hello</body>
-			<delay xmlns='urn:xmpp:delay' from='test' stamp='2021-03-07T15:59:08+00:00'>Becasue</delay>
-			</message>
-		]];
+				<message xmlns="jabber:client" xml:lang="en" to="a@test" from="b@test" type="chat" id="1">
+				<body>Hello</body>
+				<delay xmlns='urn:xmpp:delay' from='test' stamp='2021-03-07T15:59:08+00:00'>Becasue</delay>
+				<active xmlns='http://jabber.org/protocol/chatstates'/>
+				</message>
+				]];
 
 		d = {
 			to = "a@test";
@@ -45,6 +50,7 @@
 			lang = "en";
 			body = "Hello";
 			delay = {from = "test"; stamp = "2021-03-07T15:59:08+00:00"; reason = "Becasue"};
+			state = "active";
 		};
 	end);
 
--- a/teal-src/util/datamapper.tl	Sun Mar 07 00:57:36 2021 +0100
+++ b/teal-src/util/datamapper.tl	Sat Mar 06 23:14:23 2021 +0100
@@ -19,6 +19,7 @@
 			local prefix : string = nil
 			local is_attribute = false
 			local is_text = false
+			local name_is_value = false;
 
 			local proptype : js.schema_t.type_e
 			if propschema is js.schema_t then
@@ -41,10 +42,17 @@
 					is_attribute = true
 				elseif propschema.xml.text then
 					is_text = true
+				elseif propschema.xml.x_name_is_value then
+					name_is_value = true
 				end
 			end
 
-			if is_attribute then
+			if name_is_value then
+				local c = s:get_child(nil, namespace);
+				if c then
+					out[prop] = c.name;
+				end
+			elseif is_attribute then
 				local attr = name
 				if prefix then
 					attr = prefix .. ':' .. name
@@ -125,6 +133,7 @@
 				local prefix : string = nil
 				local is_attribute = false
 				local is_text = false
+				local name_is_value = false;
 
 				if propschema is js.schema_t and propschema.xml then
 
@@ -143,6 +152,8 @@
 						is_attribute = true
 					elseif propschema.xml.text then
 						is_text = true
+					elseif propschema.xml.x_name_is_value then
+						name_is_value = true
 					end
 				end
 
@@ -172,7 +183,9 @@
 					if namespace ~= current_ns then
 						propattr = { xmlns = namespace }
 					end
-					if proptype == "string" and v is string then
+					if name_is_value and v is string then
+						out:tag(v, propattr):up();
+					elseif proptype == "string" and v is string then
 						out:text_tag(name, v, propattr)
 					elseif proptype == "number" and v is number then
 						out:text_tag(name, string.format("%g", v), propattr)
--- a/teal-src/util/jsonschema.tl	Sun Mar 07 00:57:36 2021 +0100
+++ b/teal-src/util/jsonschema.tl	Sat Mar 06 23:14:23 2021 +0100
@@ -64,6 +64,7 @@
 
 		-- nonstantard, maybe in the future
 		text : boolean
+		x_name_is_value : boolean
 	end
 
 	xml : xml_t
--- a/util/datamapper.lua	Sun Mar 07 00:57:36 2021 +0100
+++ b/util/datamapper.lua	Sat Mar 06 23:14:23 2021 +0100
@@ -18,6 +18,7 @@
 			local prefix = nil
 			local is_attribute = false
 			local is_text = false
+			local name_is_value = false;
 
 			local proptype
 			if type(propschema) == "table" then
@@ -40,10 +41,17 @@
 					is_attribute = true
 				elseif propschema.xml.text then
 					is_text = true
+				elseif propschema.xml.x_name_is_value then
+					name_is_value = true
 				end
 			end
 
-			if is_attribute then
+			if name_is_value then
+				local c = s:get_child(nil, namespace);
+				if c then
+					out[prop] = c.name;
+				end
+			elseif is_attribute then
 				local attr = name
 				if prefix then
 					attr = prefix .. ":" .. name
@@ -124,6 +132,7 @@
 				local prefix = nil
 				local is_attribute = false
 				local is_text = false
+				local name_is_value = false;
 
 				if type(propschema) == "table" and propschema.xml then
 
@@ -142,6 +151,8 @@
 						is_attribute = true
 					elseif propschema.xml.text then
 						is_text = true
+					elseif propschema.xml.x_name_is_value then
+						name_is_value = true
 					end
 				end
 
@@ -171,7 +182,9 @@
 					if namespace ~= current_ns then
 						propattr = {xmlns = namespace}
 					end
-					if proptype == "string" and type(v) == "string" then
+					if name_is_value and type(v) == "string" then
+						out:tag(v, propattr):up();
+					elseif proptype == "string" and type(v) == "string" then
 						out:text_tag(name, v, propattr)
 					elseif proptype == "number" and type(v) == "number" then
 						out:text_tag(name, string.format("%g", v), propattr)