renaming to src/neco to src/nepi
[nepi.git] / src / nepi / util / parser.py
1 from neco.design.box import Box
2
3 from xml.dom import minidom
4 import sys
5
6 STRING = "string"
7 BOOL = "bool"
8 INTEGER = "integer"
9 DOUBLE = "float"
10
11 def xmlencode(s):
12     if isinstance(s, str):
13         rv = s.decode("latin1")
14     elif not isinstance(s, unicode):
15         rv = unicode(s)
16     else:
17         rv = s
18     return rv.replace(u'\x00',u'�')
19
20 def xmldecode(s):
21     return s.replace(u'&#0000',u'\x00').encode("utf8")
22
23 def from_type(value):
24     if isinstance(value, str):
25         return STRING
26     if isinstance(value, bool):
27         return BOOL
28     if isinstance(value, int):
29         return INTEGER
30     if isinstance(value, float):
31         return DOUBLE
32
33 def to_type(type, value):
34     if type == STRING:
35         return str(value)
36     if type == BOOL:
37         return value == "True"
38     if type == INTEGER:
39         return int(value)
40     if type == DOUBLE:
41         return float(value)
42
43 class XMLParser(object):
44     def to_xml(self, box):
45         doc = minidom.Document()
46
47         root = doc.createElement("boxes")
48         doc.appendChild(root)
49
50         traversed = dict()
51         self._traverse_boxes(doc, traversed, box)
52
53         # Keep the order
54         for guid in sorted(traversed.keys()):
55             bnode = traversed[guid]
56             root.appendChild(bnode)
57        
58         try:
59             xml = doc.toprettyxml(indent="    ", encoding="UTF-8")
60         except:
61             print >>sys.stderr, "Oops: generating XML from %s" % (data,)
62             raise
63         
64         return xml
65
66     def _traverse_boxes(self, doc, traversed, box):
67         bnode = doc.createElement("box")
68         bnode.setAttribute("guid", xmlencode(box.guid))
69         bnode.setAttribute("label", xmlencode(box.label))
70         bnode.setAttribute("x", xmlencode(box.x))
71         bnode.setAttribute("y", xmlencode(box.y))
72         bnode.setAttribute("width", xmlencode(box.width))
73         bnode.setAttribute("height", xmlencode(box.height))
74
75         traversed[box.guid] = bnode
76
77         anode = doc.createElement("attributes")
78         bnode.appendChild(anode)
79         for name in sorted(box.attributes):
80             value = getattr(box.a, name)
81             aanode = doc.createElement("attribute")
82             anode.appendChild(aanode)
83             aanode.setAttribute("name", xmlencode(name))
84             aanode.setAttribute("value", xmlencode(value))
85             aanode.setAttribute("type", from_type(value))
86
87         tnode = doc.createElement("tags")
88         bnode.appendChild(tnode)
89         for tag in sorted(box.tags):
90             ttnode = doc.createElement("tag")
91             tnode.appendChild(ttnode)
92             ttnode.setAttribute("name", xmlencode(tag))
93
94         cnode = doc.createElement("connections")
95         bnode.appendChild(cnode)
96         for b in sorted(box.connections):
97             ccnode = doc.createElement("connection")
98             cnode.appendChild(ccnode)
99             ccnode.setAttribute("guid", xmlencode(b.guid))
100             if b.guid not in traversed:
101                 self._traverse_boxes(doc, traversed, b)
102
103     def from_xml(self, xml):
104         doc = minidom.parseString(xml)
105         bnode_list = doc.getElementsByTagName("box")
106
107         boxes = dict()
108         connections = dict()
109
110         for bnode in bnode_list:
111             if bnode.nodeType == doc.ELEMENT_NODE:
112                 guid = int(bnode.getAttribute("guid"))
113                 label = xmldecode(bnode.getAttribute("label"))
114                 x = float(bnode.getAttribute("x"))
115                 y = float(bnode.getAttribute("y"))
116                 height = float(bnode.getAttribute("height"))
117                 width = float(bnode.getAttribute("width"))
118                 box = Box(label=label, guid=guid)
119                 boxes[guid] = box
120
121                 anode_list = bnode.getElementsByTagName("attribute") 
122                 for anode in anode_list:
123                     name = xmldecode(anode.getAttribute("name"))
124                     value = xmldecode(anode.getAttribute("value"))
125                     type = xmldecode(anode.getAttribute("type"))
126                     value = to_type(type, value)
127                     setattr(box.a, name, value)
128                     
129                 tnode_list = bnode.getElementsByTagName("tag") 
130                 for tnode in tnode_list:
131                     value = xmldecode(tnode.getAttribute("name"))
132                     box.tadd(value)
133
134                 connections[box] = set()
135                 cnode_list = bnode.getElementsByTagName("connection")
136                 for cnode in cnode_list:
137                     guid = int(cnode.getAttribute("guid"))
138                     connections[box].add(guid)
139
140         for box, conns in connections.iteritems():
141             for guid in conns:
142                 b = boxes[guid]
143                 box.connect(b)
144
145         return box
146
147