fixed shebangs in non executable .py files
[nepi.git] / src / nepi / util / parser / _xml.py
1 # -*- coding: utf-8 -*-
2
3 from nepi.core.attributes import Attribute
4 from nepi.util.parser.base import ExperimentData, ExperimentParser
5 from xml.dom import minidom
6
7 import sys
8
9 def xmlencode(s):
10     if isinstance(s, str):
11         rv = s.decode("latin1")
12     elif not isinstance(s, unicode):
13         rv = unicode(s)
14     else:
15         rv = s
16     return rv.replace(u'\x00',u'�')
17
18 def xmldecode(s):
19     return s.replace(u'&#0000',u'\x00').encode("utf8")
20
21 class XmlExperimentParser(ExperimentParser):
22     def to_xml(self, experiment_description=None, data=None):
23         if experiment_description is not None:
24             data = self.to_data(experiment_description)
25         elif data is None:
26             raise TypeError, "XmlExperimentParser.to_xml needs either 'experiment_description' or 'data' arguments"
27         doc = minidom.Document()        
28         exp_tag = doc.createElement("experiment")
29         testbeds_tag = doc.createElement("testbeds")
30         exp_tag.appendChild(testbeds_tag)
31
32         elements_tags = dict()
33         for guid in sorted(data.guids):
34             if data.is_testbed_data(guid):
35                 elements_tag = self.testbed_data_to_xml(doc, testbeds_tag, guid, data)
36                 elements_tags[guid] = elements_tag
37             else:
38                 self.box_data_to_xml(doc, elements_tags, guid, data)
39         doc.appendChild(exp_tag)
40         
41         try:
42             xml = doc.toprettyxml(indent="    ", encoding="UTF-8")
43         except:
44             print >>sys.stderr, "Oops: generating XML from %s" % (data,)
45             raise
46         
47         return xml
48
49     def testbed_data_to_xml(self, doc, parent_tag, guid, data):
50         testbed_tag = doc.createElement("testbed") 
51         testbed_tag.setAttribute("guid", xmlencode(guid))
52         (testbed_id, testbed_version) = data.get_testbed_data(guid)
53         testbed_tag.setAttribute("testbed_id", xmlencode(testbed_id))
54         testbed_tag.setAttribute("testbed_version", xmlencode(testbed_version))
55         parent_tag.appendChild(testbed_tag)
56         self.graphical_info_data_to_xml(doc, testbed_tag, guid, data)
57         self.attributes_data_to_xml(doc, testbed_tag, guid, data)
58         elements_tag = doc.createElement("elements")
59         testbed_tag.appendChild(elements_tag)
60         return elements_tag
61
62     def box_data_to_xml(self, doc, elements_tags, guid, data):
63         (testbed_guid, factory_id) = data.get_box_data(guid)
64         element_tag = doc.createElement("element")
65         parent_tag = elements_tags[testbed_guid]
66         parent_tag.appendChild(element_tag)
67         element_tag.setAttribute("factory_id", factory_id)
68         element_tag.setAttribute("guid", xmlencode(guid))
69         self.graphical_info_data_to_xml(doc, element_tag, guid, data)
70         self.factory_attributes_data_to_xml(doc, element_tag, guid, data)
71         self.attributes_data_to_xml(doc, element_tag, guid, data)
72         self.traces_data_to_xml(doc, element_tag, guid, data)
73         self.addresses_data_to_xml(doc, element_tag, guid, data)
74         self.routes_data_to_xml(doc, element_tag, guid, data)
75         self.connections_data_to_xml(doc, element_tag, guid, data)
76
77     def graphical_info_data_to_xml(self, doc, parent_tag, guid, data):
78         graphical_info_tag = doc.createElement("graphical_info") 
79         parent_tag.appendChild(graphical_info_tag)
80         (x, y, width, height) = data.get_graphical_info_data(guid)
81         graphical_info_tag.setAttribute("x", xmlencode(x))
82         graphical_info_tag.setAttribute("y", xmlencode(y))
83         graphical_info_tag.setAttribute("width", xmlencode(width))
84         graphical_info_tag.setAttribute("height", xmlencode(height))
85
86     def factory_attributes_data_to_xml(self, doc, parent_tag, guid, data):
87         factory_attributes_tag = doc.createElement("factory_attributes")
88         for (name, value) in data.get_factory_attribute_data(guid):
89             if value is not None:
90                 factory_attribute_tag = doc.createElement("factory_attribute") 
91                 factory_attributes_tag.appendChild(factory_attribute_tag)
92                 factory_attribute_tag.setAttribute("name", name)
93                 factory_attribute_tag.setAttribute("value", xmlencode(value))
94                 factory_attribute_tag.setAttribute("type", self.type_to_standard(value))
95         if factory_attributes_tag.hasChildNodes():
96             parent_tag.appendChild(factory_attributes_tag)
97
98     def attributes_data_to_xml(self, doc, parent_tag, guid, data):
99         attributes_tag = doc.createElement("attributes") 
100         for name, value in data.get_attribute_data(guid):
101             if value is not None:
102                 attribute_tag = doc.createElement("attribute") 
103                 attributes_tag.appendChild(attribute_tag)
104                 attribute_tag.setAttribute("name", name)
105                 attribute_tag.setAttribute("value", xmlencode(value))
106                 attribute_tag.setAttribute("type", self.type_to_standard(value))
107         if attributes_tag.hasChildNodes():
108             parent_tag.appendChild(attributes_tag)
109
110     def traces_data_to_xml(self, doc, parent_tag, guid, data):
111         traces_tag = doc.createElement("traces") 
112         for name in data.get_trace_data(guid):
113             trace_tag = doc.createElement("trace") 
114             traces_tag.appendChild(trace_tag)
115             trace_tag.setAttribute("name", name)
116         if traces_tag.hasChildNodes():
117             parent_tag.appendChild(traces_tag)
118
119     def addresses_data_to_xml(self, doc, parent_tag, guid, data):
120         addresses_tag = doc.createElement("addresses") 
121         for (address, netprefix, broadcast) in data.get_address_data(guid):
122             address_tag = doc.createElement("address") 
123             addresses_tag.appendChild(address_tag)
124             if address:
125                 address_tag.setAttribute("Address", xmlencode(address))
126             address_tag.setAttribute("NetPrefix", xmlencode(netprefix))
127             if broadcast:
128                 address_tag.setAttribute("Broadcast", xmlencode(broadcast))
129         if addresses_tag.hasChildNodes():
130             parent_tag.appendChild(addresses_tag)
131
132     def routes_data_to_xml(self, doc, parent_tag, guid, data):
133         routes_tag = doc.createElement("routes") 
134         for (destination, netprefix, nexthop, metric) \
135                 in data.get_route_data(guid):
136             route_tag = doc.createElement("route") 
137             routes_tag.appendChild(route_tag)
138             route_tag.setAttribute("Destination", xmlencode(destination))
139             route_tag.setAttribute("NetPrefix", xmlencode(netprefix))
140             route_tag.setAttribute("NextHop", xmlencode(nexthop))
141             route_tag.setAttribute("Metric", xmlencode(metric))
142         if routes_tag.hasChildNodes():
143             parent_tag.appendChild(routes_tag)
144
145     def connections_data_to_xml(self, doc, parent_tag, guid, data):
146         connections_tag = doc.createElement("connections") 
147         for (connector_type_name, other_guid, other_connector_type_name) \
148                 in data.get_connection_data(guid):
149                 connection_tag = doc.createElement("connection") 
150                 connections_tag.appendChild(connection_tag)
151                 connection_tag.setAttribute("connector", connector_type_name)
152                 connection_tag.setAttribute("other_guid", xmlencode(other_guid))
153                 connection_tag.setAttribute("other_connector",
154                         other_connector_type_name)
155         if connections_tag.hasChildNodes():
156             parent_tag.appendChild(connections_tag)
157
158     def from_xml_to_data(self, xml):
159         data = ExperimentData()
160         doc = minidom.parseString(xml)
161         testbeds_tag = doc.getElementsByTagName("testbeds")[0] 
162         testbed_tag_list = testbeds_tag.getElementsByTagName("testbed")
163         for testbed_tag in testbed_tag_list:
164             if testbed_tag.nodeType == doc.ELEMENT_NODE:
165                 testbed_guid = int(testbed_tag.getAttribute("guid"))
166                 elements_tag = testbed_tag.getElementsByTagName("elements")[0] 
167                 elements_tag = testbed_tag.removeChild(elements_tag)
168                 self.testbed_data_from_xml(testbed_tag, data)
169                 element_tag_list = elements_tag.getElementsByTagName("element")
170                 for element_tag in element_tag_list:
171                     if element_tag.nodeType == doc.ELEMENT_NODE:
172                         self.box_data_from_xml(element_tag, testbed_guid, data)
173         return data
174
175     def from_xml(self, experiment_description, xml):
176         data = self.from_xml_to_data(xml)
177         self.from_data(experiment_description, data)
178
179     def testbed_data_from_xml(self, tag, data):
180         testbed_guid = int(tag.getAttribute("guid"))
181         testbed_id = xmldecode(tag.getAttribute("testbed_id"))
182         testbed_version = xmldecode(tag.getAttribute("testbed_version"))
183         data.add_testbed_data(testbed_guid, testbed_id, testbed_version)
184         self.graphical_info_data_from_xml(tag, testbed_guid, data)
185         self.attributes_data_from_xml(tag, testbed_guid, data)
186
187     def box_data_from_xml(self, tag, testbed_guid, data):
188         guid = int(tag.getAttribute("guid"))
189         factory_id = xmldecode(tag.getAttribute("factory_id"))
190         data.add_box_data(guid, testbed_guid, factory_id)
191         self.graphical_info_data_from_xml(tag, guid, data)
192         self.factory_attributes_data_from_xml(tag, guid, data)
193         self.attributes_data_from_xml(tag, guid, data)
194         self.traces_data_from_xml(tag, guid, data)
195         self.addresses_data_from_xml(tag, guid, data)
196         self.routes_data_from_xml(tag, guid, data)
197         self.connections_data_from_xml(tag, guid, data)
198
199     def graphical_info_data_from_xml(self, tag, guid, data):
200         graphical_info_tag_list = tag.getElementsByTagName(
201                 "graphical_info")
202         if len(graphical_info_tag_list) == 0:
203             return
204
205         graphical_info_tag = graphical_info_tag_list[0]
206         if graphical_info_tag.nodeType == tag.ELEMENT_NODE:
207             x = float(graphical_info_tag.getAttribute("x"))
208             y = float(graphical_info_tag.getAttribute("y"))
209             width = float(graphical_info_tag.getAttribute("width"))
210             height = float(graphical_info_tag.getAttribute("height"))
211             data.add_graphical_info_data(guid, x, y, width, height)
212
213     def factory_attributes_data_from_xml(self, tag, guid, data):
214         factory_attributes_tag_list = tag.getElementsByTagName(
215                 "factory_attributes")
216         if len(factory_attributes_tag_list) == 0:
217             return
218
219         factory_attribute_tag_list = factory_attributes_tag_list[0].\
220                 getElementsByTagName("factory_attribute")
221         for factory_attribute_tag in factory_attribute_tag_list:
222              if factory_attribute_tag.nodeType == tag.ELEMENT_NODE:
223                 name = xmldecode(factory_attribute_tag.getAttribute("name"))
224                 value = xmldecode(factory_attribute_tag.getAttribute("value"))
225                 std_type = xmldecode(factory_attribute_tag.getAttribute("type"))
226                 value = self.type_from_standard(std_type, value)
227                 data.add_factory_attribute_data(guid, name, value)
228
229     def attributes_data_from_xml(self, tag, guid, data):
230         attributes_tag_list= tag.getElementsByTagName("attributes")
231         if len(attributes_tag_list) == 0:
232             return
233
234         attribute_tag_list = attributes_tag_list[0].\
235                 getElementsByTagName("attribute")
236         for attribute_tag in attribute_tag_list:
237              if attribute_tag.nodeType == tag.ELEMENT_NODE:
238                 name = xmldecode(attribute_tag.getAttribute("name"))
239                 value = xmldecode(attribute_tag.getAttribute("value"))
240                 std_type = xmldecode(attribute_tag.getAttribute("type"))
241                 value = self.type_from_standard(std_type, value)
242                 data.add_attribute_data(guid, name, value)
243
244     def traces_data_from_xml(self, tag, guid, data):
245         traces_tag_list = tag.getElementsByTagName("traces")
246         if len(traces_tag_list) == 0:
247             return
248
249         trace_tag_list = traces_tag_list[0].getElementsByTagName(
250                 "trace")
251         for trace_tag in trace_tag_list:
252              if trace_tag.nodeType == tag.ELEMENT_NODE:
253                 name = xmldecode(trace_tag.getAttribute("name"))
254                 data.add_trace_data(guid, name)
255
256     def addresses_data_from_xml(self, tag, guid, data):
257         addresses_tag_list = tag.getElementsByTagName("addresses")
258         if len(addresses_tag_list) == 0:
259             return
260
261         address_tag_list = addresses_tag_list[0].\
262                 getElementsByTagName("address")
263         for address_tag in address_tag_list:
264             if address_tag.nodeType == tag.ELEMENT_NODE:
265                 address = xmldecode(address_tag.getAttribute("Address")) \
266                        if address_tag.hasAttribute("Address") else None
267                 netprefix = int(address_tag.getAttribute("NetPrefix")) \
268                        if address_tag.hasAttribute("NetPrefix") else None
269                 broadcast = xmldecode(address_tag.getAttribute("Broadcast")) \
270                        if address_tag.hasAttribute("Broadcast") else None
271                 data.add_address_data(guid, address, netprefix, broadcast)
272
273     def routes_data_from_xml(self, tag, guid, data):
274         routes_tag_list = tag.getElementsByTagName("routes")
275         if len(routes_tag_list) == 0:
276             return
277
278         route_tag_list = routes_tag_list[0].getElementsByTagName("route")
279         for route_tag in route_tag_list:
280             if route_tag.nodeType == tag.ELEMENT_NODE:
281                 destination = xmldecode(route_tag.getAttribute("Destination"))
282                 netprefix = int(route_tag.getAttribute("NetPrefix"))
283                 nexthop = xmldecode(route_tag.getAttribute("NextHop"))
284                 metric = int(route_tag.getAttribute("Metric")) \
285                         if route_tag.hasAttribute("Metric") else 0
286                 data.add_route_data(guid, destination, netprefix, 
287                         nexthop, metric)
288
289     def connections_data_from_xml(self, tag, guid, data):
290         connections_tag_list = tag.getElementsByTagName("connections")
291         if len(connections_tag_list) == 0:
292             return
293
294         connection_tag_list = connections_tag_list[0].getElementsByTagName(
295                 "connection")
296         for connection_tag in connection_tag_list:
297              if connection_tag.nodeType == tag.ELEMENT_NODE:
298                  connector_type_name = xmldecode(connection_tag.getAttribute(
299                      "connector"))
300                  other_connector_type_name = xmldecode(connection_tag.getAttribute(
301                          "other_connector"))
302                  other_guid = int(connection_tag.getAttribute("other_guid"))
303                  data.add_connection_data(guid, connector_type_name, 
304                          other_guid, other_connector_type_name)
305
306     def type_to_standard(self, value):
307         if isinstance(value, str):
308             return Attribute.STRING
309         if isinstance(value, bool):
310             return Attribute.BOOL
311         if isinstance(value, int):
312             return Attribute.INTEGER
313         if isinstance(value, float):
314             return Attribute.DOUBLE
315     
316     def type_from_standard(self, type, value):
317         if type == Attribute.STRING:
318             return str(value)
319         if type == Attribute.BOOL:
320             return value == "True"
321         if type == Attribute.INTEGER:
322             return int(value)
323         if type == Attribute.DOUBLE:
324             return float(value)
325