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);