teal-src/util/datamapper.tl
author Kim Alvefur <zash@zash.se>
Wed, 29 Dec 2021 17:57:09 +0100
changeset 12137 11060c8919b6
parent 11485 b2f9782497dd
child 12584 a9dbf657c894
permissions -rw-r--r--
util.datamapper: Add support for $ref pointers Allows reuse of repetitive definitions in schemas.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11454
25829015917c util.datamapper: Add Copyright header
Kim Alvefur <zash@zash.se>
parents: 11443
diff changeset
     1
-- Copyright (C) 2021 Kim Alvefur
25829015917c util.datamapper: Add Copyright header
Kim Alvefur <zash@zash.se>
parents: 11443
diff changeset
     2
--
25829015917c util.datamapper: Add Copyright header
Kim Alvefur <zash@zash.se>
parents: 11443
diff changeset
     3
-- This project is MIT/X11 licensed. Please see the
25829015917c util.datamapper: Add Copyright header
Kim Alvefur <zash@zash.se>
parents: 11443
diff changeset
     4
-- COPYING file in the source package for more information.
25829015917c util.datamapper: Add Copyright header
Kim Alvefur <zash@zash.se>
parents: 11443
diff changeset
     5
--
11455
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
     6
-- Based on
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
     7
-- https://json-schema.org/draft/2020-12/json-schema-core.html
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
     8
-- https://json-schema.org/draft/2020-12/json-schema-validation.html
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
     9
-- http://spec.openapis.org/oas/v3.0.1#xmlObject
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    10
-- https://github.com/OAI/OpenAPI-Specification/issues/630 (text:true)
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    11
--
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    12
-- XML Object Extensions:
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    13
-- text to refer to the text content at the same time as attributes
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    14
-- x_name_is_value for enum fields where the <tag-name/> is the value
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    15
-- x_single_attribute for <tag attr="this"/>
ee4f2296e7df util.datamapper: Add references with notes
Kim Alvefur <zash@zash.se>
parents: 11454
diff changeset
    16
--
11456
c799bac7ca59 util.datamapper: Some TODOs
Kim Alvefur <zash@zash.se>
parents: 11455
diff changeset
    17
-- TODO pointers
c799bac7ca59 util.datamapper: Some TODOs
Kim Alvefur <zash@zash.se>
parents: 11455
diff changeset
    18
-- TODO cleanup / refactor
11463
86904555bffc teal: Use new integer support in Teal 0.13.0
Kim Alvefur <zash@zash.se>
parents: 11462
diff changeset
    19
-- TODO s/number/integer/ once we have appropriate math.type() compat
11456
c799bac7ca59 util.datamapper: Some TODOs
Kim Alvefur <zash@zash.se>
parents: 11455
diff changeset
    20
--
11454
25829015917c util.datamapper: Add Copyright header
Kim Alvefur <zash@zash.se>
parents: 11443
diff changeset
    21
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    22
local st = require "util.stanza";
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    23
local json = require"util.json"
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    24
local pointer = require"util.jsonpointer";
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    25
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    26
local json_type_name = json.json_type_name;
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    27
local json_schema_object = require "util.jsonschema"
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    28
local type schema_t = boolean | json_type_name | json_schema_object
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    29
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    30
local function toboolean ( s : string ) : boolean
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    31
	if s == "true" or s == "1" then
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    32
		return true
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    33
	elseif s == "false" or s == "0" then
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    34
		return false
11459
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    35
	elseif s then
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    36
		return true
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    37
	end
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    38
end
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    39
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    40
local function totype(t : json_type_name, s : string) : any
11483
377a9eaf7bef util.datamapper: Fix error on attempt to coerce nil to something
Kim Alvefur <zash@zash.se>
parents: 11480
diff changeset
    41
	if not s then return nil end
11459
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    42
	if t == "string" then
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    43
		return s;
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    44
	elseif t == "boolean" then
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    45
		return toboolean(s)
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    46
	elseif t == "number" or t == "integer" then
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
    47
		return tonumber(s)
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    48
	end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    49
end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    50
11458
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    51
local enum value_goes
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    52
	"in_tag_name"
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    53
	"in_text"
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    54
	"in_text_tag"
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    55
	"in_attribute"
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    56
	"in_single_attribute"
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    57
	"in_children"
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
    58
	"in_wrapper"
11458
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    59
end
1d9c1893cc5e util.datamapper: Use enum instead of mutually exclusive booleans
Kim Alvefur <zash@zash.se>
parents: 11457
diff changeset
    60
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    61
local function resolve_schema(schema  : schema_t, root : json_schema_object) : schema_t
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    62
	if schema is json_schema_object and schema["$ref"] and schema["$ref"]:sub(1, 1) == "#" then
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    63
		local referenced = pointer.resolve(root as table, schema["$ref"]:sub(2)) as schema_t;
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    64
		if referenced ~= nil then
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    65
			return referenced
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    66
		end
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    67
	end
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    68
	return schema;
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    69
end
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    70
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    71
local function unpack_propschema( propschema : schema_t, propname : string, current_ns : string )
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    72
		: json_type_name, value_goes, string, string, string, string, { any }
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    73
	local proptype : json_type_name = "string"
11470
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
    74
	local value_where : value_goes = propname and "in_text_tag" or "in_text"
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    75
	local name = propname
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
    76
	local namespace : string
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    77
	local prefix : string
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    78
	local single_attribute : string
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    79
	local enums : { any }
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    80
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    81
	if propschema is json_schema_object then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    82
		proptype = propschema.type
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    83
	elseif propschema is json_type_name then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    84
		proptype = propschema
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    85
	end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    86
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
    87
	if proptype == "object" or proptype == "array" then
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
    88
		value_where = "in_children"
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
    89
	end
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
    90
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    91
	if propschema is json_schema_object then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    92
		local xml = propschema.xml
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    93
		if xml then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    94
			if xml.name then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    95
				name = xml.name
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    96
			end
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
    97
			if xml.namespace and xml.namespace ~= current_ns then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    98
				namespace = xml.namespace
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    99
			end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   100
			if xml.prefix then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   101
				prefix = xml.prefix
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   102
			end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   103
			if proptype == "array" and xml.wrapped then
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   104
				value_where = "in_wrapper"
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   105
			elseif xml.attribute then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   106
				value_where = "in_attribute"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   107
			elseif xml.text then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   108
				value_where = "in_text"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   109
			elseif xml.x_name_is_value then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   110
				value_where = "in_tag_name"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   111
			elseif xml.x_single_attribute then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   112
				single_attribute = xml.x_single_attribute
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   113
				value_where = "in_single_attribute"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   114
			end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   115
		end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   116
		if propschema["const"] then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   117
			enums = { propschema["const"] }
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   118
		elseif propschema["enum"] then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   119
			enums = propschema["enum"]
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   120
		end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   121
	end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   122
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   123
	return proptype, value_where, name, namespace, prefix, single_attribute, enums
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   124
end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   125
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   126
local parse_object : function (schema : schema_t, s : st.stanza_t, root : json_schema_object) : { string : any }
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   127
local parse_array : function (schema : schema_t, s : st.stanza_t, root : json_schema_object) : { any }
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   128
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   129
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
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   130
	if value_where == "in_tag_name" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   131
		local c : st.stanza_t
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   132
		if proptype == "boolean" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   133
			c = s:get_child(name, namespace);
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   134
		elseif enums and proptype == "string" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   135
			-- XXX O(n²) ?
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   136
			-- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n)
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   137
			-- BUT works first, optimize later
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   138
			for i = 1, #enums do
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   139
				c = s:get_child(enums[i] as string, namespace);
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   140
				if c then break end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   141
			end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   142
		else
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   143
			c = s:get_child(nil, namespace);
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   144
		end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   145
		if c then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   146
			return c.name;
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   147
		end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   148
	elseif value_where == "in_attribute" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   149
		local attr = name
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   150
		if prefix then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   151
			attr = prefix .. ':' .. name
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   152
		elseif namespace and namespace ~= s.attr.xmlns then
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   153
			attr = namespace .. "\1" .. name
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   154
		end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   155
		return s.attr[attr]
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   156
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   157
	elseif value_where == "in_text" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   158
		return s:get_text()
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   159
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   160
	elseif value_where == "in_single_attribute" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   161
		local c = s:get_child(name, namespace)
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   162
		return c and c.attr[single_attribute]
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   163
	elseif value_where == "in_text_tag" then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   164
		return s:get_child_text(name, namespace)
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   165
	end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   166
end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   167
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   168
function parse_object (schema : schema_t, s : st.stanza_t, root : json_schema_object) : { string : any }
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   169
	local out : { string : any } = {}
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   170
	schema = resolve_schema(schema, root)
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   171
	if schema is json_schema_object and schema.properties then
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   172
		for prop, propschema in pairs(schema.properties) do
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   173
			propschema = resolve_schema(propschema, root)
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   174
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   175
			local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns)
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   176
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   177
			if value_where == "in_children" and propschema is json_schema_object then
11459
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
   178
				if proptype == "object" then
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   179
					local c = s:get_child(name, namespace)
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   180
					if c then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   181
						out[prop] = parse_object(propschema, c, root);
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   182
					end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   183
				elseif proptype == "array" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   184
					local a = parse_array(propschema, s, root);
11485
b2f9782497dd util.datamapper: Don't include empty unwrapped arrays
Kim Alvefur <zash@zash.se>
parents: 11483
diff changeset
   185
					if a and a[1] ~= nil then
b2f9782497dd util.datamapper: Don't include empty unwrapped arrays
Kim Alvefur <zash@zash.se>
parents: 11483
diff changeset
   186
						out[prop] = a;
b2f9782497dd util.datamapper: Don't include empty unwrapped arrays
Kim Alvefur <zash@zash.se>
parents: 11483
diff changeset
   187
					end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   188
				else
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   189
					error "unreachable"
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   190
				end
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   191
			elseif value_where == "in_wrapper" and propschema is json_schema_object and proptype == "array" then
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   192
				local wrapper = s:get_child(name, namespace);
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   193
				if wrapper then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   194
					out[prop] = parse_array(propschema, wrapper, root);
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   195
				end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   196
			else
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   197
				local value : string = extract_value (s, value_where, proptype, name, namespace, prefix, single_attribute, enums)
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   198
11459
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
   199
				out[prop] = totype(proptype, value)
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
   200
			end
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   201
		end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   202
	end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   203
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   204
	return out
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   205
end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   206
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   207
function parse_array (schema : json_schema_object, s : st.stanza_t, root : json_schema_object) : { any }
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   208
	local itemschema : schema_t = resolve_schema(schema.items, root);
11475
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   209
	local proptype, value_where, child_name, namespace, prefix, single_attribute, enums = unpack_propschema(itemschema, nil, s.attr.xmlns)
11470
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   210
	local attr_name : string
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   211
	if value_where == "in_single_attribute" then -- FIXME this shouldn't be needed
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   212
		value_where = "in_attribute";
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   213
		attr_name = single_attribute;
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   214
	end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   215
	local out : { any } = {}
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   216
11475
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   217
	if proptype == "object" then
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   218
		if itemschema is json_schema_object then
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   219
			for c in s:childtags(child_name, namespace) do
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   220
				table.insert(out, parse_object(itemschema, c, root));
11475
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   221
			end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   222
		else
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   223
			error "array items must be schema object"
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   224
		end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   225
	elseif proptype == "array" then
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   226
		if itemschema is json_schema_object then
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   227
			for c in s:childtags(child_name, namespace) do
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   228
				table.insert(out, parse_array(itemschema, c, root));
11475
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   229
			end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   230
		end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   231
	else
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   232
		for c in s:childtags(child_name, namespace) do
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   233
			local value : string = extract_value (c, value_where, proptype, attr_name or child_name, namespace, prefix, single_attribute, enums)
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   234
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   235
			table.insert(out, totype(proptype, value));
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   236
		end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   237
	end
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   238
	return out;
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   239
end
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   240
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   241
local function parse (schema : json_schema_object, s : st.stanza_t) : table
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   242
	if schema.type == "object" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   243
		return parse_object(schema, s, schema)
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   244
	elseif schema.type == "array" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   245
		return parse_array(schema, s, schema)
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   246
	else
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   247
		error "top-level scalars unsupported"
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   248
	end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   249
end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   250
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   251
local function toxmlstring(proptype : json_type_name, v : any) : string
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   252
	if proptype == "string" and v is string then
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   253
		return  v
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   254
	elseif proptype == "number" and v is number then
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   255
		return  string.format("%g", v)
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   256
	elseif proptype == "integer" and v is number then -- TODO is integer
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   257
		return  string.format("%d", v)
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   258
	elseif proptype == "boolean" then
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   259
		return  v and "1" or "0"
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   260
	end
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   261
end
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   262
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   263
local unparse : function (json_schema_object, table, string, string, st.stanza_t, json_schema_object) : st.stanza_t
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   264
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   265
local function unparse_property(out : st.stanza_t, v : any, proptype : json_type_name, propschema : schema_t, value_where : value_goes, name : string, namespace : string, current_ns : string, prefix : string, single_attribute : string, root : json_schema_object)
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   266
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   267
	if value_where == "in_attribute" then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   268
		local attr = name
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   269
		if prefix then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   270
			attr = prefix .. ':' .. name
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   271
		elseif namespace and namespace ~= current_ns then
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   272
			attr = namespace .. "\1" .. name
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   273
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   274
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   275
		out.attr[attr] = toxmlstring(proptype, v)
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   276
	elseif value_where == "in_text" then
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   277
		out:text(toxmlstring(proptype, v))
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   278
	elseif value_where == "in_single_attribute" then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   279
		assert(single_attribute)
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   280
		local propattr : { string : string } = {}
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   281
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   282
		if namespace and namespace ~= current_ns then
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   283
			propattr.xmlns = namespace
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   284
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   285
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   286
		propattr[single_attribute] = toxmlstring(proptype, v)
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   287
		out:tag(name, propattr):up();
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   288
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   289
	else
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   290
		local propattr : { string : string }
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   291
		if namespace ~= current_ns then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   292
			propattr = { xmlns = namespace }
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   293
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   294
		if value_where == "in_tag_name" then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   295
			if proptype == "string" and v is string then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   296
				out:tag(v, propattr):up();
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   297
			elseif proptype == "boolean" and v == true then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   298
				out:tag(name, propattr):up();
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   299
			end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   300
		elseif proptype == "object" and propschema is json_schema_object and v is table then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   301
			local c = unparse(propschema, v, name, namespace, nil, root);
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   302
			if c then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   303
				out:add_direct_child(c);
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   304
			end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   305
		elseif proptype == "array" and propschema is json_schema_object and v is table then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   306
			if value_where == "in_wrapper" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   307
				local c = unparse(propschema, v, name, namespace, nil, root);
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   308
				if c then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   309
					out:add_direct_child(c);
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   310
				end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   311
			else
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   312
				unparse(propschema, v, name, namespace, out, root);
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   313
			end
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   314
		else
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   315
			out:text_tag(name, toxmlstring(proptype, v), propattr)
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   316
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   317
	end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   318
end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   319
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   320
function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string, ctx : st.stanza_t, root : json_schema_object ) : st.stanza_t
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   321
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   322
	if root == nil then root = schema end
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   323
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   324
	if schema.xml then
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   325
		if schema.xml.name then
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   326
			current_name = schema.xml.name
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   327
		end
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   328
		if schema.xml.namespace then
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   329
			current_ns = schema.xml.namespace
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   330
		end
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   331
		-- TODO prefix?
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   332
	end
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   333
11466
d1982b7eb00d util.datamapper: Fix arrays nesting one level too deep
Kim Alvefur <zash@zash.se>
parents: 11465
diff changeset
   334
	local out = ctx or st.stanza(current_name, { xmlns = current_ns })
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   335
11462
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   336
	if schema.type == "object" then
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   337
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   338
		for prop, propschema in pairs(schema.properties) do
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   339
			propschema = resolve_schema(propschema, root)
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   340
			local v = t[prop]
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   341
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   342
			if v ~= nil then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   343
				local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(propschema, prop, current_ns)
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   344
				unparse_property(out, v, proptype, propschema, value_where, name, namespace, current_ns, prefix, single_attribute, root)
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   345
			end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   346
		end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   347
		return out;
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   348
11462
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   349
	elseif schema.type == "array" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   350
		local itemschema = resolve_schema(schema.items, root)
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   351
		local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(itemschema, current_name, current_ns)
11472
348b191cd850 util.datamapper: Complete array building support
Kim Alvefur <zash@zash.se>
parents: 11471
diff changeset
   352
		for _, item in ipairs(t as { string }) do
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   353
			unparse_property(out, item, proptype, itemschema, value_where, name, namespace, current_ns, prefix, single_attribute, root)
11462
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   354
		end
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   355
		return out;
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   356
	end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   357
end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   358
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   359
return {
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   360
	parse = parse,
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   361
	unparse = unparse,
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   362
}