Ticket #8: box labels, reference expression substitution supporting framework
[nepi.git] / src / nepi / util / parser / base.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import sys
5
6 class ExperimentData(object):
7     def __init__(self):
8         self.data = dict()
9
10     @property
11     def guids(self):
12         return self.data.keys()
13
14     def add_testbed_data(self, guid, testbed_id, testbed_version):
15         testbed_data = dict()
16         testbed_data["testbed_id"] = testbed_id
17         testbed_data["testbed_version"] = testbed_version
18         self.data[guid] = testbed_data
19
20     def add_box_data(self, guid, testbed_guid, factory_id):
21         box_data = dict()
22         box_data["testbed_guid"] = testbed_guid
23         box_data["factory_id"] = factory_id
24         self.data[guid] = box_data
25
26     def add_graphical_info_data(self, guid, x, y, width, height, label):
27         data = self.data[guid]
28         if not "graphical_info" in data:
29             data["graphical_info"] = dict()
30         graphical_info_data = data["graphical_info"]
31         graphical_info_data["x"] = x
32         graphical_info_data["y"] = y
33         graphical_info_data["width"] = width
34         graphical_info_data["height"] = height
35         graphical_info_data["label"] = label
36
37     def add_factory_attribute_data(self, guid, name, value):
38         data = self.data[guid]
39         if not "factory_attributes" in data:
40             data["factory_attributes"] = dict()
41         factory_attributes_data = data["factory_attributes"]
42         factory_attributes_data[name] = value
43
44     def add_attribute_data(self, guid, name, value):
45         data = self.data[guid]
46         if not "attributes" in data:
47             data["attributes"] = dict()
48         attributes_data = data["attributes"]
49         attributes_data[name] = value
50
51     def add_trace_data(self, guid, trace_name):
52         data = self.data[guid]
53         if not "traces" in data:
54             data["traces"] = list()
55         traces_data = data["traces"]
56         traces_data.append(trace_name)
57
58     def add_connection_data(self, guid, connector_type_name, other_guid,
59             other_connector_type_name):
60         data = self.data[guid]
61         if not "connections" in data:
62             data["connections"] = dict()
63         connections_data = data["connections"]
64         if not connector_type_name in connections_data:
65             connections_data[connector_type_name] = dict()
66         connection_data = connections_data[connector_type_name]
67         connection_data[other_guid] = other_connector_type_name
68
69     def add_address_data(self, guid, autoconf, address, netprefix, 
70             broadcast):
71         data = self.data[guid]
72         if not "addresses" in data:
73             data["addresses"] = list()
74         addresses_data = data["addresses"]
75         address_data = dict()
76         if autoconf:
77             address_data["AutoConfigure"] = autoconf
78         if address:
79             address_data["Address"] = address
80         address_data["NetPrefix"] = netprefix
81         if broadcast:
82             address_data["Broadcast"] = broadcast
83         addresses_data.append(address_data)
84
85     def add_route_data(self, guid, destination, netprefix, nexthop): 
86         data = self.data[guid]
87         if not "routes" in data:
88             data["routes"] = list()
89         routes_data = data["routes"]
90         route_data = dict({
91             "Destination": destination,
92             "NetPrefix": netprefix, 
93             "NextHop": nexthop 
94             })
95         routes_data.append(route_data)
96
97     def is_testbed_data(self, guid):
98         return True if "testbed_id" in self.data[guid] else None
99
100     def get_testbed_data(self, guid):
101         testbed_data = self.data[guid]
102         return (testbed_data["testbed_id"], testbed_data["testbed_version"])
103
104     def get_box_data(self, guid):
105         box_data = self.data[guid]
106         return (box_data["testbed_guid"], box_data["factory_id"])
107
108     def get_graphical_info_data(self, guid):
109         data = self.data[guid]
110         if not "graphical_info" in data:
111             return (0, 0, 0, 0, "") 
112         graphical_info_data = data["graphical_info"]
113         return (graphical_info_data["x"],
114                 graphical_info_data["y"],
115                 graphical_info_data["width"],
116                 graphical_info_data["height"],
117                 graphical_info_data["label"])
118
119     def get_factory_attribute_data(self, guid):
120         data = self.data[guid]
121         if not "factory_attributes" in data:
122             return []
123         factory_attributes_data = data["factory_attributes"]
124         return [(name, value) for name, value \
125                 in factory_attributes_data.iteritems()]
126
127     def get_attribute_data(self, guid, attribute=None, default=None):
128         data = self.data[guid]
129         if not "attributes" in data:
130             if attribute is None:
131                 return []
132             else:
133                 return None
134         attributes_data = data["attributes"]
135         if attribute is None:
136             return [(name, value) for name, value \
137                     in attributes_data.iteritems()]
138         else:
139             return attributes_data.get(attribute, default)
140
141     def set_attribute_data(self, guid, attribute, value):
142         data = self.data[guid]
143         if not "attributes" in data:
144             raise KeyError, "No attributes in reference OBJECT %r" % (guid,)
145         attributes_data = data["attributes"]
146         attributes_data[attribute] = value
147
148     def get_trace_data(self, guid):
149         data = self.data[guid]
150         if not "traces" in data:
151             return []
152         return [trace_id for trace_id in data["traces"]]
153
154     def get_connection_data(self, guid):
155         data = self.data[guid]
156         if not "connections" in data:
157             return []
158         connections_data = data["connections"]
159         return [(connector_type_name, other_guid, other_connector_type_name) \
160                     for connector_type_name, connection_data \
161                         in connections_data.iteritems() \
162                             for other_guid, other_connector_type_name \
163                                 in connection_data.iteritems()]
164
165     def get_address_data(self, guid):
166         data = self.data[guid]
167         if not "addresses" in data:
168             return []
169         addresses_data = data["addresses"]
170         return [(data["AutoConfigure"] if "AutoConfigure" in data else None,
171                  data["Address"] if "Address" in data else None,
172                  data["NetPrefix"] if "NetPrefix" in data else None,
173                  data["Broadcast"] if "Broadcast" in data else None) \
174                  for data in addresses_data]
175
176     def get_route_data(self, guid):
177         data = self.data[guid]
178         if not "routes" in data:
179             return []
180         routes_data = data["routes"]
181         return [(data["Destination"],
182                  data["NetPrefix"],
183                  data["NextHop"]) \
184                          for data in routes_data]
185
186 class ExperimentParser(object):
187     def to_data(self, experiment_description):
188         data = ExperimentData()
189         for testbed_description in experiment_description.testbed_descriptions:
190             guid = testbed_description.guid
191             testbed_id = testbed_description.provider.testbed_id
192             testbed_version = testbed_description.provider.testbed_version
193             data.add_testbed_data(guid, testbed_id, testbed_version)
194             self.graphical_info_to_data(data, guid, 
195                     testbed_description.graphical_info)
196             self.attributes_to_data(data, guid, testbed_description.attributes)
197             for box in testbed_description.boxes:
198                 data.add_box_data(box.guid, guid, box.factory_id)
199                 self.graphical_info_to_data(data, box.guid, box.graphical_info)
200                 self.factory_attributes_to_data(data, box.guid, 
201                         box.factory_attributes)
202                 self.attributes_to_data(data, box.guid, box.attributes)
203                 self.traces_to_data(data, box.guid, box.traces)
204                 self.connections_to_data(data, box.guid, box.connectors)
205                 self.addresses_to_data(data, box.guid, box.addresses)
206                 self.routes_to_data(data, box.guid, box.routes)
207         return data
208
209     def graphical_info_to_data(self, data, guid, g_info):
210         data.add_graphical_info_data(guid, g_info.x, g_info.y, g_info.width, 
211                 g_info.height, g_info.label)
212
213     def factory_attributes_to_data(self, data, guid, factory_attributes):
214         for name, value in factory_attributes.iteritems():
215             data.add_factory_attribute_data(guid, name, value)
216
217     def attributes_to_data(self, data, guid, attributes):
218         for attribute in attributes:
219             if attribute.modified or attribute.has_no_default_value:
220                 data.add_attribute_data(guid, attribute.name, attribute.value)
221
222     def traces_to_data(self, data, guid, traces):
223         for trace in traces:
224             if trace.enabled:
225                 data.add_trace_data(guid, trace.trace_id)
226
227     def connections_to_data(self, data, guid, connectors):
228         for connector in connectors:
229             connector_type_name = connector.connector_type.name
230             for other_connector in connector.connections:
231                 other_guid = other_connector.box.guid
232                 other_connector_type_name = other_connector.connector_type.name
233                 data.add_connection_data(guid, connector_type_name, other_guid,
234                         other_connector_type_name)
235
236     def addresses_to_data(self, data, guid, addresses):
237         for addr in addresses:
238              autoconf = addr.get_attribute_value("AutoConfigure")
239              address = addr.get_attribute_value("Address")
240              netprefix = addr.get_attribute_value("NetPrefix")
241              broadcast = addr.get_attribute_value("Broadcast") \
242                     if addr.has_attribute("Broadcast") and \
243                     addr.is_attribute_modified("Broadcast") else None
244              data.add_address_data(guid, autoconf, address, netprefix, 
245                     broadcast)
246
247     def routes_to_data(self, data, guid, routes):
248         for route in routes:
249              destination = route.get_attribute_value("Destination")
250              netprefix = route.get_attribute_value("NetPrefix")
251              nexthop = route.get_attribute_value("NextHop")
252              data.add_route_data(guid, destination, netprefix, nexthop)
253
254     def from_data(self, experiment_description, data):
255         box_guids = list()
256         for guid in data.guids:
257             if data.is_testbed_data(guid):
258                 self.testbed_from_data(experiment_description, guid, data)
259             else:
260                 self.box_from_data(experiment_description, guid, data)
261                 box_guids.append(guid)
262         self.connections_from_data(experiment_description, box_guids, data)
263
264     def testbed_from_data(self, experiment_description, guid, data):
265         from nepi.core.design import FactoriesProvider
266         (testbed_id, testbed_version) = data.get_testbed_data(guid)
267         provider = FactoriesProvider(testbed_id, testbed_version)
268         experiment_description.add_testbed_description(provider)
269         testbed_description = experiment_description.testbed_description(guid)
270         self.attributes_from_data(testbed_description, data)
271
272     def box_from_data(self, experiment_description, guid, data):
273         (testbed_guid, factory_id) = data.get_box_data(guid)
274         testbed_description = experiment_description.testbed_description(
275                 testbed_guid)
276         self.factory_attributes_from_data(testbed_description, factory_id,
277                 guid, data)
278         box = testbed_description.create(factory_id)
279         self.graphical_info_from_data(box, data)
280         self.attributes_from_data(box, data)
281         self.traces_from_data(box, data)
282         self.addresses_from_data(box, data)
283         self.routes_from_data(box, data)
284
285     def graphical_info_from_data(self, element, data):
286         (x, y, width, height, label) =  data.get_graphical_info_data(
287                 element.guid)
288         element.graphical_info.x = x
289         element.graphical_info.y = y
290         element.graphical_info.width = width
291         element.graphical_info.height = height
292         element.graphical_info.label = label
293
294     def factory_attributes_from_data(self, testbed_description, factory_id, 
295             guid, data):
296         factory = testbed_description.provider.factory(factory_id)
297         for (name, value) in data.get_factory_attribute_data(guid):
298             factory.set_attribute_value(name, value)
299
300     def attributes_from_data(self, element, data):
301         for name, value in data.get_attribute_data(element.guid):
302             element.set_attribute_value(name, value)
303
304     def traces_from_data(self, box, data):
305         for name in data.get_trace_data(box.guid):
306             box.enable_trace(name)
307
308     def addresses_from_data(self, box, data):
309         for (autoconf, address, netprefix, broadcast) \
310                 in data.get_address_data(box.guid):
311             addr = box.add_address()
312             if autoconf:
313                 addr.set_attribute_value("AutoConfigure", autoconf)
314             if address:
315                 addr.set_attribute_value("Address", address)
316             if netprefix != None:
317                 addr.set_attribute_value("NetPrefix", netprefix)
318             if broadcast:
319                 addr.set_attribute_value("Broadcast", broadcast)
320
321     def routes_from_data(self, box, data):
322          for (destination, netprefix, nexthop) \
323                  in data.get_route_data(box.guid):
324             addr = box.add_route()
325             addr.set_attribute_value("Destination", destination)
326             addr.set_attribute_value("NetPrefix", netprefix)
327             addr.set_attribute_value("NextHop", nexthop)
328
329     def connections_from_data(self, experiment_description, guids, data):
330         for guid in guids:
331             box = experiment_description.box(guid)
332             for (connector_type_name, other_guid, other_connector_type_name) \
333                     in data.get_connection_data(guid):
334                     other_box = experiment_description.box(other_guid)
335                     connector = box.connector(connector_type_name)
336                     other_connector = other_box.connector(
337                             other_connector_type_name)
338                     if not connector.is_connected(other_connector):
339                         connector.connect(other_connector)
340