diff options
author | Kim Alvefur <zash@zash.se> | 2021-03-20 19:02:18 +0100 |
---|---|---|
committer | Kim Alvefur <zash@zash.se> | 2021-03-20 19:02:18 +0100 |
commit | 87474145e51cd0460e8c6608c2dcb7a712d9ef3c (patch) | |
tree | 3952f763a56e48033552eec82da5fedc09564ee4 | |
parent | a51587da480c7521b020e8de3834b61a0e7e2928 (diff) | |
download | prosody-87474145e51cd0460e8c6608c2dcb7a712d9ef3c.tar.gz prosody-87474145e51cd0460e8c6608c2dcb7a712d9ef3c.zip |
util.datamapper: Factor out extraction of the XML part to use
So extract_value() takes an XML tag and details about which part we're
interested in and returns that.
Factoring this out will help with array implementation since this will
be common behavior.
-rw-r--r-- | teal-src/util/datamapper.tl | 82 | ||||
-rw-r--r-- | util/datamapper.lua | 82 |
2 files changed, 84 insertions, 80 deletions
diff --git a/teal-src/util/datamapper.tl b/teal-src/util/datamapper.tl index 3cbc7fda..54ecdacf 100644 --- a/teal-src/util/datamapper.tl +++ b/teal-src/util/datamapper.tl @@ -115,6 +115,45 @@ end local parse_object : function (schema : schema_t, s : st.stanza_t) : { string : any } local parse_array : function (schema : schema_t, s : st.stanza_t) : { any } +local function extract_value (s : st.stanza_t, value_where : value_goes, proptype : json.json_type_name, name : string, namespace : string, prefix : string, single_attribute : string, enums : { any }) : string + if value_where == "in_tag_name" then + local c : st.stanza_t + if proptype == "boolean" then + c = s:get_child(name, namespace); + elseif enums and proptype == "string" then + -- XXX O(n²) ? + -- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n) + -- BUT works first, optimize later + for i = 1, #enums do + c = s:get_child(enums[i] as string, namespace); + if c then break end + end + else + c = s:get_child(nil, namespace); + end + if c then + return c.name; + end + elseif value_where == "in_attribute" then + local attr = name + if prefix then + attr = prefix .. ':' .. name + elseif namespace ~= s.attr.xmlns then + attr = namespace .. "\1" .. name + end + return s.attr[attr] + + elseif value_where == "in_text" then + return s:get_text() + + elseif value_where == "in_single_attribute" then + local c = s:get_child(name, namespace) + return c and c.attr[single_attribute] + elseif value_where == "in_text_tag" then + return s:get_child_text(name, namespace) + end +end + function parse_object (schema : schema_t, s : st.stanza_t) : { string : any } local out : { string : any } = {} if schema is json_schema_object and schema.properties then @@ -122,43 +161,7 @@ function parse_object (schema : schema_t, s : st.stanza_t) : { string : any } local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns) - local value : string - if value_where == "in_tag_name" then - local c : st.stanza_t - if proptype == "boolean" then - c = s:get_child(name, namespace); - elseif enums and proptype == "string" then - -- XXX O(n²) ? - -- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n) - -- BUT works first, optimize later - for i = 1, #enums do - c = s:get_child(enums[i] as string, namespace); - if c then break end - end - else - c = s:get_child(nil, namespace); - end - if c is st.stanza_t then - value = c.name; - end - elseif value_where == "in_attribute" then - local attr = name - if prefix then - attr = prefix .. ':' .. name - elseif namespace ~= s.attr.xmlns then - attr = namespace .. "\1" .. name - end - value = s.attr[attr] - - elseif value_where == "in_text" then - value = s:get_text() - - elseif value_where == "in_single_attribute" then - local c = s:get_child(name, namespace) - 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 json_schema_object then + if value_where == "in_children" and propschema is json_schema_object then if proptype == "object" then local c = s:get_child(name, namespace) if c then @@ -177,9 +180,8 @@ function parse_object (schema : schema_t, s : st.stanza_t) : { string : any } error "unreachable" end else - error "unreachable" - end - if value_where ~= "in_children" and value_where ~= "in_wrapper" then + local value : string = extract_value (s, value_where, proptype, name, namespace, prefix, single_attribute, enums) + out[prop] = totype(proptype, value) end end diff --git a/util/datamapper.lua b/util/datamapper.lua index cb008695..32d01050 100644 --- a/util/datamapper.lua +++ b/util/datamapper.lua @@ -82,6 +82,45 @@ end local parse_object local parse_array +local function extract_value(s, value_where, proptype, name, namespace, prefix, single_attribute, enums) + if value_where == "in_tag_name" then + local c + if proptype == "boolean" then + c = s:get_child(name, namespace); + elseif enums and proptype == "string" then + + for i = 1, #enums do + c = s:get_child(enums[i], namespace); + if c then + break + end + end + else + c = s:get_child(nil, namespace); + end + if c then + return c.name + end + elseif value_where == "in_attribute" then + local attr = name + if prefix then + attr = prefix .. ":" .. name + elseif namespace ~= s.attr.xmlns then + attr = namespace .. "\1" .. name + end + return s.attr[attr] + + elseif value_where == "in_text" then + return s:get_text() + + elseif value_where == "in_single_attribute" then + local c = s:get_child(name, namespace) + return c and c.attr[single_attribute] + elseif value_where == "in_text_tag" then + return s:get_child_text(name, namespace) + end +end + function parse_object(schema, s) local out = {} if type(schema) == "table" and schema.properties then @@ -89,43 +128,7 @@ function parse_object(schema, s) local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns) - local value - if value_where == "in_tag_name" then - local c - if proptype == "boolean" then - c = s:get_child(name, namespace); - elseif enums and proptype == "string" then - - for i = 1, #enums do - c = s:get_child(enums[i], namespace); - if c then - break - end - end - else - c = s:get_child(nil, namespace); - end - if type(c) == "table" then - value = c.name; - end - elseif value_where == "in_attribute" then - local attr = name - if prefix then - attr = prefix .. ":" .. name - elseif namespace ~= s.attr.xmlns then - attr = namespace .. "\1" .. name - end - value = s.attr[attr] - - elseif value_where == "in_text" then - value = s:get_text() - - elseif value_where == "in_single_attribute" then - local c = s:get_child(name, namespace) - 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 value_where == "in_children" and type(propschema) == "table" then if proptype == "object" then local c = s:get_child(name, namespace) if c then @@ -144,9 +147,8 @@ function parse_object(schema, s) error("unreachable") end else - error("unreachable") - end - if value_where ~= "in_children" and value_where ~= "in_wrapper" then + local value = extract_value(s, value_where, proptype, name, namespace, prefix, single_attribute, enums) + out[prop] = totype(proptype, value) end end |