message_sending.py
Go to the documentation of this file.
00001 # -*- Python -*-
00002 # -*- coding: utf-8 -*-
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: message_sending.py
00017 
00018 Objects for the message sending interface.
00019 
00020 '''
00021 
00022 __version__ = '$Revision: $'
00023 # $Source$
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.exceptions import InvalidParticipantNodeError
00029 from rtsprofile.targets import TargetExecutionContext
00030 from rtsprofile.utils import get_direct_child_elements_xml, \
00031                              indent_string, validate_attribute
00032 
00033 
00034 ##############################################################################
00035 ## MessageSending base object
00036 
00037 class MessageSending(object):
00038     '''Defines the orderings and conditions components in the RT system for
00039     various actions.
00040 
00041     '''
00042 
00043     def __init__(self, targets=[]):
00044         '''@param targets Orderings and conditions.'''
00045         validate_attribute(targets, 'message_sending.Targets',
00046                            expected_type=list, required=False)
00047         self._targets = targets
00048 
00049     def __str__(self):
00050         result = self.__class__.__name__ + '\n'
00051         if self.targets:
00052             result += 'Targets:\n'
00053             for t in self.targets:
00054                 result += '{0}\n'.format(indent_string(str(t)))
00055         return result[:-1] # Lop off the last new line
00056 
00057     @property
00058     def targets(self):
00059         '''Orderings and conditions.'''
00060         return self._targets
00061 
00062     @targets.setter
00063     def targets(self, targets):
00064         validate_attribute(targets, 'message_sending.targets',
00065                            expected_type=list, required=False)
00066         self._targets = targets
00067 
00068     def parse_xml_node(self, node):
00069         '''Parse an xml.dom Node object representing a message sending object
00070         into this object.
00071 
00072         '''
00073         self._targets = []
00074         for c in node.getElementsByTagNameNS(RTS_NS, 'targets'):
00075             if c.getElementsByTagNameNS(RTS_NS, 'WaitTime'):
00076                 new_target = WaitTime()
00077             elif c.getElementsByTagNameNS(RTS_NS, 'Preceding'):
00078                 new_target = Preceding()
00079             else:
00080                 new_target = Condition()
00081             new_target.parse_xml_node(c)
00082             self._targets.append(new_target)
00083         return self
00084 
00085     def parse_yaml(self, y):
00086         '''Parse a YAML speficication of a message sending object into this
00087         object.
00088 
00089         '''
00090         self._targets = []
00091         if 'targets' in y:
00092             for t in y['targets']:
00093                 if 'waitTime' in t['condition']:
00094                     new_target = WaitTime()
00095                 elif 'preceding' in t['condition']:
00096                     new_target = Preceding()
00097                 else:
00098                     new_target = Condition()
00099                 new_target.parse_yaml(t)
00100                 self._targets.append(new_target)
00101         return self
00102 
00103     def save_xml(self, doc, element):
00104         '''Save this message_sending object into an xml.dom.Element object.'''
00105         for cond in self._targets:
00106             new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'targets')
00107             cond.save_xml(doc, new_element)
00108             element.appendChild(new_element)
00109 
00110     def to_dict(self):
00111         '''Save this message sending object into a dictionary.'''
00112         targets = []
00113         for cond in self._targets:
00114             targets.append(cond.to_dict())
00115         if targets:
00116             return {'targets': targets}
00117         else:
00118             return {}
00119 
00120 
00121 ##############################################################################
00122 ## StartUp object
00123 
00124 class StartUp(MessageSending):
00125     '''Specifies the start order and conditions of components when the RT
00126     system is started.
00127 
00128     '''
00129     pass
00130 
00131 
00132 ##############################################################################
00133 ## ShutDown object
00134 
00135 class ShutDown(MessageSending):
00136     '''Specifies the stop order and conditions of components when the RT system
00137     is stopped.
00138 
00139     '''
00140     pass
00141 
00142 
00143 ##############################################################################
00144 ## Activation object
00145 
00146 class Activation(MessageSending):
00147     '''Specifies the activation order and conditions of components when the RT
00148     system is activated.
00149 
00150     '''
00151     pass
00152 
00153 
00154 ##############################################################################
00155 ## Deactivation object
00156 
00157 class Deactivation(MessageSending):
00158     '''Specifies the deactivation order and conditions of components when the RT
00159     system is deactivated.
00160 
00161     '''
00162     pass
00163 
00164 
00165 ##############################################################################
00166 ## Resetting object
00167 
00168 class Resetting(MessageSending):
00169     '''Specifies the reset order and conditions of components when the RT
00170     system is reset.
00171 
00172     '''
00173     pass
00174 
00175 
00176 ##############################################################################
00177 ## Initialize object
00178 
00179 class Initialize(MessageSending):
00180     '''Specifies the initialisation order and conditions of components when the
00181     RT system is initialised.
00182 
00183     '''
00184     pass
00185 
00186 
00187 ##############################################################################
00188 ## Finalize object
00189 
00190 class Finalize(MessageSending):
00191     '''Specifies the finalisation order and conditions of components when the
00192     RT system is finalised.
00193 
00194     '''
00195     pass
00196 
00197 
00198 ##############################################################################
00199 ## Condition base object
00200 
00201 class Condition(object):
00202     '''Specifies execution orderings and conditions for RT components in the RT
00203     system.
00204 
00205     Execution conditions can include the time to wait before executing and
00206     order of precedence for components. The involved RT component is specified
00207     using @ref TargetExecutionContext.
00208 
00209     '''
00210 
00211     def __init__(self, sequence=0, target_component=TargetExecutionContext()):
00212         '''Constructor.
00213 
00214         @param sequence Execution order of the target component.
00215         @type sequence int
00216         @param target_component The target of the condition.
00217         @type target_component TargetComponent
00218         '''
00219         validate_attribute(sequence, 'conditions.sequence',
00220                            expected_type=int, required=False)
00221         self._sequence = sequence
00222         validate_attribute(target_component, 'conditions.TargetComponent',
00223                            expected_type=TargetExecutionContext,
00224                            required=True)
00225         self._target_component = target_component
00226         self._properties = {}
00227 
00228     def __str__(self):
00229         result = 'Sequence: {0}\nTargetEC:\n{1}\n'.format(self.sequence,
00230                 indent_string(str(self.target_component)))
00231         if self.properties:
00232             result += 'Properties:\n'
00233             for p in self.properties:
00234                 result += '  {0}: {1}\n'.format(p, self.properties[p])
00235         return result[:-1] # Lop off the last new line
00236 
00237     @property
00238     def sequence(self):
00239         '''The execution order of the target components for the various
00240         actions.
00241 
00242         '''
00243         return self._sequence
00244 
00245     @sequence.setter
00246     def sequence(self, sequence):
00247         validate_attribute(sequence, 'conditions.sequence',
00248                            expected_type=int, required=False)
00249         self._sequence = sequence
00250 
00251     @property
00252     def target_component(self):
00253         '''Target component of the condition.'''
00254         return self._target_component
00255 
00256     @target_component.setter
00257     def target_component(self, target_component):
00258         validate_attribute(target_component, 'conditions.TargetComponent',
00259                            expected_type=TargetExecutionContext,
00260                            required=True)
00261         self._target_component = target_component
00262 
00263     @property
00264     def properties(self):
00265         '''Miscellaneous properties.
00266 
00267         Stores key/value pair properties.
00268 
00269         Part of the extended profile.
00270 
00271         '''
00272         return self._properties
00273 
00274     @properties.setter
00275     def properties(self, properties):
00276         validate_attribute(properties, 'conditions.ext.Properties',
00277                            expected_type=dict, required=False)
00278         self._properties = properties
00279 
00280     def parse_xml_node(self, node):
00281         '''Parse an xml.dom Node object representing a condition into this
00282         object.
00283 
00284         '''
00285         self.sequence = int(node.getAttributeNS(RTS_NS, 'sequence'))
00286         c = node.getElementsByTagNameNS(RTS_NS, 'TargetComponent')
00287         if c.length != 1:
00288             raise InvalidParticipantNodeError
00289         self.target_component = TargetExecutionContext().parse_xml_node(c[0])
00290         for c in get_direct_child_elements_xml(node, prefix=RTS_EXT_NS,
00291                                                local_name='Properties'):
00292             name, value = parse_properties_xml(c)
00293             self._properties[name] = value
00294         return self
00295 
00296     def parse_yaml(self, y):
00297         '''Parse a YAML specification of a condition into this object.'''
00298         self.sequence = int(y['sequence'])
00299         self.target_component = \
00300                 TargetExecutionContext().parse_yaml(y['targetComponent'])
00301         if RTS_EXT_NS_YAML + 'properties' in y:
00302             for p in y.get(RTS_EXT_NS_YAML + 'properties'):
00303                 if 'value' in p:
00304                     value = p['value']
00305                 else:
00306                     value = None
00307                 self._properties[p['name']] = value
00308         return self
00309 
00310     def save_xml(self, doc, element):
00311         '''Save this condition into an xml.dom.Element object.'''
00312         element.setAttributeNS(RTS_NS, RTS_NS_S + 'sequence',
00313                                str(self.sequence))
00314         new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'TargetComponent')
00315         self.target_component.save_xml(doc, new_element)
00316         element.appendChild(new_element)
00317         for p in self.properties:
00318             new_prop_element = doc.createElementNS(RTS_EXT_NS,
00319                                                    RTS_EXT_NS_S + 'Properties')
00320             properties_to_xml(new_prop_element, p, self.properties[p])
00321             element.appendChild(new_prop_element)
00322 
00323     def to_dict(self):
00324         '''Save this condition into a dictionary.'''
00325         d = {'sequence': self.sequence,
00326                 'targetComponent': self.target_component.to_dict()}
00327         props = []
00328         for name in self.properties:
00329             p = {'name': name}
00330             if self.properties[name]:
00331                 p['value'] = str(self.properties[name])
00332             props.append(p)
00333         if props:
00334             d[RTS_EXT_NS_YAML + 'properties'] = props
00335         return d
00336 
00337 
00338 ##############################################################################
00339 ## Preceding object
00340 
00341 class Preceding(Condition):
00342     '''Specifies that the target RT component should precede other RT
00343     components that are part of the same action (e.g. activation) when that
00344     action is executed.
00345 
00346     '''
00347 
00348     def __init__(self, sequence=0, target_component=TargetExecutionContext(),
00349                  timeout=0, sending_timing='', preceding_components=[]):
00350         '''Constructor.
00351 
00352         @param sequence Execution order of the target component.
00353         @type sequence int
00354         @param target_component The target of the condition.
00355         @type target_component TargetComponent
00356         @param timeout Status check timeout.
00357         @type timeout int
00358         @param sending_timing Timing for executing actions.
00359         @type sending_timing str
00360         @param preceding_components Preceding components of the condition.
00361         @type preceding components list(TargetExecutionContext)
00362 
00363         '''
00364         super(Preceding, self).__init__(sequence, target_component)
00365         validate_attribute(timeout, 'preceding.timeout',
00366                            expected_type=int, required=False)
00367         self._timeout = timeout
00368         validate_attribute(sending_timing, 'preceding.sendingTiming',
00369                            expected_type=[str, unicode], required=False)
00370         self._sending_timing = sending_timing
00371         validate_attribute(preceding_components,
00372                            'preceding.PrecedingComponents',
00373                            expected_type=list, required=False)
00374         self._preceding_components = preceding_components
00375 
00376     def __str__(self):
00377         result = 'Timeout: {0}\nSending timing: {1}\n{2}'.format(self.timeout,
00378                 self.sending_timing, Condition.__str__(self))
00379         if self.preceding_components:
00380             for pc in self.preceding_components:
00381                 result += '\nPreceding component:\n{0}'.format(\
00382                         indent_string(str(pc)))
00383         return result
00384 
00385     @property
00386     def timeout(self):
00387         '''Time out for checking if the target component has executed the
00388         action successfully.
00389 
00390         Can be zero. Specified in milliseconds.
00391 
00392         '''
00393         return self._timeout
00394 
00395     @timeout.setter
00396     def timeout(self, timeout):
00397         validate_attribute(timeout, 'preceding.timeout',
00398                            expected_type=int, required=False)
00399         self._timeout = timeout
00400 
00401     @property
00402     def sending_timing(self):
00403         '''Timing for executing actions.
00404 
00405         Either wait for the preceding RT component to finish executing the
00406         action (specified by "SYNC"), or execute the action without waiting for
00407         the preceding RT component to finish (specified by "ASYNC"). When not
00408         specified, the first option will be assumed.
00409 
00410         '''
00411         return self._sending_timing
00412 
00413     @sending_timing.setter
00414     def sending_timing(self, sending_timing):
00415         validate_attribute(sending_timing, 'preceding.sendingTiming',
00416                            expected_type=[str, unicode], required=False)
00417         self._sending_timing = sending_timing
00418 
00419     @property
00420     def preceding_components(self):
00421         '''Preceding components of this condition.'''
00422         return self._preceding_components
00423 
00424     @preceding_components.setter
00425     def preceding_components(self, preceding_components):
00426         validate_attribute(sending_timing, 'preceding.PrecedingComponents',
00427                            expected_type=list, required=False)
00428         self._preceding_components = preceding_components
00429 
00430     def parse_xml_node(self, node):
00431         '''Parse an xml.dom Node object representing a preceding condition into
00432         this object.
00433 
00434         '''
00435         super(Preceding, self).parse_xml_node(node)
00436         p_nodes = node.getElementsByTagNameNS(RTS_NS, 'Preceding')
00437         if p_nodes.length != 1:
00438             raise InvalidParticipantNodeError
00439         p_node = p_nodes[0]
00440         if p_node.hasAttributeNS(RTS_NS, 'timeout'):
00441             self.timeout = int(p_node.getAttributeNS(RTS_NS, 'timeout'))
00442         else:
00443             self.timeout = 0
00444         if p_node.hasAttributeNS(RTS_NS, 'sendingTiming'):
00445             self.sending_timing = p_node.getAttributeNS(RTS_NS, 'sendingTiming')
00446         else:
00447             self.sending_timing = 'ASYNC'
00448         self._preceding_components = []
00449         for c in p_node.getElementsByTagNameNS(RTS_NS, 'PrecedingComponents'):
00450             self._preceding_components.append(TargetExecutionContext().parse_xml_node(c))
00451         return self
00452 
00453     def parse_yaml(self, y):
00454         '''Parse a YAML specification of a preceding condition into this
00455         object.
00456 
00457         '''
00458         super(Preceding, self).parse_yaml(y)
00459         c = y['condition']['preceding']
00460         if 'timeout' in c:
00461             self.timeout = int(c['timeout'])
00462         else:
00463             self.timeout = 0
00464         if 'sendingTiming' in c:
00465             self.sending_timing = c['sendingTiming']
00466         else:
00467             self.sending_timing = 'ASYNC'
00468         self._preceding_components = []
00469         if 'precedingComponents' in c:
00470             for p in c.get('precedingComponents'):
00471                 self._preceding_components.append(TargetExecutionContext().parse_yaml(p))
00472         return self
00473 
00474     def save_xml(self, doc, element):
00475         '''Save this preceding condition into an xml.dom.Element object.'''
00476         super(Preceding, self).save_xml(doc, element)
00477         pre_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'Preceding')
00478         if self.timeout:
00479             pre_element.setAttributeNS(RTS_NS, RTS_NS_S + 'timeout',
00480                     str(self.timeout))
00481         if self.sending_timing:
00482             pre_element.setAttributeNS(RTS_NS, RTS_NS_S + 'sendingTiming',
00483                                    self.sending_timing)
00484         for pc in self._preceding_components:
00485             new_element = doc.createElementNS(RTS_NS,
00486                                               RTS_NS_S + 'PrecedingComponents')
00487             pc.save_xml(doc, new_element)
00488             pre_element.appendChild(new_element)
00489         element.appendChild(pre_element)
00490 
00491     def to_dict(self):
00492         '''Save this preceding condition into a dictionary.'''
00493         d = super(Preceding, self).to_dict()
00494         e = {}
00495         if self.timeout != 0:
00496             e['timeout'] = self.timeout
00497         if self.sending_timing:
00498             e['sendingTiming'] = self.sending_timing
00499         pcs = []
00500         for pc in self._preceding_components:
00501             pcs.append(pc.to_dict())
00502         if pcs:
00503             e['precedingComponents'] = pcs
00504         d['condition'] = {'preceding': e}
00505         return d
00506 
00507 
00508 ##############################################################################
00509 ## WaitTime object
00510 
00511 class WaitTime(Condition):
00512     '''Specifies the time to wait before executing the specified action on the
00513     target RT component. After the action command is received by the RT
00514     component, it will wait the specified length of time before executing it.
00515 
00516     '''
00517 
00518     def __init__(self, wait_time=0, sequence=0,
00519                  target_component=TargetExecutionContext()):
00520         '''Constructor.
00521 
00522         @param sequence Execution order of the target component.
00523         @type sequence int
00524         @param target_component The target of the condition.
00525         @type target_component TargetComponent
00526         @param wait_time The length of time to wait, in milliseconds.
00527         @type wait_time int
00528 
00529         '''
00530         super(WaitTime, self).__init__(sequence, target_component)
00531         validate_attribute(wait_time, 'wait_time.waitTime',
00532                            expected_type=int, required=False)
00533         self._wait_time = wait_time
00534 
00535     def __str__(self):
00536         return 'Wait time: {0}\n{1}'.format(self.wait_time,
00537                                             Condition.__str__(self))
00538 
00539     @property
00540     def wait_time(self):
00541         '''The length of time to wait before executing the specified action.
00542 
00543         In milliseconds.
00544 
00545         '''
00546         return self._wait_time
00547 
00548     @wait_time.setter
00549     def wait_time(self, wait_time):
00550         validate_attribute(wait_time, 'wait_time.waitTime',
00551                            expected_type=int, required=False)
00552         self._wait_time = wait_time
00553 
00554     def parse_xml_node(self, node):
00555         '''Parse an xml.dom Node object representing a wait_time condition into
00556         this object.
00557 
00558         '''
00559         super(WaitTime, self).parse_xml_node(node)
00560         wait_time_nodes = node.getElementsByTagNameNS(RTS_NS, 'WaitTime')
00561         if wait_time_nodes.length != 1:
00562             raise InvalidParticipantNodeError
00563         self.wait_time = int(wait_time_nodes[0].getAttributeNS(RTS_NS,
00564                 'waitTime'))
00565         return self
00566 
00567     def parse_yaml(self, y):
00568         '''Parse a YAML specification of a wait_time condition into this
00569         object.
00570 
00571         '''
00572         super(WaitTime, self).parse_yaml(y)
00573         self.wait_time = int(y['condition']['waitTime']['waitTime'])
00574         return self
00575 
00576     def save_xml(self, doc, element):
00577         '''Save this wait_time condition into an xml.dom.Element object.'''
00578         super(WaitTime, self).save_xml(doc, element)
00579         new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'WaitTime')
00580         new_element.setAttributeNS(RTS_NS, RTS_NS_S + 'waitTime',
00581                 str(self.wait_time))
00582         element.appendChild(new_element)
00583 
00584     def to_dict(self):
00585         '''Save this wait_time condition into a dictionary.'''
00586         d = super(WaitTime, self).to_dict()
00587         d['condition'] = {'waitTime': {'waitTime': self.wait_time}}
00588         return d
00589 
00590 
00591 # vim: tw=79
00592 


rtsprofile
Author(s): Geoffrey Biggs
autogenerated on Thu Aug 27 2015 14:59:19