--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Common connector base classes
+"""
+
+import sys
+
+class ConnectorTypeBase(object):
+ def __init__(self, testbed_id, factory_id, name, max = -1, min = 0):
+ super(ConnectorTypeBase, self).__init__()
+ if max == -1:
+ max = sys.maxint
+ elif max <= 0:
+ raise RuntimeError, "The maximum number of connections allowed need to be more than 0"
+ if min < 0:
+ raise RuntimeError, "The minimum number of connections allowed needs to be at least 0"
+ # connector_type_id -- univoquely identifies a connector type
+ # across testbeds
+ self._connector_type_id = self.make_connector_type_id(
+ testbed_id, factory_id, name)
+ # name -- display name for the connector type
+ self._name = name
+ # max -- maximum amount of connections that this type support,
+ # -1 for no limit
+ self._max = max
+ # min -- minimum amount of connections required by this type of connector
+ self._min = min
+
+ @property
+ def connector_type_id(self):
+ return self._connector_type_id
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def max(self):
+ return self._max
+
+ @property
+ def min(self):
+ return self._min
+
+ @staticmethod
+ def make_connector_type_id(testbed_id, factory_id, name):
+ testbed_id = testbed_id.lower() if testbed_id else None
+ factory_id = factory_id.lower() if factory_id else None
+ name = name.lower() if name else None
+ return (testbed_id, factory_id, name)
+
+ @staticmethod
+ def _type_resolution_order(connector_type_id):
+ testbed_id, factory_id, name = connector_type_id
+
+ # the key is always a candidate
+ yield connector_type_id
+
+ # Try wildcard combinations
+ if (testbed_id, None, name) != connector_type_id:
+ yield (testbed_id, None, name)
+ if (None, factory_id, name) != connector_type_id:
+ yield (None, factory_id, name)
+ if (None, None, name) != connector_type_id:
+ yield (None, None, name)
+
+
"""
from nepi.core.attributes import AttributesMap, Attribute
+from nepi.core.connector import ConnectorTypeBase
from nepi.core.metadata import Metadata
from nepi.util import validation
from nepi.util.guid import GuidGenerator
from nepi.util.graphical_info import GraphicalInfo
from nepi.util.parser._xml import XmlExperimentParser
import sys
+
+
-class ConnectorType(object):
+class ConnectorType(ConnectorTypeBase):
def __init__(self, testbed_id, factory_id, name, help, max = -1, min = 0):
- super(ConnectorType, self).__init__()
- if max == -1:
- max = sys.maxint
- elif max <= 0:
- raise RuntimeError(
- "The maximum number of connections allowed need to be more than 0")
- if min < 0:
- raise RuntimeError(
- "The minimum number of connections allowed needs to be at least 0")
- # connector_type_id -- univoquely identifies a connector type
- # across testbeds
- self._connector_type_id = (testbed_id.lower(), factory_id.lower(),
- name.lower())
- # name -- display name for the connector type
- self._name = name
+ super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min)
+
# help -- help text
self._help = help
- # max -- maximum amount of connections that this type support,
- # -1 for no limit
- self._max = max
- # min -- minimum amount of connections required by this type of connector
- self._min = min
+
# allowed_connections -- keys in the dictionary correspond to the
# connector_type_id for possible connections. The value indicates if
# the connection is allowed accros different testbed instances
self._allowed_connections = dict()
- @property
- def connector_type_id(self):
- return self._connector_type_id
-
@property
def help(self):
return self._help
- @property
- def name(self):
- return self._name
-
- @property
- def max(self):
- return self._max
-
- @property
- def min(self):
- return self._min
-
def add_allowed_connection(self, testbed_id, factory_id, name, can_cross):
- self._allowed_connections[(testbed_id.lower(),
- factory_id.lower(), name.lower())] = can_cross
+ type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+ self._allowed_connections[type_id] = can_cross
def can_connect(self, connector_type_id, testbed_guid1, testbed_guid2):
- if not connector_type_id in self._allowed_connections.keys():
+ for lookup_type_id in self._type_resolution_order(connector_type_id):
+ if lookup_type_id in self._allowed_connections:
+ can_cross = self._allowed_connections[lookup_type_id]
+ return can_cross or (testbed_guid1 == testbed_guid2)
+ else:
return False
- can_cross = self._allowed_connections[connector_type_id]
- return can_cross or (testbed_guid1 == testbed_guid2)
class Connector(object):
"""A Connector sepcifies the connection points in an Object"""
# -*- coding: utf-8 -*-
from nepi.core.attributes import Attribute, AttributesMap
+from nepi.core.connector import ConnectorTypeBase
from nepi.util import proxy, validation
from nepi.util.constants import STATUS_FINISHED, TIME_NOW
from nepi.util.parser._xml import XmlExperimentParser
ATTRIBUTE_PATTERN_GUID_SUB = r"{#[%(guid)s]%(expr)s#}"
COMPONENT_PATTERN = re.compile(r"(?P<kind>[a-z]*)\[(?P<index>.*)\]")
-class ConnectorType(object):
+class ConnectorType(ConnectorTypeBase):
def __init__(self, testbed_id, factory_id, name, max = -1, min = 0):
- super(ConnectorType, self).__init__()
- if max == -1:
- max = sys.maxint
- elif max <= 0:
- raise RuntimeError(
- "The maximum number of connections allowed need to be more than 0")
- if min < 0:
- raise RuntimeError(
- "The minimum number of connections allowed needs to be at least 0")
- # connector_type_id -- univoquely identifies a connector type
- # across testbeds
- self._connector_type_id = (testbed_id.lower(), factory_id.lower(),
- name.lower())
- # name -- display name for the connector type
- self._name = name
- # max -- maximum amount of connections that this type support,
- # -1 for no limit
- self._max = max
- # min -- minimum amount of connections required by this type of connector
- self._min = min
+ super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min)
# from_connections -- connections where the other connector is the "From"
# to_connections -- connections where the other connector is the "To"
# keys in the dictionary correspond to the
self._from_connections = dict()
self._to_connections = dict()
- @property
- def connector_type_id(self):
- return self._connector_type_id
-
- @property
- def name(self):
- return self._name
-
- @property
- def max(self):
- return self._max
-
- @property
- def min(self):
- return self._min
-
def add_from_connection(self, testbed_id, factory_id, name, can_cross, code):
- self._from_connections[(testbed_id.lower(), factory_id.lower(),
- name.lower())] = (can_cross, code)
+ type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+ self._from_connections[type_id] = (can_cross, code)
def add_to_connection(self, testbed_id, factory_id, name, can_cross, code):
- self._to_connections[(testbed_id.lower(), factory_id.lower(),
- name.lower())] = (can_cross, code)
+ type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+ self._to_connections[type_id] = (can_cross, code)
def can_connect(self, testbed_id, factory_id, name, count,
must_cross = False):
- connector_type_id = (testbed_id.lower(), factory_id.lower(),
- name.lower())
- if connector_type_id in self._from_connections:
- (can_cross, code) = self._from_connections[connector_type_id]
- elif connector_type_id in self._to_connections:
- (can_cross, code) = self._to_connections[connector_type_id]
+ connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+ for lookup_type_id in self._type_resolution_order(connector_type_id):
+ if lookup_type_id in self._from_connections:
+ (can_cross, code) = self._from_connections[lookup_type_id]
+ elif lookup_type_id in self._to_connections:
+ (can_cross, code) = self._to_connections[lookup_type_id]
+ else:
+ # keey trying
+ continue
+ return not must_cross or can_cross
else:
return False
- return not must_cross or can_cross
def code_to_connect(self, testbed_id, factory_id, name):
- connector_type_id = (testbed_id.lower(), factory_id.lower(),
- name.lower())
- if not connector_type_id in self._to_connections.keys():
+ connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
+ for lookup_type_id in self._type_resolution_order(connector_type_id):
+ if lookup_type_id in self._to_connections:
+ (can_cross, code) = self._to_connections[lookup_type_id]
+ return code
+ else:
return False
- (can_cross, code) = self._to_connections[connector_type_id]
- return code
# TODO: create_function, start_function, stop_function, status_function
# need a definition!