Commit f3a1f4bf authored by VIGNET Pierre's avatar VIGNET Pierre
Browse files

Ability to open bcx files with notes/innerText in nodes; documentation (absent before as usual)

parent 5d1534d4
......@@ -272,8 +272,13 @@ class XmlVisitor:
class MakeHandler(ContentHandler):
"""
make a handler for the parser
"""Make a handler for the parser when the model is loaded.
Users are expected to subclass ContentHandler to support their application.
The following methods are called by the parser on the appropriate events
in the input document:
https://docs.python.org/2/library/xml.sax.handler.html
"""
def __init__(self, model = None):
......@@ -282,56 +287,63 @@ class MakeHandler(ContentHandler):
self.pile_dict = []
self.node_dict = dict()
self.in_constraints = False
self.in_transition = False
self.constraints = ""
self.model = model
self.nodes_types = (
'CStartNode', 'CTrapNode', 'CSimpleNode', 'CPermNode', 'CInputNode'
)
# Memorize the current node/transition because of inner text (note)
# processing
self.current_element = None
def init_node_functions(self):
"""Bind functions to add different types of nodes to the cadbiom model
.. note:: Must be call after the init of self.top_pile with the xml root
object.
"""
self.add_node_functions = \
{
'CStartNode': self.top_pile.add_start_node,
'CTrapNode': self.top_pile.add_trap_node,
'CSimpleNode': self.top_pile.add_simple_node,
'CPermNode': self.top_pile.add_perm_node,
'CInputNode': self.top_pile.add_input_node,
}
def startElement(self, name, att):
"""Signal the start of an element
:param arg1: Contains the raw XML 1.0 name of the element.
:param arg2: Holds an object of the Attributes interface.
:type arg1: <str>
:type arg2: <xml.sax.xmlreader.AttributesImpl>
"""
#print(att.getNames())
if name == "model":
if not self.model:
self.model = ChartModel(att.get('name',''))
# Root is a virtual macronode on top of the hierarchy.
# A model can be a list of hierarchy grouped under this node.
root = self.model.get_root()
self.pile_node.append(root)
self.top_pile = root
self.init_node_functions()
new_dict = dict()
self.pile_dict.append(new_dict)
self.node_dict = new_dict
elif name == "CStartNode":
name = att.get('name', '').encode('ascii')
xloc = float(att.get('xloc', ''))
yloc = float(att.get('yloc', ''))
node = self.top_pile.add_start_node(xloc, yloc, name)
self.node_dict[name] = node
elif name == "CTrapNode":
name = att.get('name', '').encode('ascii')
xloc = float(att.get('xloc', '') )
yloc = float(att.get('yloc', '') )
node = self.top_pile.add_trap_node(xloc, yloc, name)
self.node_dict[name] = node
elif name == "CSimpleNode":
name = att.get('name', '').encode('ascii')
xloc = float(att.get('xloc', '') )
yloc = float(att.get('yloc', '') )
node = self.top_pile.add_simple_node(name, xloc, yloc)
self.node_dict[name] = node
elif name == "CPermNode":
name = att.get('name', '').encode('ascii')
xloc = float(att.get('xloc', '') )
yloc = float(att.get('yloc', '') )
node = self.top_pile.add_perm_node(name, xloc, yloc)
self.node_dict[name] = node
elif name == "CInputNode":
name = att.get('name', '').encode('ascii')
xloc = float(att.get('xloc', '') )
yloc = float(att.get('yloc', '') )
node = self.top_pile.add_input_node(name, xloc, yloc)
self.node_dict[name] = node
elif name in self.nodes_types:
# TODO: Uniformization of API in CMacroNode() class;
# the attribute 'name' should be at the same last position...
element_name = att.get('name', '').encode('ascii')
self.current_element = self.add_node_functions[name](
name=element_name,
xcoord=float(att.get('xloc', '')),
ycoord=float(att.get('yloc', '')),
)
self.node_dict[element_name] = self.current_element
elif name == "CMacroNode":
name = att.get('name', '').encode('ascii')
......@@ -370,46 +382,52 @@ class MakeHandler(ContentHandler):
try:
node_ori = self.node_dict[ori]
node_ext = self.node_dict[ext]
except Exception, exc:
print 'Bad xml file - missing nodes', ori, ' ', ext
print self.node_dict
print exc
except Exception as exc:
print('Bad xml file - missing nodes', ori, ' -> ', ext)
print(self.node_dict)
print(exc)
self.transition = self.top_pile.add_transition(node_ori, node_ext)
self.current_element = self.top_pile.add_transition(node_ori, node_ext)
# the transition may not be created (origin = ext for example)
if self.transition:
self.transition.set_event(event)
self.transition.set_condition(condition)
self.transition.set_action(action)
self.transition.fact_ids = fact_ids
self.in_transition = True
self.transition.note = ""
if self.current_element:
self.current_element.set_event(event)
self.current_element.set_condition(condition)
self.current_element.set_action(action)
self.current_element.fact_ids = fact_ids
elif name == 'constraints':
self.in_constraints = True
self.constraints = ""
else: # ignore
pass
def characters(self, chr):
"""Receive notification of character data.
The Parser will call this method to report each chunk of character data.
SAX parsers may return all contiguous character data in a single chunk,
or they may split it into several chunks;
=> we need to do a concatenation
:param arg1: chunck of characters.
:type arg1: <str>
"""
xxx
"""
# The current elem is a constraint, a transition or a node
# print("all", self.current_element, '<'+chr+'>')
if self.in_constraints:
self.constraints = self.constraints + chr
if self.in_transition:
self.transition.note = self.transition.note + chr
self.constraints += chr
elif self.current_element:
# node or transition is currently opened in startElement()
self.current_element.note += chr
def endElement (self, name):
"""Called when an elements ends
.. note:: We handle only elements that need post processing like
transitions and nodes: reset self.current_element that is used
to load notes (inner text of xml object).
"""
xxx
"""
if name == "model":
return
elif name == "CMacroNode":
if name == 'CMacroNode':
#self.top_pile = self.pile_node.pop()
self.pile_node.remove(self.top_pile)
self.top_pile = self.pile_node[-1]
......@@ -421,12 +439,9 @@ class MakeHandler(ContentHandler):
self.in_constraints = False
self.model.constraints = self.constraints + '\n'
elif name == 'transition':
self.in_transition = False
# if self.transition:
# self.transition.note = self.transition.note + '\n'
else:
pass
elif name == 'transition' or name in self.nodes_types:
# Close the current node or transition opened in startElement()
self.current_element = None
class MakeModelFromXmlFile:
......@@ -438,12 +453,11 @@ class MakeModelFromXmlFile:
self.handler = MakeHandler(model=self.model)
self.parser = make_parser()
self.parser.setContentHandler(self.handler)
try:
self.parser.parse(xml_file)
except Exception, exc:
print 'ERROR while xml parsing'
print exc
except Exception:
print('ERROR while xml parsing')
raise
def get_model(self):
......@@ -464,9 +478,9 @@ class MakeModelFromXmlString:
try:
PS(xml_string, self.handler)
except Exception, exc:
print 'ERROR while xml parsing'
print exc
except Exception as exc:
print('ERROR while xml parsing')
print(exc)
def get_model(self):
......
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