00001
00002
00003
00004 '''rtsprofile
00005
00006 Copyright (C) 2009-2010
00007 Geoffrey Biggs
00008 RT-Synthesis Research Group
00009 Intelligent Systems Research Institute,
00010 National Institute of Advanced Industrial Science and Technology (AIST),
00011 Japan
00012 All rights reserved.
00013 Licensed under the Eclipse Public License -v 1.0 (EPL)
00014 http://www.opensource.org/licenses/eclipse-1.0.txt
00015
00016 File: exec_context.py
00017
00018 Object representing a component's execution context.
00019
00020 '''
00021
00022 __version__ = '$Revision: $'
00023
00024
00025
00026 from rtsprofile import RTS_NS, RTS_NS_S, RTS_EXT_NS, RTS_EXT_NS_S, \
00027 RTS_EXT_NS_YAML
00028 from rtsprofile.participant import Participant
00029 from rtsprofile.utils import get_direct_child_elements_xml, \
00030 indent_string, parse_properties_xml, \
00031 properties_to_xml, validate_attribute
00032
00033
00034
00035
00036
00037 class ExecutionContext(object):
00038 '''Represents an execution context being used in the RT system.'''
00039
00040 def __init__(self, id='', kind='', rate=0.0):
00041 '''Constructor.
00042
00043 @param id The ID of this execution context.
00044 @type id str
00045 @param kind The action execution type used by this context.
00046 @type kind str
00047 @param rate The execution rate of this context, if it is periodic.
00048 @type float
00049
00050 '''
00051 validate_attribute(id, 'execution_context.id',
00052 expected_type=[str, unicode], required=False)
00053 self._id = id
00054 validate_attribute(kind, 'execution_context.kind',
00055 expected_type=[str, unicode], required=False)
00056 self._kind = kind
00057 validate_attribute(rate, 'execution_context.rate',
00058 expected_type=[int, float], required=False)
00059 self._rate = rate
00060 self._participants = []
00061 self._properties = {}
00062
00063 def __str__(self):
00064 result = 'ID: {0}\nKind: {1}\nRate: {2}\n'.format(self.id, self.kind,
00065 self.rate)
00066 if self.participants:
00067 result += 'Participants:\n'
00068 for p in self.participants:
00069 result += '{0}\n'.format(indent_str(str(p)))
00070 if self.properties:
00071 result += 'Properties:\n'
00072 for p in self.properties:
00073 result += ' {0}: {1}\n'.format(p, self.properties[p])
00074 return result[:-1]
00075
00076 @property
00077 def id(self):
00078 '''The ID used to identify this execution context.'''
00079 return self._id
00080
00081 @id.setter
00082 def id(self, id):
00083 validate_attribute(id, 'execution_context.id',
00084 expected_type=[str, unicode], required=True)
00085 self._id = id
00086
00087 @property
00088 def kind(self):
00089 '''The action execution type used by this context.
00090
00091 Valid values are supposed to be in the specification appendix, but they
00092 aren't. The best way to find them is to create a system with
00093 RTSystemEditor and look at the XML. A common valid value is
00094 PeriodicExecutionContext.
00095
00096 '''
00097 return self._kind
00098
00099 @kind.setter
00100 def kind(self, kind):
00101 validate_attribute(kind, 'execution_context.kind',
00102 expected_type=[str, unicode], required=True)
00103 self._kind = kind
00104
00105 @property
00106 def participants(self):
00107 '''The components participating in this execution context.
00108
00109 An ordered list. May be an empty list if no components are
00110 participating in this context.
00111
00112 '''
00113 return self._participants
00114
00115 @participants.setter
00116 def participants(self, participants):
00117 validate_attribute(participants, 'execution_context.participants',
00118 expected_type = list)
00119 self._participants = participants
00120
00121 @property
00122 def rate(self):
00123 '''The execution rate of this context, if it has one, in Hertz.
00124
00125 This value is only used if the execution context is periodic for a data
00126 flow component.
00127
00128 '''
00129 return self._rate
00130
00131 @rate.setter
00132 def rate(self, rate):
00133 validate_attribute(rate, 'execution_context.rate',
00134 expected_type=[int, float], required=False)
00135 self._rate = rate
00136
00137 @property
00138 def properties(self):
00139 '''Miscellaneous properties.
00140
00141 Stores key/value pair properties.
00142
00143 Part of the extended profile.
00144
00145 '''
00146 return self._properties
00147
00148 @properties.setter
00149 def properties(self, properties):
00150 validate_attribute(properties, 'execution_context.ext.Properties',
00151 expected_type=dict, required=False)
00152 self._properties = properties
00153
00154 def parse_xml_node(self, node):
00155 '''Parse an xml.dom Node object representing an execution context into
00156 this object.
00157
00158 '''
00159 self.id = node.getAttributeNS(RTS_NS, 'id')
00160 self.kind = node.getAttributeNS(RTS_NS, 'kind')
00161 if node.hasAttributeNS(RTS_NS, 'rate'):
00162 self.rate = float(node.getAttributeNS(RTS_NS, 'rate'))
00163 else:
00164 self.rate = 0.0
00165 self._participants = []
00166 for c in node.getElementsByTagNameNS(RTS_NS, 'Participants'):
00167 self._participants.append(TargetComponent().parse_xml_node(c))
00168 for c in get_direct_child_elements_xml(node, prefix=RTS_EXT_NS,
00169 local_name='Properties'):
00170 name, value = parse_properties_xml(c)
00171 self._properties[name] = value
00172 return self
00173
00174 def parse_yaml(self, y):
00175 '''Parse a YAML spefication of an execution context into this
00176 object.
00177
00178 '''
00179 self.id = y['id']
00180 self.kind = y['kind']
00181 if 'rate' in y:
00182 self.rate = float(y['rate'])
00183 else:
00184 self.rate = 0.0
00185 self._participants = []
00186 if 'participants' in y:
00187 for p in y.get('participants'):
00188 self._participants.append(TargetComponent().parse_yaml(p))
00189 if RTS_EXT_NS_YAML + 'properties' in y:
00190 for p in y.get(RTS_EXT_NS_YAML + 'properties'):
00191 if 'value' in p:
00192 value = p['value']
00193 else:
00194 value = None
00195 self._properties[p['name']] = value
00196 return self
00197
00198 def save_xml(self, doc, element):
00199 '''Save this execution context into an xml.dom.Element object.'''
00200 element.setAttributeNS(RTS_NS, RTS_NS_S + 'id', self.id)
00201 element.setAttributeNS(RTS_NS, RTS_NS_S + 'kind', self.kind)
00202 element.setAttributeNS(RTS_NS, RTS_NS_S + 'rate', str(self.rate))
00203 for p in self.participants:
00204 new_element = doc.createElementNS(RTS_NS,
00205 RTS_NS_S + 'Participants')
00206 p.save_xml(doc, new_element)
00207 element.appendChild(new_element)
00208 for p in self.properties:
00209 new_prop_element = doc.createElementNS(RTS_EXT_NS,
00210 RTS_EXT_NS_S + 'Properties')
00211 properties_to_xml(new_prop_element, p, self.properties[p])
00212 element.appendChild(new_prop_element)
00213
00214 def to_dict(self):
00215 '''Save this execution context into a dictionary.'''
00216 d = {'id': self.id,
00217 'kind': self.kind}
00218 if self.rate != 0.0:
00219 d['rate'] = self.rate
00220 participants = []
00221 for p in self.participants:
00222 participants.append(p.to_dict())
00223 if participants:
00224 d['participants'] = participants
00225 props = []
00226 for name in self.properties:
00227 p = {'name': name}
00228 if self.properties[name]:
00229 p['value'] = str(self.properties[name])
00230 props.append(p)
00231 if props:
00232 d[RTS_EXT_NS_YAML + 'properties'] = props
00233 return d
00234
00235
00236
00237