Commit 978ce280 authored by VIGNET Pierre's avatar VIGNET Pierre
Browse files

[lib] XmlVisitor: Refactor this shit code...

parent 8c7f586c
......@@ -52,6 +52,7 @@ Classes::
from __future__ import unicode_literals
from __future__ import print_function
import itertools as it
from collections import OrderedDict
from xml.sax import make_parser
from xml.sax import parseString
......@@ -71,8 +72,9 @@ class XmlVisitor:
def __init__(self, model):
self.model = model
self.fact_list = []
self.xml = "" # string: xml representation of model
self.symb = set() # symbol set used to check double naming of nodes
self.xml = ""
self.symb = set()
self.default_node_attributes = ("name", "xloc", "yloc", "wloc", "hloc")
self.visit_chart_model()
def visit_chart_model(self):
......@@ -90,97 +92,110 @@ class XmlVisitor:
else:
self.symb.add(name)
def visit_cstart_node(self, snode):
"""
Generate xml representation of a start node
def get_existing_attributes(self, node):
"""Return dict of attributes of the given node
.. note:: The set of attributes are defined in the default_node_attributes
attribute of the current class.
.. note:: We use OrderedDict in order to improve human readability of
the produced models.
:return: Dictionary of attributes.
Keys: names of attributes; Values: Values of attributes;
Note that values are converted to strings in order to fit with lxml
requirements.
:rtype: <OrderedDict <str>:<str>>
"""
tag = "CStartNode"
attrname = ["name", "xloc", "yloc"]
return OrderedDict((
(attr_name, str(node.__dict__[attr_name])) for attr_name in self.default_node_attributes
if node.__dict__.get(attr_name, None)
))
attr = [snode.name, snode.xloc, snode.yloc]
return [tag, attrname, attr]
def visit_cstart_node(self, snode):
"""Return tag name and formated attributes of a start node
def visit_ctrap_node(self, tnode):
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
Generate xml representation of a trap node
# double declaration is allowed
return "CStartNode", self.get_existing_attributes(snode)
def visit_ctrap_node(self, tnode):
"""Return tag name and formated attributes of a trap node
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
tag = "CTrapNode"
attrname = ["name", "xloc", "yloc"]
attr = [tnode.name, tnode.xloc, tnode.yloc]
return [tag, attrname, attr]
# double declaration is allowed
return "CTrapNode", self.get_existing_attributes(tnode)
def visit_csimple_node(self, sin):
"""
Generate xml representation of a simple node
"""Return tag name and formated attributes of a simple node
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
self.check_name(sin.name)
tag = "CSimpleNode"
attrname = ["name", "xloc", "yloc"]
attr = [sin.name, sin.xloc, sin.yloc]
return [tag, attrname, attr]
return "CSimpleNode", self.get_existing_attributes(sin)
def visit_cperm_node(self, pnode):
"""
Generate xml representation of a perm node
"""Return tag name and formated attributes of a perm node
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
self.check_name(pnode.name)
tag = "CPermNode"
attrname = ["name", "xloc", "yloc"]
attr = [pnode.name, pnode.xloc, pnode.yloc]
return [tag, attrname, attr]
return "CPermNode", self.get_existing_attributes(pnode)
def visit_cinput_node(self, inn):
"""Return tag name and formated attributes of an input node
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
Generate xml representation of an input node
"""
# double declaration of input nodes is allowed"
tag = "CInputNode"
attrname = ["name", "xloc", "yloc"]
attr = [inn.name, inn.xloc, inn.yloc]
return [tag, attrname, attr]
# double declaration is allowed
return "CInputNode", self.get_existing_attributes(inn)
def visit_cmacro_node(self, mnode):
"""
Generate xml representation of a macro node
"""Explore subnodes and transitions in the given macro node.
Return tag name and formated attributes of a macro node.
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
self.check_name(mnode.name)
save_macro = self.current_element
tag = "CMacroNode"
attrname = ["name", "xloc", "yloc", "wloc", "hloc"]
attr = [mnode.name, mnode.xloc, mnode.yloc, mnode.wloc, mnode.hloc]
# Get attributes
# Keys: attr names; Values: attr values
attrs = self.get_existing_attributes(mnode)
macro = etree.SubElement(self.current_element, tag)
# Create new XML tag
macro = etree.SubElement(self.current_element, tag, attrs)
self.current_element = macro
# Update attributes of the element
# Keys: attr names; Values: attr values
macro.attrib.update(dict(zip(attrname, attr)))
# nodes
for snode in mnode.sub_nodes:
properties = snode.accept(self)
if properties[0] == "CMacroNode":
tag, attrs = snode.accept(self)
if tag == "CMacroNode":
self.current_element = macro
else:
subel = etree.SubElement(self.current_element, properties[0])
attrname = properties[1]
attr = [str(val) for val in properties[2]]
subel.attrib.update(dict(zip(attrname, attr)))
etree.SubElement(self.current_element, tag, attrs)
# transitions
for transition in it.chain(*mnode.transitions):
properties = transition.accept(self)
sub_tr = etree.SubElement(self.current_element, properties[0])
attrname = properties[1]
attr = [str(val) for val in properties[2]]
sub_tr.attrib.update(dict(zip(attrname, attr)))
tag, attrs = transition.accept(self)
etree.SubElement(self.current_element, tag, attrs)
self.current_element = save_macro
return [tag, attrname, attr]
return tag, attrs
def visit_ctop_node(self, tnode):
"""Interative build of xml tree for model saving
"""Interative build of XML tree for model saving
.. note:: namespace seems to be useless regarding nsmap here,
because we use the default namespace without prefix...
......@@ -200,16 +215,12 @@ class XmlVisitor:
def create_xml_element(entity):
"""Create XML element and add it to root object"""
# get node or transition properties
properties = entity.accept(self)
if properties[0] != "CMacroNode":
element = etree.Element(properties[0])
if len(properties) > 1:
attrname = properties[1]
attr = properties[2]
attributes = element.attrib
# Set attributes and values (name, event, coords...)
for i in range(0, len(attrname)):
attributes[attrname[i]] = str(attr[i])
tag, attrs = entity.accept(self)
if tag != "CMacroNode":
# Create new XML tag
# Set attributes and values (name, event, coords...)
element = etree.Element(tag, attrs)
# Add notes/text of element
if entity.note:
element.text = entity.note
......@@ -223,7 +234,8 @@ class XmlVisitor:
[create_xml_element(trans) for trans in it.chain(*tnode.transitions)]
# constraints
if len(tnode.model.constraints) > 0:
if tnode.model.constraints:
# There is text on constraints
const = etree.Element("constraints")
const.text = tnode.model.constraints
xmodel.append(const)
......@@ -234,25 +246,32 @@ class XmlVisitor:
# print(etree.tostring(xmodel,pretty_print=True))
def visit_ctransition(self, trans):
"""Return tag name and formated attributes of a transition
:return: Tuple of tag name and OrderedDict of attributes
:rtype: <str>, <OrderedDict <str>:<str>>
"""
Generate xml representation of a transition
"""
tag = "transition"
attrname = ["ori", "ext", "event", "condition", "action", "fact_ids"]
attr = [
# Mandatory attributes
attr_names = ("ori", "ext", "event", "condition")
attr_values = (
trans.ori.name,
trans.ext.name,
trans.event,
trans.condition,
trans.action,
trans.fact_ids,
]
)
attrs = OrderedDict(zip(attr_names, attr_values))
# Optional attributes
attr_names = ("action", "fact_ids")
attrs.update({
attr_name: str(trans.__dict__[attr_name]) for attr_name in attr_names
if trans.__dict__[attr_name]
})
fact_ids = trans.fact_ids
for fact in fact_ids:
self.fact_list.append(fact)
# Merge facts of the transition with XmlVisitor (why?)
self.fact_list += trans.fact_ids
return [tag, attrname, attr]
return "transition", attrs
def return_xml(self):
"""Return the model as xml string.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment