acrn-hypervisor/misc/config_tools/scenario_config/scenario_transformer.py
Weiyi-Feng 06b942f5eb config_tools: Add vue-json-schema-form and advanced custom component for IVSHMEM field
1. add Vue devtools support
2. update project dependencies
3. refactor configurator source code tree for private library hook
4. fix build issue
5. dynamic load scenario JSON schema(fix cache issue)
6. add vjsf 1.12.2 (latest) for private package dependencies
7. remove vjsf unnecessary files
8. use private vjsf as configurator dependencies
9. Add custom IVSHMEM_REGION widget
10. add a script to populate default values
11. get default values before export scenario xml
12. specify widgets in XML schema
13. add missing vjsf license file
14. populate default values to empty nodes
15. when user clicks save button, update formData with each field default value
16. fix when the user clicks the save button will collapse configFom
17. add success message for saving scenario XML

vue-json-schema-form 1.12.2 (latest)link: b30ea7c2d6/packages/lib

Tracked-On: #6691
Signed-off-by: Weiyi Feng <weiyix.feng@intel.com>
2022-05-08 15:52:28 +08:00

112 lines
4.9 KiB
Python

#!/usr/bin/env python3
#
# Copyright (C) 2022 Intel Corporation.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import elementpath
class ScenarioTransformer:
xpath_ns = {
"xs": "http://www.w3.org/2001/XMLSchema",
}
@classmethod
def get_node(cls, element, xpath):
return element.find(xpath, namespaces=cls.xpath_ns)
def __init__(self, xsd_etree, visit_optional_node=False):
self.xsd_etree = xsd_etree
self.xml_etree = None
self._visit_optional_node = visit_optional_node
def type_of_element(self, type_tag, xsd_element_node, xml_node):
xsd_alternative_node = xsd_element_node
if xml_node is not None:
for alternative in xsd_element_node.findall("xs:alternative", namespaces=self.xpath_ns):
if elementpath.select(xml_node, alternative.get("test")):
xsd_alternative_node = alternative
break
type_node = xsd_alternative_node.find(type_tag, namespaces=self.xpath_ns)
if type_node is None:
type_name = xsd_alternative_node.get("type")
if type_name:
type_node = self.get_node(self.xsd_etree, f".//{type_tag}[@name='{type_name}']")
return type_node
def simple_type_of_element(self, xsd_element_node, xml_node = None):
return self.type_of_element("xs:simpleType", xsd_element_node, xml_node)
def complex_type_of_element(self, xsd_element_node, xml_node = None):
return self.type_of_element("xs:complexType", xsd_element_node, xml_node)
def transform_node(self, xsd_element_node, xml_node):
complex_type_node = self.complex_type_of_element(xsd_element_node, xml_node)
if complex_type_node is not None:
xsd_sequence_node = complex_type_node.find("xs:sequence", namespaces=self.xpath_ns)
if xsd_sequence_node is not None:
self.transform_sequence(xsd_sequence_node, xml_node)
xsd_all_node = complex_type_node.find("xs:all", namespaces=self.xpath_ns)
if xsd_all_node is not None:
self.transform_all(xsd_all_node, xml_node)
def transform_sequence(self, xsd_sequence_node, xml_node):
children = list(enumerate(list(xml_node)))
for xsd_element_node in xsd_sequence_node.findall("xs:element", namespaces=self.xpath_ns):
element_name = xsd_element_node.get("name")
element_min_occurs = xsd_element_node.get("minOccurs")
if len(children) == 0 or children[0][1].tag != element_name:
if self._visit_optional_node or element_min_occurs != "0":
index = children[0][0] if len(children) > 0 else None
self.add_and_transform_missing_node(xsd_element_node, xml_node, new_node_index=index)
else:
while len(children) > 0 and children[0][1].tag == element_name:
xml_child_node = children.pop(0)[1]
if self.complex_type_of_element(xsd_element_node, xml_child_node) is None and not xml_child_node.text:
self.fill_empty_node(xsd_element_node, xml_node, xml_child_node)
self.transform_node(xsd_element_node, xml_child_node)
def transform_all(self, xsd_all_node, xml_node):
for xsd_element_node in xsd_all_node.findall("xs:element", namespaces=self.xpath_ns):
element_name = xsd_element_node.get("name")
if not element_name:
continue
xml_children = xml_node.findall(element_name)
if len(xml_children) == 0:
element_min_occurs = xsd_element_node.get("minOccurs")
if self._visit_optional_node or element_min_occurs != "0":
self.add_and_transform_missing_node(xsd_element_node, xml_node)
else:
for xml_child_node in xml_children:
if self.complex_type_of_element(xsd_element_node, xml_child_node) is None and not xml_child_node.text:
self.fill_empty_node(xsd_element_node, xml_node, xml_child_node)
self.transform_node(xsd_element_node, xml_child_node)
def add_and_transform_missing_node(self, xsd_element_node, xml_parent_node, new_node_index=None):
for new_node in self.add_missing_nodes(xsd_element_node, xml_parent_node, new_node_index):
self.transform_node(xsd_element_node, new_node)
def add_missing_nodes(self, xsd_element_node, xml_parent_node, new_node_index):
return []
def fill_empty_node(self, xsd_element_node, xml_parent_node, xml_empty_node):
pass
def transform(self, xml_etree):
self.xml_etree = xml_etree
xml_root_node = xml_etree.getroot()
xsd_root_node = self.get_node(self.xsd_etree, f".//xs:element[@name='{xml_root_node.tag}']")
if xsd_root_node is not None:
self.transform_node(xsd_root_node, xml_root_node)
self.xml_etree = None