From fb7df0067cf4a84b1fe7f9145b9aafb0ebae75fa Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 14 Mar 2021 16:50:49 +0100 Subject: util.datamapper: Factor out common schema unpacking This code extracts the bits from the schema that determines how the data is to be mapped to/from XML. --- teal-src/util/datamapper.tl | 140 ++++++++++++++++++-------------------------- util/datamapper.lua | 133 +++++++++++++++++------------------------ 2 files changed, 110 insertions(+), 163 deletions(-) diff --git a/teal-src/util/datamapper.tl b/teal-src/util/datamapper.tl index 38a63004..055ddabd 100644 --- a/teal-src/util/datamapper.tl +++ b/teal-src/util/datamapper.tl @@ -51,58 +51,67 @@ local enum value_goes "in_children" end -local function parse_object (schema : js.schema_t, s : st.stanza_t) : table - local out : { string : any } = {} - if schema.properties then - for prop, propschema in pairs(schema.properties) do - -- TODO factor out, if it's generic enough - local name = prop - local namespace = s.attr.xmlns; - local prefix : string = nil - local value_where : value_goes = "in_text_tag" - local single_attribute : string - local enums : { any } +local function unpack_propschema( propschema : js.schema_t | js.schema_t.type_e, propname : string, current_ns : string ) + : js.schema_t.type_e, value_goes, string, string, string, string, { any } + local proptype : js.schema_t.type_e = "string" + local value_where : value_goes = "in_text_tag" + local name = propname + local namespace = current_ns + local prefix : string + local single_attribute : string + local enums : { any } - local proptype : js.schema_t.type_e - if propschema is js.schema_t then - proptype = propschema.type - elseif propschema is js.schema_t.type_e then - proptype = propschema - end + if propschema is js.schema_t then + proptype = propschema.type + elseif propschema is js.schema_t.type_e then + proptype = propschema + end - if proptype == "object" or proptype == "array" then - value_where = "in_children" + if propschema is js.schema_t then + local xml = propschema.xml + if xml then + if xml.name then + name = xml.name + end + if xml.namespace then + namespace = xml.namespace + end + if xml.prefix then + prefix = xml.prefix end - if propschema is js.schema_t and propschema.xml then - if propschema.xml.name then - name = propschema.xml.name - end - if propschema.xml.namespace then - namespace = propschema.xml.namespace - end - if propschema.xml.prefix then - prefix = propschema.xml.prefix - end - if propschema.xml.attribute then - value_where = "in_attribute" - elseif propschema.xml.text then - -- XXX Not yet in OpenAPI - value_where = "in_text" - elseif propschema.xml.x_name_is_value then - -- XXX Custom extension - value_where = "in_tag_name" - elseif propschema.xml.x_single_attribute then - -- XXX Custom extension - single_attribute = propschema.xml.x_single_attribute - value_where = "in_single_attribute" - end - if propschema["const"] then - enums = { propschema["const"] } - elseif propschema["enum"] then - enums = propschema["enum"] - end + if xml.attribute then + value_where = "in_attribute" + elseif xml.text then + value_where = "in_text" + elseif xml.x_name_is_value then + value_where = "in_tag_name" + elseif xml.x_single_attribute then + single_attribute = xml.x_single_attribute + value_where = "in_single_attribute" end + end + if propschema["const"] then + enums = { propschema["const"] } + elseif propschema["enum"] then + enums = propschema["enum"] + end + end + + if proptype == "object" or proptype == "array" then + value_where = "in_children" + end + + return proptype, value_where, name, namespace, prefix, single_attribute, enums +end + + +local function parse_object (schema : js.schema_t, s : st.stanza_t) : table + local out : { string : any } = {} + if schema.properties then + for prop, propschema in pairs(schema.properties) do + + 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 @@ -181,43 +190,8 @@ local function unparse ( schema : js.schema_t, t : table, current_name : string, local v = t[prop] if v ~= nil then - local proptype : js.schema_t.type_e - if propschema is js.schema_t then - proptype = propschema.type - elseif propschema is js.schema_t.type_e then - proptype = propschema - end - local name = prop - local namespace = current_ns - local prefix : string = nil - local value_where : value_goes = "in_text_tag" - local single_attribute : string - - if propschema is js.schema_t and propschema.xml then - - if propschema.xml.name then - name = propschema.xml.name - end - if propschema.xml.namespace then - namespace = propschema.xml.namespace - end - - if propschema.xml.prefix then - prefix = propschema.xml.prefix - end - - if propschema.xml.attribute then - value_where = "in_attribute" - elseif propschema.xml.text then - value_where = "in_text" - elseif propschema.xml.x_name_is_value then - value_where = "in_tag_name" - elseif propschema.xml.x_single_attribute then - single_attribute = propschema.xml.x_single_attribute - value_where = "in_single_attribute" - end - end + local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(propschema, prop, current_ns) if value_where == "in_attribute" then local attr = name diff --git a/util/datamapper.lua b/util/datamapper.lua index d642c881..da46d072 100644 --- a/util/datamapper.lua +++ b/util/datamapper.lua @@ -22,58 +22,66 @@ end local value_goes = {} -local function parse_object(schema, s) - local out = {} - if schema.properties then - for prop, propschema in pairs(schema.properties) do +local function unpack_propschema(propschema, propname, current_ns) + + local proptype = "string" + local value_where = "in_text_tag" + local name = propname + local namespace = current_ns + local prefix + local single_attribute + local enums + + if type(propschema) == "table" then + proptype = propschema.type + elseif type(propschema) == "string" then + proptype = propschema + end - local name = prop - local namespace = s.attr.xmlns; - local prefix = nil - local value_where = "in_text_tag" - local single_attribute - local enums - - local proptype - if type(propschema) == "table" then - proptype = propschema.type - elseif type(propschema) == "string" then - proptype = propschema + if type(propschema) == "table" then + local xml = propschema.xml + if xml then + if xml.name then + name = xml.name + end + if xml.namespace then + namespace = xml.namespace + end + if xml.prefix then + prefix = xml.prefix end - if proptype == "object" or proptype == "array" then - value_where = "in_children" + if xml.attribute then + value_where = "in_attribute" + elseif xml.text then + value_where = "in_text" + elseif xml.x_name_is_value then + value_where = "in_tag_name" + elseif xml.x_single_attribute then + single_attribute = xml.x_single_attribute + value_where = "in_single_attribute" end + end + if propschema["const"] then + enums = {propschema["const"]} + elseif propschema["enum"] then + enums = propschema["enum"] + end + end - if type(propschema) == "table" and propschema.xml then - if propschema.xml.name then - name = propschema.xml.name - end - if propschema.xml.namespace then - namespace = propschema.xml.namespace - end - if propschema.xml.prefix then - prefix = propschema.xml.prefix - end - if propschema.xml.attribute then - value_where = "in_attribute" - elseif propschema.xml.text then + if proptype == "object" or proptype == "array" then + value_where = "in_children" + end - value_where = "in_text" - elseif propschema.xml.x_name_is_value then + return proptype, value_where, name, namespace, prefix, single_attribute, enums +end - value_where = "in_tag_name" - elseif propschema.xml.x_single_attribute then +local function parse_object(schema, s) + local out = {} + if schema.properties then + for prop, propschema in pairs(schema.properties) do - single_attribute = propschema.xml.x_single_attribute - value_where = "in_single_attribute" - end - if propschema["const"] then - enums = {propschema["const"]} - elseif propschema["enum"] then - enums = propschema["enum"] - end - end + 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 @@ -152,43 +160,8 @@ local function unparse(schema, t, current_name, current_ns) local v = t[prop] if v ~= nil then - local proptype - if type(propschema) == "table" then - proptype = propschema.type - elseif type(propschema) == "string" then - proptype = propschema - end - - local name = prop - local namespace = current_ns - local prefix = nil - local value_where = "in_text_tag" - local single_attribute - if type(propschema) == "table" and propschema.xml then - - if propschema.xml.name then - name = propschema.xml.name - end - if propschema.xml.namespace then - namespace = propschema.xml.namespace - end - - if propschema.xml.prefix then - prefix = propschema.xml.prefix - end - - if propschema.xml.attribute then - value_where = "in_attribute" - elseif propschema.xml.text then - value_where = "in_text" - elseif propschema.xml.x_name_is_value then - value_where = "in_tag_name" - elseif propschema.xml.x_single_attribute then - single_attribute = propschema.xml.x_single_attribute - value_where = "in_single_attribute" - end - end + local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(propschema, prop, current_ns) if value_where == "in_attribute" then local attr = name -- cgit v1.2.3