Attention une mise à jour du service Gitlab va être effectuée le mardi 18 janvier (et non lundi 17 comme annoncé précédemment) entre 18h00 et 18h30. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes.

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.
......
Markdown is supported
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