Changeset

11455:a5050e21ab08

util.datamapper: Separate extraction of xml from coercion to target type Now it gets the text, attribute or name first, then turns it into whatever the schema wants. This should be easier to further factor out into preparation for array support.
author Kim Alvefur <zash@zash.se>
date Sun, 14 Mar 2021 03:06:37 +0100
parents 11454:1d9c1893cc5e
children 11456:4e376a43fe40
files teal-src/util/datamapper.tl util/datamapper.lua
diffstat 2 files changed, 56 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/teal-src/util/datamapper.tl	Sun Mar 14 01:57:00 2021 +0100
+++ b/teal-src/util/datamapper.tl	Sun Mar 14 03:06:37 2021 +0100
@@ -27,6 +27,18 @@
 		return true
 	elseif s == "false" or s == "0" then
 		return false
+	elseif s then
+		return true
+	end
+end
+
+local function totype(t : js.schema_t.type_e, s : string) : any
+	if t == "string" then
+		return s;
+	elseif t == "boolean" then
+		return toboolean(s)
+	elseif t == "number" or t == "integer" then
+		return tonumber(s)
 	end
 end
 
@@ -58,6 +70,10 @@
 				proptype = propschema
 			end
 
+			if proptype == "object" or proptype == "array" then
+				value_where = "in_children"
+			end
+
 			if propschema is js.schema_t and propschema.xml then
 				if propschema.xml.name then
 					name = propschema.xml.name
@@ -88,6 +104,7 @@
 				end
 			end
 
+			local value : string
 			if value_where == "in_tag_name" then
 				local c : st.stanza_t
 				if proptype == "boolean" then
@@ -103,11 +120,7 @@
 				else
 					c = s:get_child(nil, namespace);
 				end
-				if c and proptype == "string" then
-					out[prop] = c.name;
-				elseif proptype == "boolean" and c then
-					out[prop] = true;
-				end
+				value = c.name;
 			elseif value_where == "in_attribute" then
 				local attr = name
 				if prefix then
@@ -115,40 +128,18 @@
 				elseif namespace ~= s.attr.xmlns then
 					attr = namespace .. "\1" .. name
 				end
-				if proptype == "string" then
-					out[prop] = s.attr[attr]
-				elseif proptype == "integer" or proptype == "number" then
-					-- TODO floor if integer ?
-					out[prop] = tonumber(s.attr[attr])
-				elseif proptype == "boolean" then
-					out[prop] = toboolean(s.attr[attr])
-				-- else TODO
-				end
+				value = s.attr[attr]
 
 			elseif value_where == "in_text" then
-				if proptype == "string" then
-					out[prop] = s:get_text()
-				elseif proptype == "integer" or proptype == "number" then
-					out[prop] = tonumber(s:get_text())
-				end
+				value = s:get_text()
 
 			elseif value_where == "in_single_attribute" then
 				local c = s:get_child(name, namespace)
-				local a = c and c.attr[single_attribute]
-				if proptype == "string" then
-					out[prop] = a
-				elseif proptype == "integer" or proptype == "number" then
-					out[prop] = tonumber(a)
-				elseif proptype == "boolean" then
-					out[prop] = toboolean(a)
-				end
-			else
-
-				if proptype == "string" then
-					out[prop] = s:get_child_text(name, namespace)
-				elseif proptype == "integer" or proptype == "number" then
-					out[prop] = tonumber(s:get_child_text(name, namespace))
-				elseif proptype == "object" and propschema is js.schema_t then
+				value = c and c.attr[single_attribute]
+			elseif value_where == "in_text_tag" then
+				value = s:get_child_text(name, namespace)
+			elseif value_where == "in_children" and propschema is js.schema_t then
+				if proptype == "object" then
 					local c = s:get_child(name, namespace)
 					if c then
 						out[prop] = parse_object(propschema, c);
@@ -156,6 +147,9 @@
 				-- else TODO
 				end
 			end
+			if value_where ~= "in_children" then
+				out[prop] = totype(proptype, value)
+			end
 		end
 	end
 
--- a/util/datamapper.lua	Sun Mar 14 01:57:00 2021 +0100
+++ b/util/datamapper.lua	Sun Mar 14 03:06:37 2021 +0100
@@ -5,6 +5,18 @@
 		return true
 	elseif s == "false" or s == "0" then
 		return false
+	elseif s then
+		return true
+	end
+end
+
+local function totype(t, s)
+	if t == "string" then
+		return s
+	elseif t == "boolean" then
+		return toboolean(s)
+	elseif t == "number" or t == "integer" then
+		return tonumber(s)
 	end
 end
 
@@ -29,6 +41,10 @@
 				proptype = propschema
 			end
 
+			if proptype == "object" or proptype == "array" then
+				value_where = "in_children"
+			end
+
 			if type(propschema) == "table" and propschema.xml then
 				if propschema.xml.name then
 					name = propschema.xml.name
@@ -59,6 +75,7 @@
 				end
 			end
 
+			local value
 			if value_where == "in_tag_name" then
 				local c
 				if proptype == "boolean" then
@@ -74,11 +91,7 @@
 				else
 					c = s:get_child(nil, namespace);
 				end
-				if c and proptype == "string" then
-					out[prop] = c.name;
-				elseif proptype == "boolean" and c then
-					out[prop] = true;
-				end
+				value = c.name;
 			elseif value_where == "in_attribute" then
 				local attr = name
 				if prefix then
@@ -86,40 +99,18 @@
 				elseif namespace ~= s.attr.xmlns then
 					attr = namespace .. "\1" .. name
 				end
-				if proptype == "string" then
-					out[prop] = s.attr[attr]
-				elseif proptype == "integer" or proptype == "number" then
-
-					out[prop] = tonumber(s.attr[attr])
-				elseif proptype == "boolean" then
-					out[prop] = toboolean(s.attr[attr])
-
-				end
+				value = s.attr[attr]
 
 			elseif value_where == "in_text" then
-				if proptype == "string" then
-					out[prop] = s:get_text()
-				elseif proptype == "integer" or proptype == "number" then
-					out[prop] = tonumber(s:get_text())
-				end
+				value = s:get_text()
 
 			elseif value_where == "in_single_attribute" then
 				local c = s:get_child(name, namespace)
-				local a = c and c.attr[single_attribute]
-				if proptype == "string" then
-					out[prop] = a
-				elseif proptype == "integer" or proptype == "number" then
-					out[prop] = tonumber(a)
-				elseif proptype == "boolean" then
-					out[prop] = toboolean(a)
-				end
-			else
-
-				if proptype == "string" then
-					out[prop] = s:get_child_text(name, namespace)
-				elseif proptype == "integer" or proptype == "number" then
-					out[prop] = tonumber(s:get_child_text(name, namespace))
-				elseif proptype == "object" and type(propschema) == "table" then
+				value = c and c.attr[single_attribute]
+			elseif value_where == "in_text_tag" then
+				value = s:get_child_text(name, namespace)
+			elseif value_where == "in_children" and type(propschema) == "table" then
+				if proptype == "object" then
 					local c = s:get_child(name, namespace)
 					if c then
 						out[prop] = parse_object(propschema, c);
@@ -127,6 +118,9 @@
 
 				end
 			end
+			if value_where ~= "in_children" then
+				out[prop] = totype(proptype, value)
+			end
 		end
 	end