component.py
Go to the documentation of this file.
1 # -*- Python -*-
2 # -*- coding: utf-8 -*-
3 
4 '''rtsprofile
5 
6 Copyright (C) 2009-2010
7  Geoffrey Biggs
8  RT-Synthesis Research Group
9  Intelligent Systems Research Institute,
10  National Institute of Advanced Industrial Science and Technology (AIST),
11  Japan
12  All rights reserved.
13 Licensed under the Eclipse Public License -v 1.0 (EPL)
14 http://www.opensource.org/licenses/eclipse-1.0.txt
15 
16 File: component.py
17 
18 Object representing a component in an RT system.
19 
20 '''
21 
22 __version__ = '$Revision: $'
23 # $Source$
24 
25 
26 from rtsprofile import RTS_NS, RTS_NS_S, RTS_EXT_NS, RTS_EXT_NS_S, \
27  RTS_EXT_NS_YAML
28 from rtsprofile import composite_type as comp_type
29 from rtsprofile.config_set import ConfigurationSet
30 from rtsprofile.exceptions import InvalidCompositeTypeError
31 from rtsprofile.exec_context import ExecutionContext
32 from rtsprofile.location import Location
33 from rtsprofile.ports import DataPort, ServicePort
34 from rtsprofile.utils import get_direct_child_elements_xml, \
35  indent_string, parse_properties_xml, \
36  properties_to_xml, validate_attribute
37 
38 
39 ##############################################################################
40 ## Component object
41 
42 class Component(object):
43  '''Information about a component contained in an RT system.'''
44 
45  def __init__(self, id='', path_uri='', active_configuration_set='',
46  instance_name='', composite_type=comp_type.NONE,
47  is_required=False, comment='', visible=True,
48  location=Location()):
49  '''@param id Component ID.
50  @type id str
51  @param path_uri Path to the component.
52  @type path_uri str
53  @param active_configuration_set Name of the active configuration set.
54  @type active_configuration_set str
55  @param instance_name Component's instance name.
56  @type instance_name str
57  @param composite_type Type of composition the component is in.
58  @type composite_type CompositeType
59  @param is_required If the component is optional in the system.
60  @type is_required bool
61  @param comment A comment about the component.
62  @type comment str
63  @param visible If this component is visible in graphical displays.
64  @type visible bool
65  @param location The location of this component in graphical displays.
66  @type location Location
67 
68  '''
69  self._reset()
70  validate_attribute(id, 'component.id',
71  expected_type=[str, unicode], required=False)
72  self._id = id
73  validate_attribute(path_uri, 'component.pathUri',
74  expected_type=[str, unicode], required=False)
75  self._path_uri = path_uri
76  validate_attribute(active_configuration_set,
77  'component.activeConfigurationSet',
78  expected_type=[str, unicode], required=False)
79  self._active_config_set = active_configuration_set
80  validate_attribute(instance_name, 'component.instanceName',
81  expected_type=[str, unicode], required=False)
82  self._instance_name = instance_name
83  validate_attribute(composite_type, 'component.compositeType',
84  expected_type=comp_type.const_type, required=False)
85  self._composite_type = composite_type
86  validate_attribute(is_required, 'component.isRequired',
87  expected_type=bool)
88  self._is_required = is_required
89  validate_attribute(comment, 'component.ext.comment',
90  expected_type=[str, unicode], required=False)
91  self._comment = comment
92  validate_attribute(visible, 'component.ext.visible',
93  expected_type=bool, required=False)
94  self._visible = visible
95  validate_attribute(location, 'component.ext.Location',
96  expected_type=Location, required=True)
97  self._location = location
98 
99  def __str__(self):
100  result = 'Instance name: {3}\n ID: {0}\n Path URI: {1}\n Active \
101 configuration set: {2}\n Composite type: {4}\n Is required: {5}\n'.format(\
102  self.id, self.path_uri, self.active_configuration_set,
103  self.instance_name, comp_type.to_string(self.composite_type),
104  self.is_required)
105  if self.comment:
106  result += ' Comment: {0}\n'.format(self.comment)
107  result += ' Visible: {0}\n'.format(self.visible)
108  if self.data_ports:
109  result += ' Data ports:\n'
110  for p in self.data_ports:
111  result += '{0}\n'.format(indent_string(str(p), num_spaces=4))
112  if self.service_ports:
113  result += ' Service ports:\n'
114  for p in self.service_ports:
115  result += '{0}\n'.format(indent_string(str(p), num_spaces=4))
116  if self.configuration_sets:
117  result += ' Configuration sets:\n'
118  for c in self.configuration_sets:
119  result += '{0}\n'.format(indent_string(str(c), num_spaces=4))
120  if self.execution_contexts:
121  result += ' Execution contexts:\n'
122  for e in self.execution_contexts:
123  result += '{0}\n'.format(indent_string(str(e), num_spaces=4))
124  if self.participants:
125  result += ' Participants:\n'
126  for p in self.participants:
127  result += '{0}\n'.format(indent_string(str(p)))
128  result += ' Location:\n{0}\n'.format(indent_string(str(self.location),
129  num_spaces=4))
130  if self.properties:
131  result += ' Properties:\n'
132  for p in self.properties:
133  result += ' {0}: {1}\n'.format(p, self.properties[p])
134  return result[:-1] # Lop off the last new line
135 
136  ###########################################################################
137  # Properties
138 
139  @property
140  def id(self):
141  '''ID of this component in the RT system.
142 
143  In case of the same RT Component specification being used to create
144  multiple RT Components within a single RT system, this ID is prepended
145  to the instance name attribute to distinguish individual components.
146 
147  '''
148  return self._id
149 
150  @id.setter
151  def id(self, id):
152  validate_attribute(id, 'component.id',
153  expected_type=[str, unicode], required=True)
154  self._id = id
155 
156  @property
157  def path_uri(self):
158  '''Path to where this component is registered in URI format.'''
159  return self._path_uri
160 
161  @path_uri.setter
162  def path_uri(self, path_uri):
163  validate_attribute(path_uri, 'component.pathUri',
164  expected_type=[str, unicode], required=True)
165  self._path_uri = path_uri
166 
167  @property
169  '''The ID of the active configuration set of the component.
170 
171  If no configuration set is active, this may be empty.
172 
173  '''
174  return self._active_config_set
175 
176  @active_configuration_set.setter
177  def active_configuration_set(self, active_config_set):
178  validate_attribute(active_config_set,
179  'component.activeConfigurationSet',
180  expected_type=[str, unicode], required=False)
181  self._active_config_set = active_config_set
182 
183  @property
184  def instance_name(self):
185  '''Instance name of the component in the RT system.
186 
187  In case of the same RT Component specification being used to create
188  multiple RT Components within a single RT system, this instance name is
189  appended to the ID attribute to distinguish individual components.
190 
191  '''
192  return self._instance_name
193 
194  @instance_name.setter
195  def instance_name(self, instance_name):
196  validate_attribute(instance_name, 'component.instanceName',
197  expected_type=[str, unicode], required=True)
198  self._instance_name = instance_name
199 
200  @property
201  def composite_type(self):
202  '''The type of composite component this component is involved in.
203 
204  If this component is involved in a composite component, this attribute
205  specifies the type of composition. See @ref CompositeType for valid
206  values.
207 
208  '''
209  return self._composite_type
210 
211  @composite_type.setter
212  def composite_type(self, composite_type):
213  validate_attribute(composite_type, 'component.compositeType',
214  expected_type=comp_type.const_type, required=True)
215  self._composite_type = composite_type
216 
217  @property
218  def is_required(self):
219  '''Specifies if this component is optional in the RT system.
220 
221  Sometimes a component does not need to be present for an RT system to
222  function. If this component must be present for the RT system to
223  function, this attribute will be True.
224 
225  '''
226  return self._is_required
227 
228  @is_required.setter
229  def is_required(self, is_required):
230  validate_attribute(is_required, 'component.isRequired',
231  expected_type=bool)
232  self._is_required = is_required
233 
234  @property
235  def data_ports(self):
236  '''Data ports owned by this component.
237 
238  May be an empty list if this component has no data ports. Members are
239  of type @ref DataPort.
240 
241  '''
242  return self._data_ports
243 
244  @data_ports.setter
245  def data_ports(self, data_ports):
246  validate_attribute(data_ports, 'component.DataPorts',
247  expected_type=list, required=False)
248  self._data_ports = data_ports
249 
250  @property
251  def service_ports(self):
252  '''Service ports owned by this component.
253 
254  May be an empty list if this component has no service ports. Members
255  are of type @ref ServicePort.
256 
257  '''
258  return self._service_ports
259 
260  @service_ports.setter
261  def service_ports(self, service_ports):
262  validate_attribute(service_ports, 'component.ServicePorts',
263  expected_type=list, required=False)
264  self._service_ports = service_ports
265 
266  @property
268  '''The configuration sets in this component.
269 
270  May be an empty list if this component has no configuration sets.
271  Members are of type @ref ConfigurationSet.
272 
273  '''
274  return self._config_sets
275 
276  @configuration_sets.setter
277  def configuration_sets(self, configuration_sets):
278  validate_attribute(configuration_sets, 'component.ConfigurationSets',
279  expected_type=list, required=False)
280  self._config_sets = configuration_sets
281 
282  @property
284  '''The execution contexts owned by this component.
285 
286  May be an empty list if this component does not own any contexts.
287  Members are of type @ref ExecutionContext.
288 
289  '''
290  return self._exec_contexts
291 
292  @execution_contexts.setter
293  def execution_contexts(self, execution_contexts):
294  validate_attribute(execution_contexts, 'component.ExecutionContexts',
295  expected_type=list, required=False)
296  self._exec_contexts = execution_contexts
297 
298  @property
299  def participants(self):
300  '''The list of participating components, if this component is a
301  composite component.
302 
303  Members are of type @ref Participant.
304 
305  '''
306  return self._participants
307 
308  @participants.setter
309  def participants(self, participants):
310  validate_attribute(participants, 'component.Participants',
311  expected_type=list, required=False)
312  self._participants = participants
313 
314  @property
315  def comment(self):
316  '''Comment about the component.
317 
318  A brief comment about the component. May or may not be displayed in
319  other tools. May be empty.
320 
321  Part of the extended profile.
322 
323  '''
324  return self._comment
325 
326  @comment.setter
327  def comment(self, comment):
328  validate_attribute(comment, 'component.ext.comment',
329  expected_type=[str, unicode], required=False)
330  self._comment = comment
331 
332  @property
333  def visible(self):
334  '''Display the component in graphical tools.
335 
336  This value controls whether graphical tools will display this component
337  or not.
338 
339  Part of the extended profile.
340 
341  '''
342  return self._visible
343 
344  @visible.setter
345  def visible(self, visible):
346  validate_attribute(visible, 'component.ext.visible',
347  expected_type=bool, required=False)
348  self._visible = visible
349 
350  @property
351  def location(self):
352  '''Specifies the position of the component in graphical tools.
353 
354  Part of the extended profile.
355 
356  '''
357  return self._location
358 
359  @location.setter
360  def location(self, location):
361  validate_attribute(location, 'component.ext.Location',
362  expected_type=Location, required=True)
363  self._location = location
364 
365  @property
366  def properties(self):
367  '''Miscellaneous properties.
368 
369  Stores key/value pair properties.
370 
371  Part of the extended profile.
372 
373  '''
374  return self._properties
375 
376  @properties.setter
377  def properties(self, properties):
378  validate_attribute(properties, 'component.ext.Properties',
379  expected_type=dict, required=False)
380  self._properties = properties
381 
382  ###########################################################################
383  # API functions
384 
386  '''Finds a configuration set in the component by its ID.
387 
388  @param id The ID of the configuration set to search for.
389  @return The ConfigurationSet object for the set, or None if it was not
390  found.
391 
392  '''
393  for cs in self.configuration_sets:
394  if cs.id == id:
395  return cs
396  return None
397 
398  ###########################################################################
399  # XML
400 
401  def parse_xml_node(self, node):
402  '''Parse an xml.dom Node object representing a component into this
403  object.
404 
405  '''
406  self._reset()
407  # Get the attributes
408  self.id = node.getAttributeNS(RTS_NS, 'id')
409  self.path_uri = node.getAttributeNS(RTS_NS, 'pathUri')
410  if node.hasAttributeNS(RTS_NS, 'activeConfigurationSet'):
411  self.active_configuration_set = node.getAttributeNS(RTS_NS,
412  'activeConfigurationSet')
413  else:
414  self.active_configuration_set = ''
415  self.instance_name = node.getAttributeNS(RTS_NS, 'instanceName')
416  self.compositeType = comp_type.from_string(node.getAttributeNS(RTS_NS,
417  'compositeType'))
418  required = node.getAttributeNS(RTS_NS, 'isRequired')
419  if required == 'true' or required == '1':
420  self.is_required = True
421  else:
422  self.is_required = False
423  self.comment = node.getAttributeNS(RTS_EXT_NS, 'comment')
424  if node.hasAttributeNS(RTS_EXT_NS, 'visible'):
425  visible = node.getAttributeNS(RTS_EXT_NS, 'visible')
426  if visible.lower() == 'true' or visible == '1':
427  self.visible = True
428  else:
429  self.visible = False
430 
431  # Get the children
432  for c in node.getElementsByTagNameNS(RTS_NS, 'DataPorts'):
433  self._data_ports.append(DataPort().parse_xml_node(c))
434  for c in node.getElementsByTagNameNS(RTS_NS, 'ServicePorts'):
435  self._service_ports.append(ServicePort().parse_xml_node(c))
436  for c in node.getElementsByTagNameNS(RTS_NS, 'ConfigurationSets'):
437  self._config_sets.append(ConfigurationSet().parse_xml_node(c))
438  for c in node.getElementsByTagNameNS(RTS_NS, 'ExecutionContexts'):
439  self._exec_contexts.append(ExecutionContext().parse_xml_node(c))
440  for c in node.getElementsByTagNameNS(RTS_NS, 'Participants'):
441  self._participants.append(Participant().parse_xml_node(c))
442  # Extended profile children
443  c = node.getElementsByTagNameNS(RTS_EXT_NS, 'Location')
444  if c.length > 0:
445  if c.length > 1:
446  raise InvalidRtsProfileNodeError('Location')
447  self._location = Location().parse_xml_node(c[0])
448  for c in get_direct_child_elements_xml(node, prefix=RTS_EXT_NS,
449  local_name='Properties'):
450  name, value = parse_properties_xml(c)
451  self._properties[name] = value
452 
453  return self
454 
455  def save_xml(self, doc, element):
456  '''Save this component into an xml.dom.Element object.'''
457  element.setAttributeNS(RTS_NS, RTS_NS_S + 'id', self.id)
458  element.setAttributeNS(RTS_NS, RTS_NS_S + 'pathUri', self.path_uri)
459  if self.active_configuration_set:
460  element.setAttributeNS(RTS_NS, RTS_NS_S + 'activeConfigurationSet',
462  element.setAttributeNS(RTS_NS, RTS_NS_S + 'instanceName',
463  self.instance_name)
464  element.setAttributeNS(RTS_NS, RTS_NS_S + 'compositeType',
465  comp_type.to_string(self.composite_type))
466  element.setAttributeNS(RTS_NS, RTS_NS_S + 'isRequired',
467  str(self.is_required).lower())
468  if self.comment:
469  element.setAttributeNS(RTS_EXT_NS, RTS_EXT_NS_S + 'comment',
470  self.comment)
471  element.setAttributeNS(RTS_EXT_NS, RTS_EXT_NS_S + 'visible',
472  str(self.visible).lower())
473  for port in self.data_ports:
474  new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'DataPorts')
475  port.save_xml(doc, new_element)
476  element.appendChild(new_element)
477  for port in self.service_ports:
478  new_element = doc.createElementNS(RTS_NS,
479  RTS_NS_S + 'ServicePorts')
480  port.save_xml(doc, new_element)
481  element.appendChild(new_element)
482  for cs in self.configuration_sets:
483  new_element = doc.createElementNS(RTS_NS,
484  RTS_NS_S + 'ConfigurationSets')
485  cs.save_xml(doc, new_element)
486  element.appendChild(new_element)
487  for ec in self.execution_contexts:
488  new_element = doc.createElementNS(RTS_NS,
489  RTS_NS_S + 'ExecutionContexts')
490  ec.save_xml(doc, new_element)
491  element.appendChild(new_element)
492  for p in self.participants:
493  new_element = doc.createElementNS(RTS_NS,
494  RTS_NS_S + 'Participants')
495  p.save_xml(doc, new_element)
496  element.appendChild(new_element)
497  new_element = doc.createElementNS(RTS_EXT_NS,
498  RTS_EXT_NS_S + 'Location')
499  self._location.save_xml(doc, new_element)
500  element.appendChild(new_element)
501  for p in self.properties:
502  new_prop_element = doc.createElementNS(RTS_EXT_NS,
503  RTS_EXT_NS_S + 'Properties')
504  properties_to_xml(new_prop_element, p, self.properties[p])
505  element.appendChild(new_prop_element)
506 
507  ###########################################################################
508  # YAML
509 
510  def parse_yaml(self, y):
511  '''Parse a YAML specification of a component into this object.'''
512  self._reset()
513  self.id = y['id']
514  self.path_uri = y['pathUri']
515  if 'activeConfigurationSet' in y:
516  self.active_configuration_set = y['activeConfigurationSet']
517  else:
518  self.active_configuration_set = ''
519  self.instance_name = y['instanceName']
520  self.compositeType = comp_type.from_string(y['compositeType'])
521  required = y['isRequired']
522  if required == 'true' or required == '1':
523  self.is_required = True
524  else:
525  self.is_required = False
526  if RTS_EXT_NS_YAML + 'comment' in y:
527  self.comment = y[RTS_EXT_NS_YAML + 'comment']
528  self.visible = False
529  if RTS_EXT_NS_YAML + 'visible' in y:
530  visible = y.get(RTS_EXT_NS_YAML + 'visible')
531  if visible == True or visible == 'true' or visible == 'True':
532  self.visible = True
533 
534  # Get the children
535  if 'dataPorts' in y:
536  for p in y.get('dataPorts'):
537  self._data_ports.append(DataPort().parse_yaml(p))
538  if 'servicePorts' in y:
539  for p in y.get('servicePorts'):
540  self._service_ports.append(ServicePort().parse_yaml(p))
541  if 'configurationSets' in y:
542  for p in y.get('configurationSets'):
543  self._config_sets.append(ConfigurationSet().parse_yaml(p))
544  if 'executionContexts' in y:
545  for p in y.get('executionContexts'):
546  self._exec_contexts.append(ExecutionContext().parse_yaml(p))
547  if 'participants' in y:
548  for p in y.get('participants'):
549  self._participants.append(Participant().parse_yaml(p))
550 
551  # Extended profile children
552  if RTS_EXT_NS_YAML + 'location' in y:
553  l = y[RTS_EXT_NS_YAML + 'location']
554  self._location = Location().parse_yaml(l)
555  if RTS_EXT_NS_YAML + 'properties' in y:
556  for p in y.get(RTS_EXT_NS_YAML + 'properties'):
557  if 'value' in p:
558  value = p['value']
559  else:
560  value = None
561  self._properties[p['name']] = value
562 
563  return self
564 
565  def to_dict(self):
566  d = {'id': self.id,
567  'pathUri': self.path_uri,
568  'instanceName': self.instance_name,
569  'compositeType': comp_type.to_string(self.composite_type),
570  'isRequired': str(self.is_required).lower(),
571  RTS_EXT_NS_YAML + 'visible': str(self.visible).lower()}
572  if self.active_configuration_set:
573  d['activeConfigurationSet'] = self.active_configuration_set
574  if self.comment:
575  d[RTS_EXT_NS_YAML + 'comment'] = self.comment
576 
577  ports = []
578  for p in self.data_ports:
579  ports.append(p.to_dict())
580  if ports:
581  d['dataPorts'] = ports
582  ports = []
583  for p in self.service_ports:
584  ports.append(p.to_dict())
585  if ports:
586  d['servicePorts'] = ports
587  sets = []
588  for cs in self.configuration_sets:
589  sets.append(cs.to_dict())
590  if sets:
591  d['configurationSets'] = sets
592  ecs = []
593  for ec in self.execution_contexts:
594  ecs.append(ec.to_dict())
595  if ecs:
596  d['executionContexts'] = ecs
597  participants = []
598  for p in self.participants:
599  participants.append(p.to_dict())
600  if participants:
601  d['participants'] = participants
602 
603  d[RTS_EXT_NS_YAML + 'location'] = self._location.to_dict()
604  props = []
605  for name in self.properties:
606  p = {'name': name}
607  if self.properties[name]:
608  p['value'] = str(self.properties[name])
609  props.append(p)
610  if props:
611  d[RTS_EXT_NS_YAML + 'properties'] = props
612 
613  return d
614 
615  ###########################################################################
616  # Internal functions
617 
618  def _reset(self):
619  # Clears all values in the class in preparation for parsing an XML
620  # file.
621  # Attributes
622  self._id = ''
623  self._path_uri = ''
624  self._active_config_set = ''
625  self._instance_name = ''
626  self._composite_type = comp_type.NONE
627  self._is_required = False
628  # Children
629  self._data_ports = []
630  self._service_ports = []
631  self._config_sets = []
632  self._exec_contexts = []
633  self._participants = []
634  # Extended spec
635  self._comment = ''
636  self._visible = True
637  self._location = Location()
638  self._properties = {}
639 
640 
641 # vim: tw=79
642 
def parse_xml_node(self, node)
XML.
Definition: component.py:401
Component object.
Definition: component.py:42
ConfigurationSet object.
Definition: config_set.py:34
def _reset(self)
Internal functions.
Definition: component.py:618
def save_xml(self, doc, element)
Definition: component.py:455
def properties_to_xml(element, name, value=None)
Definition: utils.py:86
def parse_properties_xml(node)
Definition: utils.py:77
DataPort object.
Definition: ports.py:35
def validate_attribute(attr, name, expected_type=None, required=False)
Definition: utils.py:92
def get_direct_child_elements_xml(node, prefix=None, local_name=None)
Definition: utils.py:50
ServicePort object.
Definition: ports.py:215
def __init__(self, id='', path_uri='', active_configuration_set='', instance_name='', composite_type=comp_type.NONE, is_required=False, comment='', visible=True, location=Location())
Definition: component.py:48
def parse_yaml(self, y)
YAML.
Definition: component.py:510
def indent_string(string, num_spaces=2)
Definition: utils.py:65
def get_configuration_set_by_id(self, id)
API functions.
Definition: component.py:385
Location object.
Definition: location.py:34


rtsprofile
Author(s): Geoffrey Biggs
autogenerated on Fri Jun 7 2019 21:52:35