teal-src/util/datamapper.tl
author Kim Alvefur <zash@zash.se>
Wed, 19 Oct 2022 14:07:48 +0200
changeset 12780 4715301a3504
parent 12584 a9dbf657c894
child 12786 8815d3090928
permissions -rw-r--r--
util.datamapper: Remove leftover debug assert (Only Teal, not included in build)
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"
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    28
local type schema_t = boolean | 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
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    62
	if schema is json_schema_object then
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    63
		if schema["$ref"] and schema["$ref"]:sub(1, 1) == "#" then
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    64
			return pointer.resolve(root as table, schema["$ref"]:sub(2)) as schema_t;
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    65
		end
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
	return schema;
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    68
end
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
    69
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    70
local function guess_schema_type(schema : json_schema_object) : json_type_name
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    71
	local schema_types = schema.type
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    72
	if schema_types is json_type_name then
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    73
		return schema_types
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    74
	elseif schema_types ~= nil then
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    75
		error "schema has unsupported 'type' property"
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    76
	elseif schema.properties then
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    77
		return "object"
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    78
	elseif schema.items then
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    79
		return "array"
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    80
	end
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    81
	return "string" -- default assumption
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    82
end
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    83
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    84
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
    85
		: 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
    86
	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
    87
	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
    88
	local name = propname
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
    89
	local namespace : string
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    90
	local prefix : string
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    91
	local single_attribute : string
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    92
	local enums : { any }
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    93
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
    94
	if propschema is json_schema_object then
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    95
		proptype = guess_schema_type(propschema);
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    96
	elseif propschema is string then -- Teal says this can never be a string, but it could before so best be sure
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
    97
		error("schema as string is not supported: "..propschema.." {"..current_ns.."}"..propname)
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    98
	end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
    99
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   100
	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
   101
		value_where = "in_children"
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   102
	end
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   103
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   104
	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
   105
		local xml = propschema.xml
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   106
		if xml then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   107
			if xml.name then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   108
				name = xml.name
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   109
			end
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   110
			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
   111
				namespace = xml.namespace
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   112
			end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   113
			if xml.prefix then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   114
				prefix = xml.prefix
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   115
			end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   116
			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
   117
				value_where = "in_wrapper"
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   118
			elseif xml.attribute then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   119
				value_where = "in_attribute"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   120
			elseif xml.text then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   121
				value_where = "in_text"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   122
			elseif xml.x_name_is_value then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   123
				value_where = "in_tag_name"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   124
			elseif xml.x_single_attribute then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   125
				single_attribute = xml.x_single_attribute
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   126
				value_where = "in_single_attribute"
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   127
			end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   128
		end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   129
		if propschema["const"] then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   130
			enums = { propschema["const"] }
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   131
		elseif propschema["enum"] then
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   132
			enums = propschema["enum"]
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   133
		end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   134
	end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   135
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   136
	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
   137
end
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   138
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   139
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
   140
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
   141
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   142
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
   143
	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
   144
		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
   145
		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
   146
			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
   147
		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
   148
			-- XXX O(n²) ?
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   149
			-- 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
   150
			-- 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
   151
			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
   152
				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
   153
				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
   154
			end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   155
		else
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   156
			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
   157
		end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   158
		if c then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   159
			return c.name;
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   160
		end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   161
	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
   162
		local attr = name
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   163
		if prefix then
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   164
			attr = prefix .. ':' .. name
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   165
		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
   166
			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
   167
		end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   168
		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
   169
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   170
	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
   171
		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
   172
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   173
	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
   174
		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
   175
		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
   176
	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
   177
		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
   178
	end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   179
end
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   180
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   181
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
   182
	local out : { string : any } = {}
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   183
	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
   184
	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
   185
		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
   186
			propschema = resolve_schema(propschema, root)
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   187
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   188
			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
   189
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   190
			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
   191
				if proptype == "object" then
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   192
					local c = s:get_child(name, namespace)
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   193
					if c then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   194
						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
   195
					end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   196
				elseif proptype == "array" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   197
					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
   198
					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
   199
						out[prop] = a;
b2f9782497dd util.datamapper: Don't include empty unwrapped arrays
Kim Alvefur <zash@zash.se>
parents: 11483
diff changeset
   200
					end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   201
				else
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   202
					error "unreachable"
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   203
				end
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   204
			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
   205
				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
   206
				if wrapper then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   207
					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
   208
				end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   209
			else
11469
19a88b61ab4e util.datamapper: Factor out extraction of the XML part to use
Kim Alvefur <zash@zash.se>
parents: 11468
diff changeset
   210
				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
   211
11459
a5050e21ab08 util.datamapper: Separate extraction of xml from coercion to target type
Kim Alvefur <zash@zash.se>
parents: 11458
diff changeset
   212
				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
   213
			end
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   214
		end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   215
	end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   216
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   217
	return out
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   218
end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   219
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   220
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
   221
	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
   222
	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
   223
	local attr_name : string
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   224
	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
   225
		value_where = "in_attribute";
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   226
		attr_name = single_attribute;
c098d07e6717 util.datamapper: Finally implement support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11469
diff changeset
   227
	end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   228
	local out : { any } = {}
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   229
11475
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   230
	if proptype == "object" then
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   231
		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
   232
			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
   233
				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
   234
			end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   235
		else
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   236
			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
   237
		end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   238
	elseif proptype == "array" then
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   239
		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
   240
			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
   241
				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
   242
			end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   243
		end
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   244
	else
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   245
		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
   246
			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
   247
ab03de8e503e util.datamapper: Handle nested arrays or objects in arrays
Kim Alvefur <zash@zash.se>
parents: 11474
diff changeset
   248
			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
   249
		end
11461
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   250
	end
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   251
	return out;
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   252
end
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   253
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   254
local function parse (schema : json_schema_object, s : st.stanza_t) : table
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
   255
	local s_type = guess_schema_type(schema)
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
   256
	if s_type == "object" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   257
		return parse_object(schema, s, schema)
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
   258
	elseif s_type == "array" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   259
		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
   260
	else
6a51749af7f4 util.datamapper: Add initial support for parsing arrays
Kim Alvefur <zash@zash.se>
parents: 11460
diff changeset
   261
		error "top-level scalars unsupported"
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   262
	end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   263
end
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   264
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   265
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
   266
	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
   267
		return  v
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   268
	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
   269
		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
   270
	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
   271
		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
   272
	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
   273
		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
   274
	end
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   275
end
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   276
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   277
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
   278
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   279
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
   280
11471
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   281
	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
   282
		local attr = name
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   283
		if prefix then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   284
			attr = prefix .. ':' .. name
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   285
		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
   286
			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
   287
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   288
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   289
		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
   290
	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
   291
		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
   292
	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
   293
		assert(single_attribute)
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   294
		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
   295
11480
83e127eb91f9 util.datamapper: Deal with locally built stanzas missing xmlns
Kim Alvefur <zash@zash.se>
parents: 11479
diff changeset
   296
		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
   297
			propattr.xmlns = namespace
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   298
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   299
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   300
		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
   301
		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
   302
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   303
	else
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   304
		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
   305
		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
   306
			propattr = { xmlns = namespace }
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   307
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   308
		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
   309
			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
   310
				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
   311
			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
   312
				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
   313
			end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   314
		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
   315
			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
   316
			if c then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   317
				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
   318
			end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   319
		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
   320
			if value_where == "in_wrapper" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   321
				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
   322
				if c then
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   323
					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
   324
				end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   325
			else
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   326
				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
   327
			end
11479
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   328
		else
9bd36e871f05 util.datamapper: Factor out conversion from any value to XML string
Kim Alvefur <zash@zash.se>
parents: 11475
diff changeset
   329
			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
   330
		end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   331
	end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   332
end
88792dd2bee9 util.datamapper: Factor out handling of object properties for array reuse
Kim Alvefur <zash@zash.se>
parents: 11470
diff changeset
   333
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   334
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
   335
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   336
	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
   337
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   338
	if schema.xml then
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   339
		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
   340
			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
   341
		end
11465
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   342
		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
   343
			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
   344
		end
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   345
		-- TODO prefix?
766b0eddd12c util.datamapper: Deal with type name changes in util.jsonschema
Kim Alvefur <zash@zash.se>
parents: 11463
diff changeset
   346
	end
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   347
11466
d1982b7eb00d util.datamapper: Fix arrays nesting one level too deep
Kim Alvefur <zash@zash.se>
parents: 11465
diff changeset
   348
	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
   349
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
   350
	local s_type = guess_schema_type(schema)
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
   351
	if s_type == "object" then
11462
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   352
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   353
		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
   354
			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
   355
			local v = t[prop]
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   356
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   357
			if v ~= nil then
11460
4e376a43fe40 util.datamapper: Factor out common schema unpacking
Kim Alvefur <zash@zash.se>
parents: 11459
diff changeset
   358
				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
   359
				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
   360
			end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   361
		end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   362
		return out;
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   363
12584
a9dbf657c894 util.datamapper: Improve handling of schemas with non-obvious "type"
Kim Alvefur <zash@zash.se>
parents: 12137
diff changeset
   364
	elseif s_type == "array" then
12137
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   365
		local itemschema = resolve_schema(schema.items, root)
11060c8919b6 util.datamapper: Add support for $ref pointers
Kim Alvefur <zash@zash.se>
parents: 11485
diff changeset
   366
		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
   367
		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
   368
			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
   369
		end
0e00fa518688 util.datamapper: Limited support for unparsing simple arrays of strings
Kim Alvefur <zash@zash.se>
parents: 11461
diff changeset
   370
		return out;
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   371
	end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   372
end
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   373
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   374
return {
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   375
	parse = parse,
11440
5df9ffc25bb4 util.datamapper: Add 'unparse' for turning tables into XML
Kim Alvefur <zash@zash.se>
parents: 11439
diff changeset
   376
	unparse = unparse,
11439
a1fa6202fa13 util.datamapper: Library for extracting data from stanzas
Kim Alvefur <zash@zash.se>
parents:
diff changeset
   377
}