Software /
code /
prosody
Comparison
teal-src/util/datamapper.tl @ 11467:88792dd2bee9
util.datamapper: Factor out handling of object properties for array reuse
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 20 Mar 2021 21:25:45 +0100 |
parent | 11466:c098d07e6717 |
child | 11468:348b191cd850 |
comparison
equal
deleted
inserted
replaced
11466:c098d07e6717 | 11467:88792dd2bee9 |
---|---|
214 else | 214 else |
215 error "top-level scalars unsupported" | 215 error "top-level scalars unsupported" |
216 end | 216 end |
217 end | 217 end |
218 | 218 |
219 local function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string, ctx : st.stanza_t ) : st.stanza_t | 219 local unparse : function (json_schema_object, table, string, string, st.stanza_t) : st.stanza_t |
220 | |
221 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) | |
222 if value_where == "in_attribute" then | |
223 local attr = name | |
224 if prefix then | |
225 attr = prefix .. ':' .. name | |
226 elseif namespace ~= current_ns then | |
227 attr = namespace .. "\1" .. name | |
228 end | |
229 | |
230 if proptype == "string" and v is string then | |
231 out.attr[attr] = v | |
232 elseif proptype == "number" and v is number then | |
233 out.attr[attr] = string.format("%g", v) | |
234 elseif proptype == "integer" and v is number then -- TODO is integer | |
235 out.attr[attr] = string.format("%d", v) | |
236 elseif proptype == "boolean" then | |
237 out.attr[attr] = v and "1" or "0" | |
238 end | |
239 elseif value_where == "in_text" then | |
240 if v is string then | |
241 out:text(v) | |
242 end | |
243 elseif value_where == "in_single_attribute" then | |
244 assert(single_attribute) | |
245 local propattr : { string : string } = {} | |
246 | |
247 if namespace ~= current_ns then | |
248 propattr.xmlns = namespace | |
249 end | |
250 | |
251 if proptype == "string" and v is string then | |
252 propattr[single_attribute] = v | |
253 elseif proptype == "number" and v is number then | |
254 propattr[single_attribute] = string.format("%g", v) | |
255 elseif proptype == "integer" and v is number then -- TODO is integer | |
256 propattr[single_attribute] = string.format("%d", v) | |
257 elseif proptype == "boolean" and v is boolean then | |
258 propattr[single_attribute] = v and "1" or "0" | |
259 end | |
260 out:tag(name, propattr):up(); | |
261 | |
262 else | |
263 local propattr : { string : string } | |
264 if namespace ~= current_ns then | |
265 propattr = { xmlns = namespace } | |
266 end | |
267 if value_where == "in_tag_name" then | |
268 if proptype == "string" and v is string then | |
269 out:tag(v, propattr):up(); | |
270 elseif proptype == "boolean" and v == true then | |
271 out:tag(name, propattr):up(); | |
272 end | |
273 elseif proptype == "string" and v is string then | |
274 out:text_tag(name, v, propattr) | |
275 elseif proptype == "number" and v is number then | |
276 out:text_tag(name, string.format("%g", v), propattr) | |
277 elseif proptype == "integer" and v is number then -- TODO is integer | |
278 out:text_tag(name, string.format("%d", v), propattr) | |
279 elseif proptype == "boolean" and v is boolean then | |
280 out:text_tag(name, v and "1" or "0", propattr) | |
281 elseif proptype == "object" and propschema is json_schema_object and v is table then | |
282 local c = unparse(propschema, v, name, namespace); | |
283 if c then | |
284 out:add_direct_child(c); | |
285 end | |
286 elseif proptype == "array" and propschema is json_schema_object and v is table then | |
287 if value_where == "in_wrapper" then | |
288 local c = unparse(propschema, v, name, namespace); | |
289 if c then | |
290 out:add_direct_child(c); | |
291 end | |
292 else | |
293 unparse(propschema, v, name, namespace, out); | |
294 end | |
295 end | |
296 end | |
297 end | |
298 | |
299 function unparse ( schema : json_schema_object, t : table, current_name : string, current_ns : string, ctx : st.stanza_t ) : st.stanza_t | |
220 | 300 |
221 if schema.xml then | 301 if schema.xml then |
222 if schema.xml.name then | 302 if schema.xml.name then |
223 current_name = schema.xml.name | 303 current_name = schema.xml.name |
224 end | 304 end |
234 | 314 |
235 for prop, propschema in pairs(schema.properties) do | 315 for prop, propschema in pairs(schema.properties) do |
236 local v = t[prop] | 316 local v = t[prop] |
237 | 317 |
238 if v ~= nil then | 318 if v ~= nil then |
239 | |
240 local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(propschema, prop, current_ns) | 319 local proptype, value_where, name, namespace, prefix, single_attribute = unpack_propschema(propschema, prop, current_ns) |
241 | 320 unparse_property(out, v, proptype, propschema, value_where, name, namespace, current_ns, prefix, single_attribute) |
242 if value_where == "in_attribute" then | |
243 local attr = name | |
244 if prefix then | |
245 attr = prefix .. ':' .. name | |
246 elseif namespace ~= current_ns then | |
247 attr = namespace .. "\1" .. name | |
248 end | |
249 | |
250 if proptype == "string" and v is string then | |
251 out.attr[attr] = v | |
252 elseif proptype == "number" and v is number then | |
253 out.attr[attr] = string.format("%g", v) | |
254 elseif proptype == "integer" and v is number then -- TODO is integer | |
255 out.attr[attr] = string.format("%d", v) | |
256 elseif proptype == "boolean" then | |
257 out.attr[attr] = v and "1" or "0" | |
258 end | |
259 elseif value_where == "in_text" then | |
260 if v is string then | |
261 out:text(v) | |
262 end | |
263 elseif value_where == "in_single_attribute" then | |
264 local propattr : { string : string } = {} | |
265 | |
266 if namespace ~= current_ns then | |
267 propattr.xmlns = namespace | |
268 end | |
269 | |
270 if proptype == "string" and v is string then | |
271 propattr[single_attribute] = v | |
272 elseif proptype == "number" and v is number then | |
273 propattr[single_attribute] = string.format("%g", v) | |
274 elseif proptype == "integer" and v is number then -- TODO is integer | |
275 propattr[single_attribute] = string.format("%d", v) | |
276 elseif proptype == "boolean" and v is boolean then | |
277 propattr[single_attribute] = v and "1" or "0" | |
278 end | |
279 out:tag(name, propattr):up(); | |
280 | |
281 else | |
282 local propattr : { string : string } | |
283 if namespace ~= current_ns then | |
284 propattr = { xmlns = namespace } | |
285 end | |
286 if value_where == "in_tag_name" then | |
287 if proptype == "string" and v is string then | |
288 out:tag(v, propattr):up(); | |
289 elseif proptype == "boolean" and v == true then | |
290 out:tag(name, propattr):up(); | |
291 end | |
292 elseif proptype == "string" and v is string then | |
293 out:text_tag(name, v, propattr) | |
294 elseif proptype == "number" and v is number then | |
295 out:text_tag(name, string.format("%g", v), propattr) | |
296 elseif proptype == "integer" and v is number then -- TODO is integer | |
297 out:text_tag(name, string.format("%d", v), propattr) | |
298 elseif proptype == "boolean" and v is boolean then | |
299 out:text_tag(name, v and "1" or "0", propattr) | |
300 elseif proptype == "object" and propschema is json_schema_object and v is table then | |
301 local c = unparse(propschema, v, name, namespace); | |
302 if c then | |
303 out:add_direct_child(c); | |
304 end | |
305 elseif proptype == "array" and propschema is json_schema_object and v is table then | |
306 if value_where == "in_wrapper" then | |
307 local c = unparse(propschema, v, name, namespace); | |
308 if c then | |
309 out:add_direct_child(c); | |
310 end | |
311 else | |
312 unparse(propschema, v, name, namespace, out); | |
313 end | |
314 else | |
315 error "NYI" | |
316 end | |
317 end | |
318 end | 321 end |
319 end | 322 end |
320 return out; | 323 return out; |
321 | 324 |
322 elseif schema.type == "array" then | 325 elseif schema.type == "array" then |