intermediate xml serialization using ExperimentData
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Wed, 16 Feb 2011 15:51:13 +0000 (16:51 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Wed, 16 Feb 2011 15:51:13 +0000 (16:51 +0100)
examples/design1.py
src/nepi/core/attributes.py
src/nepi/util/parser/_xml.py
src/nepi/util/parser/base.py

index 1e98079..1765b21 100644 (file)
@@ -32,12 +32,12 @@ app.connector("node").connect(node1.connector("apps"))
 from nepi.util.parser.base import ExperimentParser
 p = ExperimentParser()
 data = p.to_data(exp_desc)
-print data
+print data.data
 exp_desc2 = ExperimentDescription()
 p.from_data(exp_desc2, data)
 data2 = p.to_data(exp_desc2)
-print data2
-print data == data2
+print data2.data
+print data.data == data2.data
 
 from nepi.util.parser._xml import XmlExperimentParser
 p = XmlExperimentParser()
index 187f43a..d462230 100644 (file)
@@ -40,6 +40,9 @@ class AttributesMap(object):
     def get_attribute_readonly(self, name):
         return self._attributes[name].readonly
 
+    def is_attribute_modified(self, name):
+        return self._attributes[name].modified
+
     def add_attribute(self, name, help, type, value = None, range = None,
         allowed = None, readonly = False, validation_function = None):
         if name in self._attributes:
index db4c0d9..fa21d0a 100644 (file)
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 from nepi.core.attributes import Attribute
-from nepi.util.parser.base import ExperimentParser
+from nepi.util.parser.base import ExperimentData, ExperimentParser
 from xml.dom import minidom
 
 class XmlExperimentParser(ExperimentParser):
@@ -14,154 +14,148 @@ class XmlExperimentParser(ExperimentParser):
         exp_tag.appendChild(testbeds_tag)
 
         elements_tags = dict()
-        for guid, elem_data in data.iteritems():
-            if "testbed_id" in elem_data:
-                elements_tag = self.testbed_data_to_xml(doc, testbeds_tag, guid,
-                        elem_data)
+        for guid in data.guids:
+            if data.is_testbed_data(guid):
+                elements_tag = self.testbed_data_to_xml(doc, testbeds_tag, guid, data)
                 elements_tags[guid] = elements_tag
             else:
-                testbed_guid = elem_data["testbed_guid"]
-                elements_tag = elements_tags[testbed_guid]
-                self.box_data_to_xml(doc, elements_tag, guid, elem_data)
-
+                self.box_data_to_xml(doc, elements_tags, guid, data)
         doc.appendChild(exp_tag)
         xml = doc.toprettyxml(indent="    ", encoding="UTF-8")
         return xml
 
-    def testbed_data_to_xml(self, doc, parent_tag, guid, testbed_data):
+    def testbed_data_to_xml(self, doc, parent_tag, guid, data):
         testbed_tag = doc.createElement("testbed") 
         testbed_tag.setAttribute("guid", str(guid))
-        testbed_tag.setAttribute("testbed_id", str(testbed_data["testbed_id"]))
-        testbed_tag.setAttribute("testbed_version", 
-                str(testbed_data["testbed_version"]))
+        (testbed_id, testbed_version) = data.get_testbed_data(guid)
+        testbed_tag.setAttribute("testbed_id", str(testbed_id))
+        testbed_tag.setAttribute("testbed_version", str(testbed_version))
         parent_tag.appendChild(testbed_tag)
+        self.attributes_data_to_xml(doc, testbed_tag, guid, data)
         elements_tag = doc.createElement("elements")
         testbed_tag.appendChild(elements_tag)
         return elements_tag
 
-    def box_data_to_xml(self, doc, parent_tag, guid, box_data):
+    def box_data_to_xml(self, doc, elements_tags, guid, data):
+        (testbed_guid, factory_id) = data.get_box_data(guid)
         element_tag = doc.createElement("element")
+        parent_tag = elements_tags[testbed_guid]
         parent_tag.appendChild(element_tag)
-        element_tag.setAttribute("factory_id", str(box_data["factory_id"]))
+        element_tag.setAttribute("factory_id", factory_id)
         element_tag.setAttribute("guid", str(guid))
-        if "factory_attributes" in box_data:
-            self.factory_attributes_data_to_xml(doc, element_tag,
-                    box_data["factory_attributes"])
-        if "attributes" in box_data:
-            self.attributes_data_to_xml(doc, element_tag, 
-                    box_data["attributes"])
-        if "traces" in box_data:
-            self.traces_data_to_xml(doc, element_tag, box_data["traces"])
-        if "addresses" in box_data:
-            self.addresses_data_to_xml(doc, element_tag, 
-                    box_data["addresses"])
-        if "routes" in box_data:
-            self.routes_data_to_xml(doc, element_tag, box_data["routes"])
-        if "connections" in box_data:
-            self.connections_data_to_xml(doc, element_tag, 
-                    box_data["connections"])
+        self.factory_attributes_data_to_xml(doc, element_tag, guid, data)
+        self.attributes_data_to_xml(doc, element_tag, guid, data)
+        self.traces_data_to_xml(doc, element_tag, guid, data)
+        self.addresses_data_to_xml(doc, element_tag, guid, data)
+        self.routes_data_to_xml(doc, element_tag, guid, data)
+        self.connections_data_to_xml(doc, element_tag, guid, data)
         
-    def factory_attributes_data_to_xml(self, doc, parent_tag, data):
+    def factory_attributes_data_to_xml(self, doc, parent_tag, guid, data):
         factory_attributes_tag = doc.createElement("factory_attributes") 
         parent_tag.appendChild(factory_attributes_tag)
-        for name, value in data.iteritems():
+        for (name, value) in data.get_factory_attribute_data(guid):
             factory_attribute_tag = doc.createElement("factory_attribute") 
             factory_attributes_tag.appendChild(factory_attribute_tag)
             factory_attribute_tag.setAttribute("name", name)
             factory_attribute_tag.setAttribute("value", str(value))
             factory_attribute_tag.setAttribute("type", self.type_to_standard(value))
 
-    def attributes_data_to_xml(self, doc, parent_tag, data):
+    def attributes_data_to_xml(self, doc, parent_tag, guid, data):
         attributes_tag = doc.createElement("attributes") 
         parent_tag.appendChild(attributes_tag)
-        for name, value in data.iteritems():
+        for name, value in data.get_attribute_data(guid):
             attribute_tag = doc.createElement("attribute") 
             attributes_tag.appendChild(attribute_tag)
             attribute_tag.setAttribute("name", name)
             attribute_tag.setAttribute("value", str(value))
             attribute_tag.setAttribute("type", self.type_to_standard(value))
 
-    def traces_data_to_xml(self, doc, parent_tag, data):
+    def traces_data_to_xml(self, doc, parent_tag, guid, data):
         traces_tag = doc.createElement("traces") 
         parent_tag.appendChild(traces_tag)
-        for name in data:
+        for name in data.get_trace_data(guid):
             trace_tag = doc.createElement("trace") 
             traces_tag.appendChild(trace_tag)
             trace_tag.setAttribute("name", name)
 
-    def addresses_data_to_xml(self, doc, parent_tag, data):
+    def addresses_data_to_xml(self, doc, parent_tag, guid, data):
         addresses_tag = doc.createElement("addresses") 
         parent_tag.appendChild(addresses_tag)
-        for address in data:
+        for (autoconfigure, address, family, netprefix, broadcast) \
+                in data.get_address_data(guid):
             address_tag = doc.createElement("address") 
             addresses_tag.appendChild(address_tag)
-            for name, value in address.iteritems():
-                address_tag.setAttribute(name, str(value))
+            if autoconfigure:
+                address_tag.setAttribute("AutoConfigure", str(autoconf))
+            if address:
+                address_tag.setAttribute("Address", str(address))
+            if family:
+                address_tag.setAttribute("Family", str(family))
+            if netprefix:
+                address_tag.setAttribute("NetPrefix", str(netprefix))
+            if broadcast:
+                address_tag.setAttribute("Broadcast", str(broadcast))
 
-    def routes_data_to_xml(self, doc, parent_tag, data):
+    def routes_data_to_xml(self, doc, parent_tag, guid, data):
         routes_tag = doc.createElement("routes") 
         parent_tag.appendChild(routes_tag)
-        for route in data:
+        for (family, destination, netprefix, nexthop, interface) \
+                in data.get_route_data(guid):
             route_tag = doc.createElement("route") 
             routes_tag.appendChild(route_tag)
-            for name, value in route.iteritems():
-                route_tag.setAttribute(name, str(value))
+            route_tag.setAttribute("Family", str(family))
+            route_tag.setAttribute("Destination", str(destination))
+            route_tag.setAttribute("NetPrefix", str(netprefix))
+            route_tag.setAttribute("NextHop", str(nexthop))
+            route_tag.setAttribute("Interface", str(interface))
 
-    def connections_data_to_xml(self, doc, parent_tag, data):
+    def connections_data_to_xml(self, doc, parent_tag, guid, data):
         connections_tag = doc.createElement("connections") 
         parent_tag.appendChild(connections_tag)
-        for connector_type_id, connections in data.iteritems():
-            for other_guid, other_connector_type_id in connections.iteritems():
+        for (connector_type_name, other_guid, other_connector_type_name) \
+                in data.get_connection_data(guid):
                 connection_tag = doc.createElement("connection") 
                 connections_tag.appendChild(connection_tag)
-                connection_tag.setAttribute("connector", connector_type_id)
+                connection_tag.setAttribute("connector", connector_type_name)
                 connection_tag.setAttribute("other_guid", str(other_guid))
                 connection_tag.setAttribute("other_connector",
-                        other_connector_type_id)
+                        other_connector_type_name)
 
     def from_xml(self, experiment_description, xml):
-        data = dict()
+        data = ExperimentData()
         doc = minidom.parseString(xml)
         testbeds_tag = doc.getElementsByTagName("testbeds")[0] 
         testbed_tag_list = testbeds_tag.getElementsByTagName("testbed")
         for testbed_tag in testbed_tag_list:
             if testbed_tag.nodeType == doc.ELEMENT_NODE:
-                testbed_data = self.testbed_data_from_xml(testbed_tag)
-                testbed_guid = testbed_tag.getAttribute("guid")
-                data[int(testbed_guid)] = testbed_data
+                testbed_guid = int(testbed_tag.getAttribute("guid"))
+                self.testbed_data_from_xml(testbed_tag, data)
                 elements_tag = testbed_tag.getElementsByTagName("elements")[0] 
                 element_tag_list = elements_tag.getElementsByTagName("element")
                 for element_tag in element_tag_list:
                     if element_tag.nodeType == doc.ELEMENT_NODE:
-                        box_data = self.box_data_from_xml(testbed_guid, element_tag)
-                        guid = element_tag.getAttribute("guid")
-                        data[int(guid)] = box_data
-        print data
+                        self.box_data_from_xml(element_tag, testbed_guid, data)
         self.from_data(experiment_description, data)
 
-    def testbed_data_from_xml(self, tag):
-        testbed_id = tag.getAttribute("testbed_id")
-        testbed_version = tag.getAttribute("testbed_version")
-        return dict({
-            "testbed_id": str(testbed_id), 
-            "testbed_version": str(testbed_version),
-            })
+    def testbed_data_from_xml(self, tag, data):
+        testbed_guid = int(tag.getAttribute("guid"))
+        testbed_id = str(tag.getAttribute("testbed_id"))
+        testbed_version = str(tag.getAttribute("testbed_version"))
+        data.add_testbed_data(testbed_guid, testbed_id, testbed_version)
+        self.attributes_data_from_xml(tag, testbed_guid, data)
 
-    def box_data_from_xml(self, testbed_guid, tag):
-        factory_id = tag.getAttribute("factory_id")
-        data = dict({
-            "testbed_guid": int(testbed_guid),
-            "factory_id": str(factory_id)
-            })
-        self.factory_attributes_data_from_xml(data, tag)
-        self.attributes_data_from_xml(data, tag)
-        self.traces_data_from_xml(data, tag)
-        self.addresses_data_from_xml(data, tag)
-        self.routes_data_from_xml(data, tag)
-        self.connections_data_from_xml(data, tag)
-        return data
+    def box_data_from_xml(self, tag, testbed_guid, data):
+        guid = int(tag.getAttribute("guid"))
+        factory_id = str(tag.getAttribute("factory_id"))
+        data.add_box_data(guid, testbed_guid, factory_id)
+        self.factory_attributes_data_from_xml(tag, guid, data)
+        self.attributes_data_from_xml(tag, guid, data)
+        self.traces_data_from_xml(tag, guid, data)
+        self.addresses_data_from_xml(tag, guid, data)
+        self.routes_data_from_xml(tag, guid, data)
+        self.connections_data_from_xml(tag, guid, data)
         
-    def factory_attributes_data_from_xml(self, data, tag):
+    def factory_attributes_data_from_xml(self, tag, guid, data):
         factory_attributes_tag_list = tag.getElementsByTagName(
                 "factory_attributes")
         if len(factory_attributes_tag_list) == 0:
@@ -169,117 +163,95 @@ class XmlExperimentParser(ExperimentParser):
 
         factory_attribute_tag_list = factory_attributes_tag_list[0].\
                 getElementsByTagName("factory_attribute")
-        factory_attributes_data = dict()
         for factory_attribute_tag in factory_attribute_tag_list:
              if factory_attribute_tag.nodeType == tag.ELEMENT_NODE:
-                name = factory_attribute_tag.getAttribute("name")
+                name = str(factory_attribute_tag.getAttribute("name"))
                 value = factory_attribute_tag.getAttribute("value")
                 std_type = factory_attribute_tag.getAttribute("type")
                 value = self.type_from_standard(std_type, value)
-                factory_attributes_data[str(name)] = value
-        data["factory_attributes"] = factory_attributes_data
-    
-    def attributes_data_from_xml(self, data, tag):
+                data.add_factory_attribute_data(guid, name, value)
+
+    def attributes_data_from_xml(self, tag, guid, data):
         attributes_tag_list= tag.getElementsByTagName("attributes")
         if len(attributes_tag_list) == 0:
             return
 
         attribute_tag_list = attributes_tag_list[0].\
                 getElementsByTagName("attribute")
-        attributes_data = dict()
         for attribute_tag in attribute_tag_list:
              if attribute_tag.nodeType == tag.ELEMENT_NODE:
-                name = attribute_tag.getAttribute("name")
+                name = str(attribute_tag.getAttribute("name"))
                 value = attribute_tag.getAttribute("value")
                 std_type = attribute_tag.getAttribute("type")
                 value = self.type_from_standard(std_type, value)
-                attributes_data[str(name)] = value
-        data["attributes"] = attributes_data
+                data.add_attribute_data(guid, name, value)
 
-    def traces_data_from_xml(self, data, tag):
+    def traces_data_from_xml(self, tag, guid, data):
         traces_tag_list = tag.getElementsByTagName("traces")
         if len(traces_tag_list) == 0:
             return
 
         trace_tag_list = traces_tag_list[0].getElementsByTagName(
                 "trace")
-        traces_data = list()
         for trace_tag in trace_tag_list:
              if trace_tag.nodeType == tag.ELEMENT_NODE:
-                name = trace_tag.getAttribute("name")
-                traces_data.append(name)
-        data["traces"] = traces_data
+                name = str(trace_tag.getAttribute("name"))
+                data.add_trace_data(guid, name)
 
-    def addresses_data_from_xml(self, data, tag):
+    def addresses_data_from_xml(self, tag, guid, data):
         addresses_tag_list = tag.getElementsByTagName("addresses")
         if len(addresses_tag_list) == 0:
             return
 
         address_tag_list = addresses_tag_list[0].\
                 getElementsByTagName("address")
-        addresses_data = list()
-        address_attributes = dict({"AutoConfigure": Attribute.BOOL, 
-            "Address": Attribute.STRING,
-            "Family": Attribute.INTEGER,
-            "NetPrefix": Attribute.INTEGER,
-            "Broadcast": Attribute.STRING 
-            })
         for address_tag in address_tag_list:
             if address_tag.nodeType == tag.ELEMENT_NODE:
-                address_data = dict()
-                for attr_name in address_attributes.keys():
-                    if address_tag.hasAttribute(attr_name):
-                        value = address_tag.getAttribute(attr_name)
-                        type = address_attributes[attr_name]
-                        address_data[attr_name] = self.type_from_standard(
-                                type, value)
-                addresses_data.append(address_data)
-        data["addresses"] = addresses_data
+                autoconf = bool(address_tag.getAttribute("AutoConfigure")) \
+                       if address_tag.hasAttribute("AutoConfigure") else None
+                address = str(address_tag.getAttribute("Address")) \
+                       if address_tag.hasAttribute("Address") else None
+                family = int(address_tag.getAttribute("Family")) \
+                       if address_tag.hasAttribute("Family") else None
+                netprefix = int(address_tag.getAttribute("NetPrefix")) \
+                       if address_tag.hasAttribute("NetPrefix") else None
+                broadcast = str(address_tag.getAttribute("Broadcast")) \
+                       if address_tag.hasAttribute("Broadcast") else None
+                data.add_address_data(guid, autoconf, address, family, 
+                    netprefix, broadcast)
 
-    def routes_data_from_xml(self, data, tag):
+    def routes_data_from_xml(self, tag, guid, data):
         routes_tag_list = tag.getElementsByTagName("routes")
         if len(routes_tag_list) == 0:
             return
 
         route_tag_list = routes_tag_list[0].getElementsByTagName("route")
-        routes_data = list()
-        route_attributes = dict({"Family": Attribute.INTEGER,
-            "Destination": Attribute.STRING,
-            "NetPrefix": Attribute.INTEGER,
-            "NextHop": Attribute.STRING,
-            "Interface": Attribute.STRING,
-            })
         for route_tag in route_tag_list:
-            if address_tag.nodeType == tag.ELEMENT_NODE:
-                route_data = dict()
-                for attr_name in route_attributes.keys():
-                    if route_tag.hasAttribute(attr_name):
-                        value = route_tag.getAttribute(attr_name)
-                        type = route_attributes[attr_name]
-                        route_data[attr_name] = self.type_from_standard(
-                                type, value)
-                routes_data.append(route_data)
-        data["routes"] = routes_data
+            if route_tag.nodeType == tag.ELEMENT_NODE:
+                family = int(route_tag.getAttribute("Family"))
+                destination = str(route_tag.getAttribute("Destination"))
+                netprefix = int(route_tag.getAttribute("NetPrefix"))
+                nexthop = str(route_tag.getAttribute("NextHop"))
+                interface = str(route_tag.getAttribute("Interface"))
+                data.add_route_data(guid, family, destination, netprefix, 
+                        nexthop, interface)
 
-    def connections_data_from_xml(self, data, tag):
+    def connections_data_from_xml(self, tag, guid, data):
         connections_tag_list = tag.getElementsByTagName("connections")
         if len(connections_tag_list) == 0:
             return
 
         connection_tag_list = connections_tag_list[0].getElementsByTagName(
                 "connection")
-        connections_data = dict()
         for connection_tag in connection_tag_list:
              if connection_tag.nodeType == tag.ELEMENT_NODE:
-                 connector = connection_tag.getAttribute("connector")
-                 other_connector = connection_tag.getAttribute(
-                         "other_connector")
-                 other_guid = connection_tag.getAttribute("other_guid")
-                 if not connector in connections_data:
-                     connections_data[str(connector)] = dict()
-                 connection_data = connections_data[str(connector)]
-                 connection_data[int(other_guid)] = str(other_connector)
-        data["connections"] = connections_data
+                 connector_type_name = str(connection_tag.getAttribute(
+                     "connector"))
+                 other_connector_type_name = str(connection_tag.getAttribute(
+                         "other_connector"))
+                 other_guid = int(connection_tag.getAttribute("other_guid"))
+                 data.add_connection_data(guid, connector_type_name, 
+                         other_guid, other_connector_type_name)
 
     def type_to_standard(self, value):
         if type(value) == str:
index 06a0310..feef6ab 100644 (file)
 
 import sys
 
+class ExperimentData(object):
+    def __init__(self):
+        self.data = dict()
+
+    @property
+    def guids(self):
+        return self.data.keys()
+
+    def add_testbed_data(self, guid, testbed_id, testbed_version):
+        testbed_data = dict()
+        testbed_data["testbed_id"] = testbed_id
+        testbed_data["testbed_version"] = testbed_version
+        self.data[guid] = testbed_data
+
+    def add_box_data(self, guid, testbed_guid, factory_id):
+        box_data = dict()
+        box_data["testbed_guid"] = testbed_guid
+        box_data["factory_id"] = factory_id
+        self.data[guid] = box_data
+
+    def add_factory_attribute_data(self, guid, name, value):
+        data = self.data[guid]
+        if not "factory_attributes" in data:
+            data["factory_attributes"] = dict()
+        factory_attributes_data = data["factory_attributes"]
+        factory_attributes_data[name] = value
+
+    def add_attribute_data(self, guid, name, value):
+        data = self.data[guid]
+        if not "attributes" in data:
+            data["attributes"] = dict()
+        attributes_data = data["attributes"]
+        attributes_data[name] = value
+
+    def add_trace_data(self, guid, trace_name):
+        data = self.data[guid]
+        if not "traces" in data:
+            data["traces"] = list()
+        traces_data = data["traces"]
+        traces_data.append(trace_name)
+
+    def add_connection_data(self, guid, connector_type_name, other_guid,
+            other_connector_type_name):
+        data = self.data[guid]
+        if not "connections" in data:
+            data["connections"] = dict()
+        connections_data = data["connections"]
+        if not connector_type_name in connections_data:
+            connections_data[connector_type_name] = dict()
+        connection_data = connections_data[connector_type_name]
+        connection_data[other_guid] = other_connector_type_name
+
+    def add_address_data(self, guid, autoconf, address, family, netprefix, 
+            broadcast):
+        data = self.data[guid]
+        if not "addresses" in data:
+            data["addresses"] = list()
+        addresses_data = data["addresses"]
+        address_data = dict()
+        if autoconf:
+            address_data["AutoConfigure"] = autoconf
+        if address:
+            address_data["Address"] = address
+        if family:
+            address_data["Family"] = family
+        if netprefix:
+            address_data["NetPrefix"] = netprefix
+        if broadcast:
+            address_data["Broadcast"] = broadcast
+        addresses_data.append(address_data)
+
+    def add_route_data(self, guid, family, destination, netprefix, nexthop, 
+            interface):
+        data = self.data[guid]
+        if not "routes" in data:
+            data["routes"] = list()
+        routes_data = data["routes"]
+        route_data = dict({
+            "Family": family, 
+            "Destination": destination,
+            "NetPrefix": netprefix, 
+            "NextHop": nexthop, 
+            "Interface": Interface
+            })
+        routes_data.append(route_data)
+
+    def is_testbed_data(self, guid):
+        return True if "testbed_id" in self.data[guid] else None
+
+    def get_testbed_data(self, guid):
+        testbed_data = self.data[guid]
+        return (testbed_data["testbed_id"], testbed_data["testbed_version"])
+
+    def get_box_data(self, guid):
+        box_data = self.data[guid]
+        return (box_data["testbed_guid"], box_data["factory_id"])
+
+    def get_factory_attribute_data(self, guid):
+        data = self.data[guid]
+        if not "factory_attributes" in data:
+            return []
+        factory_attributes_data = data["factory_attributes"]
+        return [(name, value) for name, value \
+                in factory_attributes_data.iteritems()]
+
+    def get_attribute_data(self, guid):
+        data = self.data[guid]
+        if not "attributes" in data:
+            return []
+        attributes_data = data["attributes"]
+        return [(name, value) for name, value \
+                in attributes_data.iteritems()]
+
+    def get_trace_data(self, guid):
+        data = self.data[guid]
+        if not "traces" in data:
+            return []
+        return [trace_name for trace_name in data["traces"]]
+
+    def get_connection_data(self, guid):
+        data = self.data[guid]
+        if not "connections" in data:
+            return []
+        connections_data = data["connections"]
+        return [(connector_type_name, other_guid, other_connector_type_name) \
+                    for connector_type_name, connection_data \
+                        in connections_data.iteritems() \
+                            for other_guid, other_connector_type_name \
+                                in connection_data.iteritems()]
+
+    def get_address_data(self, guid):
+        data = self.data[guid]
+        if not "addresses" in data:
+            return []
+        addresses_data = data["addresses"]
+        return [(data["AutoConfigure"] if "AutoConfigure" in data else None,
+                 data["Address"] if "Address" in data else None,
+                 data["Family"] if "Family" in data else None,
+                 data["NetPrefix"] if "NetPrefix" in data else None,
+                 data["Broadcast"] if "Broadcast" in data else None) \
+                 for data in addresses_data]
+
+    def get_route_data(self, guid):
+        data = self.data[guid]
+        if not "routes" in data:
+            return []
+        routes_data = data["routes"]
+        return [(data["Family"],
+                 data["Destination"],
+                 data["NetPrefix"],
+                 data["NextHop"],
+                 data["Interface"]) \
+                 for data in routes_data]
+
 class ExperimentParser(object):
     def to_data(self, experiment_description):
-        data = dict()
+        data = ExperimentData()
         for testbed_description in experiment_description.testbed_descriptions:
             guid = testbed_description.guid
-            data[guid] = self.testbed_to_data(testbed_description)
+            testbed_id = testbed_description.provider.testbed_id
+            testbed_version = testbed_description.provider.testbed_version
+            data.add_testbed_data(guid, testbed_id, testbed_version)
+            self.attributes_to_data(data, guid, testbed_description.attributes)
             for box in testbed_description.boxes:
-                data[box.guid] = self.box_to_data(guid, box)
+                data.add_box_data(box.guid, guid, box.factory_id)
+                self.factory_attributes_to_data(data, box.guid, 
+                        box.factory_attributes)
+                self.attributes_to_data(data, box.guid, box.attributes)
+                self.traces_to_data(data, box.guid, box.traces)
+                self.connections_to_data(data, box.guid, box.connectors)
+                self.addresses_to_data(data, box.guid, box.addresses)
+                self.routes_to_data(data, box.guid, box.routes)
         return data
 
-    def testbed_to_data(self, testbed_description):
-        elem = dict()
-        elem["testbed_id"] = testbed_description.provider.testbed_id
-        elem["testbed_version"] = testbed_description.provider.testbed_version
-        return elem 
-
-    def box_to_data(self, testbed_guid, box):
-        elem = dict()
-        elem["testbed_guid"] = testbed_guid
-        elem["factory_id"] = box.factory_id
-        fattrs = self.factory_attributes_to_data(box.factory_attributes)
-        if fattrs:
-            elem["factory_attributes"] = fattrs
-        attrs = self.attributes_to_data(box.attributes)
-        if attrs:
-            elem["attributes"] = attrs
-        traces = self.traces_to_data(box.traces)
-        if traces:
-            elem["traces"] = traces
-        connections = self.connections_to_data(box.connectors)
-        if connections:
-            elem["connections"] = connections
-        addresses = self.addresses_to_data(box.addresses)
-        if addresses:
-            elem["addresses"] = addresses
-        routes = self.routes_to_data(box.routes)
-        if routes:
-            elem["routes"] = routes
-        return elem
-
-    def factory_attributes_to_data(self, attributes):
-        fattrs = dict()
+    def factory_attributes_to_data(self, data, guid, attributes):
         for attribute in attributes:
             if attribute.modified:
-                fattrs[attribute.name] = attribute.value
-        return fattrs if len(fattrs) > 0 else None
+                data.add_factory_attribute_data(guid, attribute.name, 
+                        attribute.value)
 
-    def attributes_to_data(self, attributes):
-        attrs = dict()
+    def attributes_to_data(self, data, guid, attributes):
         for attribute in attributes:
             if attribute.modified:
-                attrs[attribute.name] = attribute.value
-        return attrs if len(attrs) > 0 else None
+                data.add_attribute_data(guid, attribute.name, attribute.value)
 
-    def traces_to_data(self, traces):
-        trcs = list()
+    def traces_to_data(self, data, guid, traces):
         for trace in traces:
             if trace.enabled:
-                trcs.append(trace.name)
-        return trcs if len(trcs) > 0 else None
+                data.add_trace_data(guid, trace.name)
 
-    def connections_to_data(self, connectors):
-        cnctrs = dict()
+    def connections_to_data(self, data, guid, connectors):
         for connector in connectors:
-            cnxs = dict()
+            connector_type_name = connector.connector_type.name
             for other_connector in connector.connections:
-                guid = other_connector.box.guid
-                cnxs[guid] = other_connector.connector_type.name
-            if len(cnxs) > 0:
-                cnctrs[connector.connector_type.name] = cnxs
-        return cnctrs if len(cnctrs) > 0 else None
-
-    def addresses_to_data(self, addresses):
-        addrs = list()
-        for address in addresses:
-            addr = dict()
-            for attribute in address.attributes:
-                if attribute.modified:
-                    addr[attribute.name] = attribute.value
-            addrs.append(addr)
-        return addrs if len(addrs) > 0 else None
-
-    def routes_to_data(self, routes):
-        rts = list()
+                other_guid = other_connector.box.guid
+                other_connector_type_name = other_connector.connector_type.name
+                data.add_connection_data(guid, connector_type_name, other_guid,
+                        other_connector_type_name)
+
+    def addresses_to_data(self, data, guid, addresses):
+        for addr in addresses:
+             autoconf = addr.get_attribute_value("AutoConfigure") \
+                    if addr.is_attribute_modified("AutoConfigure") else None
+             address = addr.get_attribute_value("Address") \
+                    if addr.is_attribute_modified("Address") else None
+             netprefix = addr.get_attribute_value("NetPrefix") \
+                    if addr.is_attribute_modified("NetPrefix") else None
+             family = addr.get_attribute_value("Family") \
+                    if addr.is_attribute_modified("Family") else None
+             broadcast = addr.get_attribute_value("Broadcast") \
+                    if addr.has_attribute("Broadcast") and \
+                     addr.is_attribute_modified("Broadcast") else None
+             data.add_address_data(guid, autoconf, address, family, netprefix, 
+                    broadcast)
+
+    def routes_to_data(self, data, guid, routes):
         for route in routes:
-            rt = dict()
-            for attribute in route.attibutes:
-                if attribute.modified:
-                    rt[attribute.name] = attribute.value
-            rts.append(rt)
-        return rts if len(rts) > 0 else None
+             family = route.get_attribute_value("Family")
+             destination = route.get_attribute_value("Destination")
+             netprefix = route.get_attribute_value("NetPrefix")
+             nexthop = route.get_attribute_value("NextHop")
+             interface = route.get_attribute_value("Interface")
+             data.add_route_data(guid, family, destination, netprefix, nexthop, 
+                    interface)
 
     def from_data(self, experiment_description, data):
-        connections_data = dict()
-        for guid, elem_data in data.iteritems():
-            if "testbed_id" in elem_data:
-                self.testbed_from_data(experiment_description, elem_data)
+        box_guids = list()
+        for guid in data.guids:
+            if data.is_testbed_data(guid):
+                self.testbed_from_data(experiment_description, guid, data)
             else:
-                self.box_from_data(experiment_description, elem_data)
-                if "connections" in elem_data:
-                    connections_data[guid] = elem_data["connections"]
-        # Connections need all boxes to be created
-        self.connections_from_data(experiment_description, connections_data)
-        return experiment_description
-
-    def testbed_from_data(self, experiment_description, data):
-        testbed_id = data["testbed_id"]
-        testbed_version = data["testbed_version"]
+                self.box_from_data(experiment_description, guid, data)
+                box_guids.append(guid)
+        self.connections_from_data(experiment_description, box_guids, data)
+
+    def testbed_from_data(self, experiment_description, guid, data):
+        (testbed_id, testbed_version) = data.get_testbed_data(guid)
         mod_name = 'nepi.testbeds.%s' % testbed_id
         if not mod_name in sys.modules:
             __import__(mod_name)
         testbed_mod = sys.modules[mod_name]
         provider = testbed_mod.TestbedFactoriesProvider(testbed_version)
         experiment_description.add_testbed_description(provider)
+        testbed_description = experiment_description.testbed_description(guid)
+        self.attributes_from_data(testbed_description, data)
 
-    def box_from_data(self, experiment_description, data):
-        testbed_guid = data["testbed_guid"]
+    def box_from_data(self, experiment_description, guid, data):
+        (testbed_guid, factory_id) = data.get_box_data(guid)
         testbed_description = experiment_description.testbed_description(
                 testbed_guid)
-        factory_id = data["factory_id"]
-        if "factory_attributes" in data:
-            self.factory_attributes_from_data(factory_id, testbed_description, 
-                    data["factory_attributes"])
+        self.factory_attributes_from_data(testbed_description, factory_id,
+                guid, data)
         box = testbed_description.create(factory_id)
-        if "attributes" in data:
-            self.attributes_from_data(box, data["attributes"])
-        if "traces" in data:
-            self.traces_from_data(box, data["traces"])
-        if "addresses" in data:
-            self.addresses_from_data(box, data["addresses"])
-        if "routes" in data:
-            self.routes_from_data(box, experiment_description, data["routes"])
-
-    def factory_attributes_from_data(self, factory_id, testbed_description, 
-            data):
+        self.attributes_from_data(box, data)
+        self.traces_from_data(box, data)
+        self.addresses_from_data(box, data)
+        self.routes_from_data(box, data)
+
+    def factory_attributes_from_data(self, testbed_description, factory_id, 
+            guid, data):
         factory = testbed_description.provider.factory(factory_id)
-        for name, value in data.iteritems():
+        for (name, value) in data.get_factory_attribute_data(guid):
             factory.set_attribute_value(name, value)
 
-    def attributes_from_data(self, box, data):
-        for name, value in data.iteritems():
-            box.set_attribute_value(name, value)
+    def attributes_from_data(self, element, data):
+        for name, value in data.get_attribute_data(element.guid):
+            element.set_attribute_value(name, value)
 
     def traces_from_data(self, box, data):
-        for name in data:
+        for name in data.get_trace_data(box.guid):
             box.trace(name).enable()
 
-    def connections_from_data(self, experiment_description, data):
-        for guid, connector_data in data.iteritems():
+    def addresses_from_data(self, box, data):
+        for (autoconf, address, family, netprefix, broadcast) \
+                in data.get_address_data(box.guid):
+            addr = box.add_address()
+            if autoconf:
+                addr.set_attribute_value("AutoConfigure", autoconf)
+            if address:
+                addr.set_attribute_value("Address", address)
+            if family:
+                addr.set_attribute_value("Family", family)
+            if netprefix:
+                addr.set_attribute_value("NetPrefix", netprefix)
+            if broadcast:
+                addr.set_attribute_value("Broadcast", broadcast)
+
+    def routes_from_data(self, box, data):
+         for (family, destination, netprefix, nexthop, interface) \
+                in data.get_route_data(box.guid):
+            addr = box.add_route(family)
+            addr.set_attribute_value("Destination", destination)
+            addr.set_attribute_value("NetPrefix", netprefix)
+            addr.set_attribute_value("NextHop", nexthop)
+            addr.set_attribute_value("Interface", interface)
+
+    def connections_from_data(self, experiment_description, guids, data):
+        for guid in guids:
             box = experiment_description.box(guid)
-            for connector_type_name, connections in connector_data.iteritems():
-                for guid, other_connector_type_name in connections.iteritems():
-                    other_box = experiment_description.box(guid)
+            for (connector_type_name, other_guid, other_connector_type_name) \
+                    in data.get_connection_data(guid):
+                    other_box = experiment_description.box(other_guid)
                     connector = box.connector(connector_type_name)
                     other_connector = other_box.connector(
                             other_connector_type_name)
                     if not connector.is_connected(other_connector):
                         connector.connect(other_connector)
 
-    def addresses_from_data(self, box, data):
-        for address_attrs in data:
-            addr = box.add_address()
-            for name, value in address_attrs.iteritems():
-                addr.set_attribute_value(name, value)
-
-    def routes_from_data(self, box, experiment_description, data):
-        for route_attrs in data:
-            route = box.add_route()
-            for name, value in route_attrs.iteritems():
-                route.set_attribute_value(name, value)