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