1#!/usr/bin/env python3
2__package__ = 'configurator.pyodide'
3
4import json
5
6import xmltodict
7
8from . import convert_result, nuc11_scenario, IS_WEB
9
10if IS_WEB:
11    # load js function from
12    # misc/config_tools/configurator/packages/configurator/src/pyodide.js
13    # by pyodide js library
14    # noinspection PyUnresolvedReferences
15    from js import __dynamic__load__scenario__from__pyodide__
16
17    scenario_json_schema = __dynamic__load__scenario__from__pyodide__()
18else:
19    from . import scenario_json_schema
20
21
22def get_array_and_int_keys():
23    array_keys = []
24    int_keys = ['@id']
25
26    def object_mapper(obj):
27        if not isinstance(obj, dict):
28            return obj
29        for key, value in obj.items():
30            if not isinstance(value, dict):
31                continue
32            if value.get('type', '') == 'array':
33                array_keys.append(key)
34            elif value.get('type', '') == 'integer':
35                int_keys.append(key)
36        return obj
37
38    json.loads(scenario_json_schema, object_hook=object_mapper)
39    array_keys = list(set(array_keys))
40    int_keys = list(set(int_keys))
41    return array_keys, int_keys
42
43
44def load_scenario_xml(scenario):
45    """
46    convert scenario xml to json data followed scenario json schema
47
48    :type scenario: str
49    :param scenario: scenario xml text
50    :return:
51    """
52    arr_keys, int_keys = get_array_and_int_keys()
53    scenario_xml = xmltodict.parse(scenario)
54    scenario_xml = json.dumps(scenario_xml)
55
56    def correct_struct(obj):
57        if not isinstance(obj, dict):
58            return obj
59        keys_need_remove = []
60        for key, value in obj.items():
61            if value is None:
62                keys_need_remove.append(key)
63                continue
64            if key in int_keys:
65                if isinstance(obj[key], list):
66                    obj[key] = [int(x) for x in obj[key]]
67                elif not isinstance(value, int):
68                    obj[key] = int(value)
69            if key in arr_keys and not isinstance(value, list):
70                obj[key] = [value]
71        for key in keys_need_remove:
72            del obj[key]
73        return obj
74
75    scenario_dict = json.loads(scenario_xml, object_hook=correct_struct)
76    return scenario_dict
77
78
79def main(scenario):
80    result = load_scenario_xml(scenario)
81    return convert_result(result)
82
83
84def test():
85    main(nuc11_scenario)
86
87
88if __name__ == '__main__':
89    test()
90