component.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: component.py
00017 
00018 Object representing a component in an RT system.
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 import composite_type as comp_type
00029 from rtsprofile.config_set import ConfigurationSet
00030 from rtsprofile.exceptions import InvalidCompositeTypeError
00031 from rtsprofile.exec_context import ExecutionContext
00032 from rtsprofile.location import Location
00033 from rtsprofile.ports import DataPort, ServicePort
00034 from rtsprofile.utils import get_direct_child_elements_xml, \
00035                              indent_string, parse_properties_xml, \
00036                              properties_to_xml, validate_attribute
00037 
00038 
00039 ##############################################################################
00040 ## Component object
00041 
00042 class Component(object):
00043     '''Information about a component contained in an RT system.'''
00044 
00045     def __init__(self, id='', path_uri='', active_configuration_set='',
00046                  instance_name='', composite_type=comp_type.NONE,
00047                  is_required=False, comment='', visible=True,
00048                  location=Location()):
00049         '''@param id Component ID.
00050         @type id str
00051         @param path_uri Path to the component.
00052         @type path_uri str
00053         @param active_configuration_set Name of the active configuration set.
00054         @type active_configuration_set str
00055         @param instance_name Component's instance name.
00056         @type instance_name str
00057         @param composite_type Type of composition the component is in.
00058         @type composite_type CompositeType
00059         @param is_required If the component is optional in the system.
00060         @type is_required bool
00061         @param comment A comment about the component.
00062         @type comment str
00063         @param visible If this component is visible in graphical displays.
00064         @type visible bool
00065         @param location The location of this component in graphical displays.
00066         @type location Location
00067 
00068         '''
00069         self._reset()
00070         validate_attribute(id, 'component.id',
00071                            expected_type=[str, unicode], required=False)
00072         self._id = id
00073         validate_attribute(path_uri, 'component.pathUri',
00074                            expected_type=[str, unicode], required=False)
00075         self._path_uri = path_uri
00076         validate_attribute(active_configuration_set,
00077                            'component.activeConfigurationSet',
00078                            expected_type=[str, unicode], required=False)
00079         self._active_config_set = active_configuration_set
00080         validate_attribute(instance_name, 'component.instanceName',
00081                            expected_type=[str, unicode], required=False)
00082         self._instance_name = instance_name
00083         validate_attribute(composite_type, 'component.compositeType',
00084                            expected_type=comp_type.const_type, required=False)
00085         self._composite_type = composite_type
00086         validate_attribute(is_required, 'component.isRequired',
00087                            expected_type=bool)
00088         self._is_required = is_required
00089         validate_attribute(comment, 'component.ext.comment',
00090                            expected_type=[str, unicode], required=False)
00091         self._comment = comment
00092         validate_attribute(visible, 'component.ext.visible',
00093                            expected_type=bool, required=False)
00094         self._visible = visible
00095         validate_attribute(location, 'component.ext.Location',
00096                            expected_type=Location, required=True)
00097         self._location = location
00098 
00099     def __str__(self):
00100         result = 'Instance name: {3}\n  ID: {0}\n  Path URI: {1}\n  Active \
00101 configuration set: {2}\n  Composite type: {4}\n  Is required: {5}\n'.format(\
00102                 self.id, self.path_uri, self.active_configuration_set,
00103                 self.instance_name, comp_type.to_string(self.composite_type),
00104                 self.is_required)
00105         if self.comment:
00106             result += '  Comment: {0}\n'.format(self.comment)
00107         result += '  Visible: {0}\n'.format(self.visible)
00108         if self.data_ports:
00109             result += '  Data ports:\n'
00110             for p in self.data_ports:
00111                 result += '{0}\n'.format(indent_string(str(p), num_spaces=4))
00112         if self.service_ports:
00113             result += '  Service ports:\n'
00114             for p in self.service_ports:
00115                 result += '{0}\n'.format(indent_string(str(p), num_spaces=4))
00116         if self.configuration_sets:
00117             result += '  Configuration sets:\n'
00118             for c in self.configuration_sets:
00119                 result += '{0}\n'.format(indent_string(str(c), num_spaces=4))
00120         if self.execution_contexts:
00121             result += '  Execution contexts:\n'
00122             for e in self.execution_contexts:
00123                 result += '{0}\n'.format(indent_string(str(e), num_spaces=4))
00124         if self.participants:
00125             result += '  Participants:\n'
00126             for p in self.participants:
00127                 result += '{0}\n'.format(indent_string(str(p)))
00128         result += '  Location:\n{0}\n'.format(indent_string(str(self.location),
00129                                                            num_spaces=4))
00130         if self.properties:
00131             result += '  Properties:\n'
00132             for p in self.properties:
00133                 result += '    {0}: {1}\n'.format(p, self.properties[p])
00134         return result[:-1] # Lop off the last new line
00135 
00136     ###########################################################################
00137     # Properties
00138 
00139     @property
00140     def id(self):
00141         '''ID of this component in the RT system.
00142 
00143         In case of the same RT Component specification being used to create
00144         multiple RT Components within a single RT system, this ID is prepended
00145         to the instance name attribute to distinguish individual components.
00146 
00147         '''
00148         return self._id
00149 
00150     @id.setter
00151     def id(self, id):
00152         validate_attribute(id, 'component.id',
00153                            expected_type=[str, unicode], required=True)
00154         self._id = id
00155 
00156     @property
00157     def path_uri(self):
00158         '''Path to where this component is registered in URI format.'''
00159         return self._path_uri
00160 
00161     @path_uri.setter
00162     def path_uri(self, path_uri):
00163         validate_attribute(path_uri, 'component.pathUri',
00164                            expected_type=[str, unicode], required=True)
00165         self._path_uri = path_uri
00166 
00167     @property
00168     def active_configuration_set(self):
00169         '''The ID of the active configuration set of the component.
00170 
00171         If no configuration set is active, this may be empty.
00172 
00173         '''
00174         return self._active_config_set
00175 
00176     @active_configuration_set.setter
00177     def active_configuration_set(self, active_config_set):
00178         validate_attribute(active_config_set,
00179                            'component.activeConfigurationSet',
00180                            expected_type=[str, unicode], required=False)
00181         self._active_config_set = active_config_set
00182 
00183     @property
00184     def instance_name(self):
00185         '''Instance name of the component in the RT system.
00186 
00187         In case of the same RT Component specification being used to create
00188         multiple RT Components within a single RT system, this instance name is
00189         appended to the ID attribute to distinguish individual components.
00190 
00191         '''
00192         return self._instance_name
00193 
00194     @instance_name.setter
00195     def instance_name(self, instance_name):
00196         validate_attribute(instance_name, 'component.instanceName',
00197                            expected_type=[str, unicode], required=True)
00198         self._instance_name = instance_name
00199 
00200     @property
00201     def composite_type(self):
00202         '''The type of composite component this component is involved in.
00203 
00204         If this component is involved in a composite component, this attribute
00205         specifies the type of composition. See @ref CompositeType for valid
00206         values.
00207 
00208         '''
00209         return self._composite_type
00210 
00211     @composite_type.setter
00212     def composite_type(self, composite_type):
00213         validate_attribute(composite_type, 'component.compositeType',
00214                            expected_type=comp_type.const_type, required=True)
00215         self._composite_type = composite_type
00216 
00217     @property
00218     def is_required(self):
00219         '''Specifies if this component is optional in the RT system.
00220 
00221         Sometimes a component does not need to be present for an RT system to
00222         function. If this component must be present for the RT system to
00223         function, this attribute will be True.
00224 
00225         '''
00226         return self._is_required
00227 
00228     @is_required.setter
00229     def is_required(self, is_required):
00230         validate_attribute(is_required, 'component.isRequired',
00231                            expected_type=bool)
00232         self._is_required = is_required
00233 
00234     @property
00235     def data_ports(self):
00236         '''Data ports owned by this component.
00237 
00238         May be an empty list if this component has no data ports. Members are
00239         of type @ref DataPort.
00240 
00241         '''
00242         return self._data_ports
00243 
00244     @data_ports.setter
00245     def data_ports(self, data_ports):
00246         validate_attribute(data_ports, 'component.DataPorts',
00247                            expected_type=list, required=False)
00248         self._data_ports = data_ports
00249 
00250     @property
00251     def service_ports(self):
00252         '''Service ports owned by this component.
00253 
00254         May be an empty list if this component has no service ports. Members
00255         are of type @ref ServicePort.
00256 
00257         '''
00258         return self._service_ports
00259 
00260     @service_ports.setter
00261     def service_ports(self, service_ports):
00262         validate_attribute(service_ports, 'component.ServicePorts',
00263                            expected_type=list, required=False)
00264         self._service_ports = service_ports
00265 
00266     @property
00267     def configuration_sets(self):
00268         '''The configuration sets in this component.
00269 
00270         May be an empty list if this component has no configuration sets.
00271         Members are of type @ref ConfigurationSet.
00272 
00273         '''
00274         return self._config_sets
00275 
00276     @configuration_sets.setter
00277     def configuration_sets(self, configuration_sets):
00278         validate_attribute(configuration_sets, 'component.ConfigurationSets',
00279                            expected_type=list, required=False)
00280         self._config_sets = configuration_sets
00281 
00282     @property
00283     def execution_contexts(self):
00284         '''The execution contexts owned by this component.
00285 
00286         May be an empty list if this component does not own any contexts.
00287         Members are of type @ref ExecutionContext.
00288 
00289         '''
00290         return self._exec_contexts
00291 
00292     @execution_contexts.setter
00293     def execution_contexts(self, execution_contexts):
00294         validate_attribute(execution_contexts, 'component.ExecutionContexts',
00295                            expected_type=list, required=False)
00296         self._exec_contexts = execution_contexts
00297 
00298     @property
00299     def participants(self):
00300         '''The list of participating components, if this component is a
00301         composite component.
00302 
00303         Members are of type @ref Participant.
00304 
00305         '''
00306         return self._participants
00307 
00308     @participants.setter
00309     def participants(self, participants):
00310         validate_attribute(participants, 'component.Participants',
00311                            expected_type=list, required=False)
00312         self._participants = participants
00313 
00314     @property
00315     def comment(self):
00316         '''Comment about the component.
00317 
00318         A brief comment about the component. May or may not be displayed in
00319         other tools. May be empty.
00320 
00321         Part of the extended profile.
00322 
00323         '''
00324         return self._comment
00325 
00326     @comment.setter
00327     def comment(self, comment):
00328         validate_attribute(comment, 'component.ext.comment',
00329                            expected_type=[str, unicode], required=False)
00330         self._comment = comment
00331 
00332     @property
00333     def visible(self):
00334         '''Display the component in graphical tools.
00335 
00336         This value controls whether graphical tools will display this component
00337         or not.
00338 
00339         Part of the extended profile.
00340 
00341         '''
00342         return self._visible
00343 
00344     @visible.setter
00345     def visible(self, visible):
00346         validate_attribute(visible, 'component.ext.visible',
00347                            expected_type=bool, required=False)
00348         self._visible = visible
00349 
00350     @property
00351     def location(self):
00352         '''Specifies the position of the component in graphical tools.
00353 
00354         Part of the extended profile.
00355 
00356         '''
00357         return self._location
00358 
00359     @location.setter
00360     def location(self, location):
00361         validate_attribute(location, 'component.ext.Location',
00362                            expected_type=Location, required=True)
00363         self._location = location
00364 
00365     @property
00366     def properties(self):
00367         '''Miscellaneous properties.
00368 
00369         Stores key/value pair properties.
00370 
00371         Part of the extended profile.
00372 
00373         '''
00374         return self._properties
00375 
00376     @properties.setter
00377     def properties(self, properties):
00378         validate_attribute(properties, 'component.ext.Properties',
00379                            expected_type=dict, required=False)
00380         self._properties = properties
00381 
00382     ###########################################################################
00383     # API functions
00384 
00385     def get_configuration_set_by_id(self, id):
00386         '''Finds a configuration set in the component by its ID.
00387 
00388         @param id The ID of the configuration set to search for.
00389         @return The ConfigurationSet object for the set, or None if it was not
00390         found.
00391 
00392         '''
00393         for cs in self.configuration_sets:
00394             if cs.id == id:
00395                 return cs
00396         return None
00397 
00398     ###########################################################################
00399     # XML
00400 
00401     def parse_xml_node(self, node):
00402         '''Parse an xml.dom Node object representing a component into this
00403         object.
00404 
00405         '''
00406         self._reset()
00407         # Get the attributes
00408         self.id = node.getAttributeNS(RTS_NS, 'id')
00409         self.path_uri = node.getAttributeNS(RTS_NS, 'pathUri')
00410         if node.hasAttributeNS(RTS_NS, 'activeConfigurationSet'):
00411             self.active_configuration_set = node.getAttributeNS(RTS_NS,
00412                     'activeConfigurationSet')
00413         else:
00414             self.active_configuration_set = ''
00415         self.instance_name = node.getAttributeNS(RTS_NS, 'instanceName')
00416         self.compositeType = comp_type.from_string(node.getAttributeNS(RTS_NS,
00417                 'compositeType'))
00418         required = node.getAttributeNS(RTS_NS, 'isRequired')
00419         if required == 'true' or required == '1':
00420             self.is_required = True
00421         else:
00422             self.is_required = False
00423         self.comment = node.getAttributeNS(RTS_EXT_NS, 'comment')
00424         if node.hasAttributeNS(RTS_EXT_NS, 'visible'):
00425             visible = node.getAttributeNS(RTS_EXT_NS, 'visible')
00426             if visible.lower() == 'true' or visible == '1':
00427                 self.visible = True
00428             else:
00429                 self.visible = False
00430 
00431         # Get the children
00432         for c in node.getElementsByTagNameNS(RTS_NS, 'DataPorts'):
00433             self._data_ports.append(DataPort().parse_xml_node(c))
00434         for c in node.getElementsByTagNameNS(RTS_NS, 'ServicePorts'):
00435             self._service_ports.append(ServicePort().parse_xml_node(c))
00436         for c in node.getElementsByTagNameNS(RTS_NS, 'ConfigurationSets'):
00437             self._config_sets.append(ConfigurationSet().parse_xml_node(c))
00438         for c in node.getElementsByTagNameNS(RTS_NS, 'ExecutionContexts'):
00439             self._exec_contexts.append(ExecutionContext().parse_xml_node(c))
00440         for c in node.getElementsByTagNameNS(RTS_NS, 'Participants'):
00441             self._participants.append(Participant().parse_xml_node(c))
00442         # Extended profile children
00443         c = node.getElementsByTagNameNS(RTS_EXT_NS, 'Location')
00444         if c.length > 0:
00445             if c.length > 1:
00446                 raise InvalidRtsProfileNodeError('Location')
00447             self._location = Location().parse_xml_node(c[0])
00448         for c in get_direct_child_elements_xml(node, prefix=RTS_EXT_NS,
00449                                                local_name='Properties'):
00450             name, value = parse_properties_xml(c)
00451             self._properties[name] = value
00452 
00453         return self
00454 
00455     def save_xml(self, doc, element):
00456         '''Save this component into an xml.dom.Element object.'''
00457         element.setAttributeNS(RTS_NS, RTS_NS_S + 'id', self.id)
00458         element.setAttributeNS(RTS_NS, RTS_NS_S + 'pathUri', self.path_uri)
00459         if self.active_configuration_set:
00460             element.setAttributeNS(RTS_NS, RTS_NS_S + 'activeConfigurationSet',
00461                                    self.active_configuration_set)
00462         element.setAttributeNS(RTS_NS, RTS_NS_S + 'instanceName',
00463                                self.instance_name)
00464         element.setAttributeNS(RTS_NS, RTS_NS_S + 'compositeType',
00465                                comp_type.to_string(self.composite_type))
00466         element.setAttributeNS(RTS_NS, RTS_NS_S + 'isRequired',
00467                                str(self.is_required).lower())
00468         if self.comment:
00469             element.setAttributeNS(RTS_EXT_NS, RTS_EXT_NS_S + 'comment',
00470                                    self.comment)
00471         element.setAttributeNS(RTS_EXT_NS, RTS_EXT_NS_S + 'visible',
00472                                str(self.visible).lower())
00473         for port in self.data_ports:
00474             new_element = doc.createElementNS(RTS_NS, RTS_NS_S + 'DataPorts')
00475             port.save_xml(doc, new_element)
00476             element.appendChild(new_element)
00477         for port in self.service_ports:
00478             new_element = doc.createElementNS(RTS_NS,
00479                                               RTS_NS_S + 'ServicePorts')
00480             port.save_xml(doc, new_element)
00481             element.appendChild(new_element)
00482         for cs in self.configuration_sets:
00483             new_element = doc.createElementNS(RTS_NS,
00484                                               RTS_NS_S + 'ConfigurationSets')
00485             cs.save_xml(doc, new_element)
00486             element.appendChild(new_element)
00487         for ec in self.execution_contexts:
00488             new_element = doc.createElementNS(RTS_NS,
00489                                               RTS_NS_S + 'ExecutionContexts')
00490             ec.save_xml(doc, new_element)
00491             element.appendChild(new_element)
00492         for p in self.participants:
00493             new_element = doc.createElementNS(RTS_NS,
00494                                               RTS_NS_S + 'Participants')
00495             p.save_xml(doc, new_element)
00496             element.appendChild(new_element)
00497         new_element = doc.createElementNS(RTS_EXT_NS,
00498                                           RTS_EXT_NS_S + 'Location')
00499         self._location.save_xml(doc, new_element)
00500         element.appendChild(new_element)
00501         for p in self.properties:
00502             new_prop_element = doc.createElementNS(RTS_EXT_NS,
00503                                                    RTS_EXT_NS_S + 'Properties')
00504             properties_to_xml(new_prop_element, p, self.properties[p])
00505             element.appendChild(new_prop_element)
00506 
00507     ###########################################################################
00508     # YAML
00509 
00510     def parse_yaml(self, y):
00511         '''Parse a YAML specification of a component into this object.'''
00512         self._reset()
00513         self.id = y['id']
00514         self.path_uri = y['pathUri']
00515         if 'activeConfigurationSet' in y:
00516             self.active_configuration_set = y['activeConfigurationSet']
00517         else:
00518             self.active_configuration_set = ''
00519         self.instance_name = y['instanceName']
00520         self.compositeType = comp_type.from_string(y['compositeType'])
00521         required = y['isRequired']
00522         if required == 'true' or required == '1':
00523             self.is_required = True
00524         else:
00525             self.is_required = False
00526         if RTS_EXT_NS_YAML + 'comment' in y:
00527             self.comment = y[RTS_EXT_NS_YAML + 'comment']
00528         self.visible = False
00529         if RTS_EXT_NS_YAML + 'visible' in y:
00530             visible = y.get(RTS_EXT_NS_YAML + 'visible')
00531             if visible == True or visible == 'true' or visible == 'True':
00532                 self.visible = True
00533 
00534         # Get the children
00535         if 'dataPorts' in y:
00536             for p in y.get('dataPorts'):
00537                 self._data_ports.append(DataPort().parse_yaml(p))
00538         if 'servicePorts' in y:
00539             for p in y.get('servicePorts'):
00540                 self._service_ports.append(ServicePort().parse_yaml(p))
00541         if 'configurationSets' in y:
00542             for p in y.get('configurationSets'):
00543                 self._config_sets.append(ConfigurationSet().parse_yaml(p))
00544         if 'executionContexts' in y:
00545             for p in y.get('executionContexts'):
00546                 self._exec_contexts.append(ExecutionContext().parse_yaml(p))
00547         if 'participants' in y:
00548             for p in y.get('participants'):
00549                 self._participants.append(Participant().parse_yaml(p))
00550 
00551         # Extended profile children
00552         if RTS_EXT_NS_YAML + 'location' in y:
00553             l = y[RTS_EXT_NS_YAML + 'location']
00554             self._location = Location().parse_yaml(l)
00555         if RTS_EXT_NS_YAML + 'properties' in y:
00556             for p in y.get(RTS_EXT_NS_YAML + 'properties'):
00557                 if 'value' in p:
00558                     value = p['value']
00559                 else:
00560                     value = None
00561                 self._properties[p['name']] = value
00562 
00563         return self
00564 
00565     def to_dict(self):
00566         d = {'id': self.id,
00567                 'pathUri': self.path_uri,
00568                 'instanceName': self.instance_name,
00569                 'compositeType': comp_type.to_string(self.composite_type),
00570                 'isRequired': str(self.is_required).lower(),
00571                 RTS_EXT_NS_YAML + 'visible': str(self.visible).lower()}
00572         if self.active_configuration_set:
00573             d['activeConfigurationSet'] = self.active_configuration_set
00574         if self.comment:
00575             d[RTS_EXT_NS_YAML + 'comment'] = self.comment
00576 
00577         ports = []
00578         for p in self.data_ports:
00579             ports.append(p.to_dict())
00580         if ports:
00581             d['dataPorts'] = ports
00582         ports = []
00583         for p in self.service_ports:
00584             ports.append(p.to_dict())
00585         if ports:
00586             d['servicePorts'] = ports
00587         sets = []
00588         for cs in self.configuration_sets:
00589             sets.append(cs.to_dict())
00590         if sets:
00591             d['configurationSets'] = sets
00592         ecs = []
00593         for ec in self.execution_contexts:
00594             ecs.append(ec.to_dict())
00595         if ecs:
00596             d['executionContexts'] = ecs
00597         participants = []
00598         for p in self.participants:
00599             participants.append(p.to_dict())
00600         if participants:
00601             d['participants'] = participants
00602 
00603         d[RTS_EXT_NS_YAML + 'location'] = self._location.to_dict()
00604         props = []
00605         for name in self.properties:
00606             p = {'name': name}
00607             if self.properties[name]:
00608                 p['value'] = str(self.properties[name])
00609             props.append(p)
00610         if props:
00611             d[RTS_EXT_NS_YAML + 'properties'] = props
00612 
00613         return d
00614 
00615     ###########################################################################
00616     # Internal functions
00617 
00618     def _reset(self):
00619         # Clears all values in the class in preparation for parsing an XML
00620         # file.
00621         # Attributes
00622         self._id = ''
00623         self._path_uri = ''
00624         self._active_config_set = ''
00625         self._instance_name = ''
00626         self._composite_type = comp_type.NONE
00627         self._is_required = False
00628         # Children
00629         self._data_ports = []
00630         self._service_ports = []
00631         self._config_sets = []
00632         self._exec_contexts = []
00633         self._participants = []
00634         # Extended spec
00635         self._comment = ''
00636         self._visible = True
00637         self._location = Location()
00638         self._properties = {}
00639 
00640 
00641 # vim: tw=79
00642 


rtsprofile
Author(s): Geoffrey Biggs
autogenerated on Sun Mar 26 2017 03:39:43