Software /
code /
prosody
Comparison
teal-src/util/datamapper.tl @ 11461:766b0eddd12c
util.datamapper: Deal with type name changes in util.jsonschema
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 19 Mar 2021 00:26:04 +0100 |
parent | 11459:86904555bffc |
child | 11462:d1982b7eb00d |
comparison
equal
deleted
inserted
replaced
11460:a8b4e04bc044 | 11461:766b0eddd12c |
---|---|
19 -- TODO cleanup / refactor | 19 -- TODO cleanup / refactor |
20 -- TODO s/number/integer/ once we have appropriate math.type() compat | 20 -- TODO s/number/integer/ once we have appropriate math.type() compat |
21 -- | 21 -- |
22 | 22 |
23 local st = require "util.stanza"; | 23 local st = require "util.stanza"; |
24 local js = require "util.jsonschema" | 24 local json = require"util.json" |
25 | |
26 local json_type_name = json.json_type_name; | |
27 local json_schema_object = require "util.jsonschema" | |
28 local type schema_t = boolean | json_type_name | json_schema_object | |
25 | 29 |
26 local function toboolean ( s : string ) : boolean | 30 local function toboolean ( s : string ) : boolean |
27 if s == "true" or s == "1" then | 31 if s == "true" or s == "1" then |
28 return true | 32 return true |
29 elseif s == "false" or s == "0" then | 33 elseif s == "false" or s == "0" then |
31 elseif s then | 35 elseif s then |
32 return true | 36 return true |
33 end | 37 end |
34 end | 38 end |
35 | 39 |
36 local function totype(t : js.schema_t.type_e, s : string) : any | 40 local function totype(t : json_type_name, s : string) : any |
37 if t == "string" then | 41 if t == "string" then |
38 return s; | 42 return s; |
39 elseif t == "boolean" then | 43 elseif t == "boolean" then |
40 return toboolean(s) | 44 return toboolean(s) |
41 elseif t == "number" or t == "integer" then | 45 elseif t == "number" or t == "integer" then |
51 "in_single_attribute" | 55 "in_single_attribute" |
52 "in_children" | 56 "in_children" |
53 "in_wrapper" | 57 "in_wrapper" |
54 end | 58 end |
55 | 59 |
56 local function unpack_propschema( propschema : js.schema_t | js.schema_t.type_e, propname : string, current_ns : string ) | 60 local function unpack_propschema( propschema : schema_t, propname : string, current_ns : string ) |
57 : js.schema_t.type_e, value_goes, string, string, string, string, { any } | 61 : json_type_name, value_goes, string, string, string, string, { any } |
58 local proptype : js.schema_t.type_e = "string" | 62 local proptype : json_type_name = "string" |
59 local value_where : value_goes = "in_text_tag" | 63 local value_where : value_goes = "in_text_tag" |
60 local name = propname | 64 local name = propname |
61 local namespace = current_ns | 65 local namespace = current_ns |
62 local prefix : string | 66 local prefix : string |
63 local single_attribute : string | 67 local single_attribute : string |
64 local enums : { any } | 68 local enums : { any } |
65 | 69 |
66 if propschema is js.schema_t then | 70 if propschema is json_schema_object then |
67 proptype = propschema.type | 71 proptype = propschema.type |
68 elseif propschema is js.schema_t.type_e then | 72 elseif propschema is json_type_name then |
69 proptype = propschema | 73 proptype = propschema |
70 end | 74 end |
71 | 75 |
72 if proptype == "object" or proptype == "array" then | 76 if proptype == "object" or proptype == "array" then |
73 value_where = "in_children" | 77 value_where = "in_children" |
74 end | 78 end |
75 | 79 |
76 if propschema is js.schema_t then | 80 if propschema is json_schema_object then |
77 local xml = propschema.xml | 81 local xml = propschema.xml |
78 if xml then | 82 if xml then |
79 if xml.name then | 83 if xml.name then |
80 name = xml.name | 84 name = xml.name |
81 end | 85 end |
106 end | 110 end |
107 | 111 |
108 return proptype, value_where, name, namespace, prefix, single_attribute, enums | 112 return proptype, value_where, name, namespace, prefix, single_attribute, enums |
109 end | 113 end |
110 | 114 |
111 local parse_object : function (schema : js.schema_t, s : st.stanza_t) : { string : any } | 115 local parse_object : function (schema : schema_t, s : st.stanza_t) : { string : any } |
112 local parse_array : function (schema : js.schema_t, s : st.stanza_t) : { any } | 116 local parse_array : function (schema : schema_t, s : st.stanza_t) : { any } |
113 | 117 |
114 function parse_object (schema : js.schema_t, s : st.stanza_t) : { string : any } | 118 function parse_object (schema : schema_t, s : st.stanza_t) : { string : any } |
115 local out : { string : any } = {} | 119 local out : { string : any } = {} |
116 if schema.properties then | 120 if schema is json_schema_object and schema.properties then |
117 for prop, propschema in pairs(schema.properties) do | 121 for prop, propschema in pairs(schema.properties) do |
118 | 122 |
119 local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns) | 123 local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns) |
120 | 124 |
121 local value : string | 125 local value : string |
150 elseif value_where == "in_single_attribute" then | 154 elseif value_where == "in_single_attribute" then |
151 local c = s:get_child(name, namespace) | 155 local c = s:get_child(name, namespace) |
152 value = c and c.attr[single_attribute] | 156 value = c and c.attr[single_attribute] |
153 elseif value_where == "in_text_tag" then | 157 elseif value_where == "in_text_tag" then |
154 value = s:get_child_text(name, namespace) | 158 value = s:get_child_text(name, namespace) |
155 elseif value_where == "in_children" and propschema is js.schema_t then | 159 elseif value_where == "in_children" and propschema is json_schema_object then |
156 if proptype == "object" then | 160 if proptype == "object" then |
157 local c = s:get_child(name, namespace) | 161 local c = s:get_child(name, namespace) |
158 if c then | 162 if c then |
159 out[prop] = parse_object(propschema, c); | 163 out[prop] = parse_object(propschema, c); |
160 end | 164 end |
161 elseif proptype == "array" then | 165 elseif proptype == "array" then |
162 out[prop] = parse_array(propschema, s); | 166 out[prop] = parse_array(propschema, s); |
163 else | 167 else |
164 error "unreachable" | 168 error "unreachable" |
165 end | 169 end |
166 elseif value_where == "in_wrapper" and propschema is js.schema_t and proptype == "array" then | 170 elseif value_where == "in_wrapper" and propschema is json_schema_object and proptype == "array" then |
167 local wrapper = s:get_child(name, namespace); | 171 local wrapper = s:get_child(name, namespace); |
168 if wrapper then | 172 if wrapper then |
169 out[prop] = parse_array(propschema, wrapper); | 173 out[prop] = parse_array(propschema, wrapper); |
170 else | 174 else |
171 error "unreachable" | 175 error "unreachable" |
172 end | 176 end |
173 else | 177 else |
174 error "unreachable" | 178 error "unreachable" |
175 end | 179 end |
176 if value_where ~= "in_children" and value_where ~= "in_wrapper" then | 180 if value_where ~= "in_children" and value_where ~= "in_wrapper" then |
177 out[prop] = totype(proptype, value) | 181 out[prop] = totype(proptype, value) |
180 end | 184 end |
181 | 185 |
182 return out | 186 return out |
183 end | 187 end |
184 | 188 |
185 function parse_array (schema : js.schema_t, s : st.stanza_t) : { any } | 189 function parse_array (schema : json_schema_object, s : st.stanza_t) : { any } |
186 local proptype, value_where, child_name, namespace = unpack_propschema(schema.items, nil, s.attr.xmlns) | 190 local proptype, value_where, child_name, namespace = unpack_propschema(schema.items, nil, s.attr.xmlns) |
187 local out : { any } = {} | 191 local out : { any } = {} |
188 for c in s:childtags(child_name, namespace) do | 192 for c in s:childtags(child_name, namespace) do |
189 local value : string; | 193 local value : string; |
190 if value_where == "in_text_tag" then | 194 if value_where == "in_text_tag" then |
200 end | 204 end |
201 end | 205 end |
202 return out; | 206 return out; |
203 end | 207 end |
204 | 208 |
205 local function parse (schema : js.schema_t, s : st.stanza_t) : table | 209 local function parse (schema : json_schema_object, s : st.stanza_t) : table |
206 if schema.type == "object" then | 210 if schema.type == "object" then |
207 return parse_object(schema, s) | 211 return parse_object(schema, s) |
208 elseif schema.type == "array" then | 212 elseif schema.type == "array" then |
209 return parse_array(schema, s) | 213 return parse_array(schema, s) |
210 else | 214 else |
211 error "top-level scalars unsupported" | 215 error "top-level scalars unsupported" |
212 end | 216 end |
213 end | 217 end |
214 | 218 |
215 local function unparse ( schema : js.schema_t, t : table, current_name : string, current_ns : string ) : st.stanza_t | 219 local function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string ) : st.stanza_t |
216 | 220 |
217 if schema.xml then | 221 if schema.xml then |
218 if schema.xml.name then | 222 if schema.xml.name then |
219 current_name = schema.xml.name | 223 current_name = schema.xml.name |
220 end | 224 end |
221 if schema.xml.namespace then | 225 if schema.xml.namespace then |
222 current_ns = schema.xml.namespace | 226 current_ns = schema.xml.namespace |
223 end | 227 end |
224 -- TODO prefix? | 228 -- TODO prefix? |
225 end | 229 end |
226 | 230 |
227 local out = st.stanza(current_name, { xmlns = current_ns }) | 231 local out = st.stanza(current_name, { xmlns = current_ns }) |
228 | 232 |
229 if schema.type == "object" then | 233 if schema.type == "object" then |
230 | 234 |
231 for prop, propschema in pairs(schema.properties) do | 235 for prop, propschema in pairs(schema.properties) do |
232 local v = t[prop] | 236 local v = t[prop] |
291 out:text_tag(name, string.format("%g", v), propattr) | 295 out:text_tag(name, string.format("%g", v), propattr) |
292 elseif proptype == "integer" and v is number then -- TODO is integer | 296 elseif proptype == "integer" and v is number then -- TODO is integer |
293 out:text_tag(name, string.format("%d", v), propattr) | 297 out:text_tag(name, string.format("%d", v), propattr) |
294 elseif proptype == "boolean" and v is boolean then | 298 elseif proptype == "boolean" and v is boolean then |
295 out:text_tag(name, v and "1" or "0", propattr) | 299 out:text_tag(name, v and "1" or "0", propattr) |
296 elseif proptype == "object" and propschema is js.schema_t and v is table then | 300 elseif proptype == "object" and propschema is json_schema_object and v is table then |
297 local c = unparse(propschema, v, name, namespace); | 301 local c = unparse(propschema, v, name, namespace); |
298 if c then | 302 if c then |
299 out:add_direct_child(c); | 303 out:add_direct_child(c); |
300 end | 304 end |
301 elseif proptype == "array" and propschema is js.schema_t and v is table then | 305 elseif proptype == "array" and propschema is json_schema_object and v is table then |
302 local c = unparse(propschema, v, name, namespace); | 306 local c = unparse(propschema, v, name, namespace); |
303 if c then | 307 if c then |
304 if value_where == "in_wrapper" then | 308 if value_where == "in_wrapper" then |
305 local w = st.stanza(propschema.xml.name or name, { xmlns = propschema.xml.namespace or namespace }) | 309 local w = st.stanza(propschema.xml.name or name, { xmlns = propschema.xml.namespace or namespace }) |
306 w:add_direct_child(c); | 310 w:add_direct_child(c); |