class Syskit::Models::BoundDataService
Representation of a data service as provided by a component model
Instances of this class are usually created by {Models::Component#provides}. Note that bound dynamic services are instances of {BoundDynamicDataService} instead.
At the component instance level, each {Models::BoundDataService} is represented by a corresponding {Syskit::BoundDataService}, whose {Syskit::BoundDataService#model} method returns this object. This instance-level object is created with {#bind}
Bound data services are promoted from one component model to its submodels, which means that when one does
bound_m = task_m.test_srv sub_m = task_m.mew_submodel sub_bound_m = bound_m.test_srv
Then sub_bound_m != bound_m as sub_bound_m is bound to sub_m and bound_m is bound to task_m. Use {#same_service?} to check whether two services are different promoted version of the same original service
Constants
- DRoby
Attributes
The task model which provides this service
The original service from which self has been promoted
See {BoundDataService} for more details on promotion
The service's full name, i.e. the name with which it is referred to in the task model
The master service (if there is one)
The service model
The service name
The mappings needed between the ports in the service interface and the actual ports on the component
Public Class Methods
# File lib/syskit/models/bound_data_service.rb, line 74 def initialize(name, component_model, master, model, port_mappings) @name, @component_model, @master, @model, @port_mappings = name, component_model, master, model, port_mappings @full_name = if master "#{master.name}.#{name}" else name end @demoted = self end
Public Instance Methods
# File lib/syskit/models/bound_data_service.rb, line 63 def ==(other) eql?(other) end
Returns a view of this service as a provider of service_model
It allows to transparently apply port mappings as if self was
a service of type service_model
The original state of self (before as was called) can be retrieved by calling {as_real_model} on the returned value
@return [BoundDataService]
# File lib/syskit/models/bound_data_service.rb, line 184 def as(service_model) result = dup result.instance_variable_set(:@model, service_model) mappings = port_mappings.dup mappings.delete_if do |srv, _| !service_model.fullfills?(srv) end result.instance_variable_set(:@port_mappings, mappings) result.ports.clear result end
Returns the actual bound data service when the receiver is the return value of {as}
@return [BoundDataService]
# File lib/syskit/models/bound_data_service.rb, line 201 def as_real_model component_model.find_data_service(full_name) end
Returns the bound data service object that represents self being attached to a new component model
# File lib/syskit/models/bound_data_service.rb, line 134 def attach(new_component_model, verify: true) if new_component_model == self return self elsif verify && !new_component_model.fullfills?(component_model) raise ArgumentError, "cannot attach #{self} on #{new_component_model}: does not fullfill #{component_model}" end # NOTE: do NOT use #find_data_service here ! find_data_service # NOTE: might require some promotion from parent models, which # NOTE: is done using #attach ! result = dup result.instance_variable_set :@component_model, new_component_model result end
Returns the BoundDataService object that binds this provided service to an actual task
@param [Component,Syskit::BoundDataService] task the component
that we should bind to. It can itself be a data service
@return [Syskit::BoundDataService]
# File lib/syskit/models/bound_data_service.rb, line 285 def bind(task) if task.model == self # !!! task is a BoundDataService return task elsif task.model <= component_model # This is stronger than #fullfills? Syskit::BoundDataService.new(task, self) elsif task.fullfills?(component_model) # Fullfills, but does not inherit ? component_model may be # a data service proxies if component_model.placeholder_task? base_model = component_model.superclass if base_model_srv = base_model.find_data_service(name) # The data service is from a concrete task model Syskit::BoundDataService.new(task, base_model_srv) else task.find_data_service_from_type(model) end # Or maybe we're dealing with dynamic service instanciation else resolved = task.find_data_service(name) if resolved && resolved.model.same_service?(self) return resolved else raise InternalError, "#{component_model} is fullfilled by #{task}, but is not inherited by its model #{task.model}. I didn't manage to resolve this, either as a task-to-placeholder mapping, or as a dynamic service" end end else raise ArgumentError, "cannot bind #{self} on #{task}: does not fullfill #{component_model}" end end
# File lib/syskit/models/bound_data_service.rb, line 149 def connect_to(other, policy = Hash.new) Syskit.connect(self, other, policy) end
# File lib/syskit/models/bound_data_service.rb, line 54 def dependency_injection_names; Array.new end
# File lib/syskit/models/bound_data_service.rb, line 418 def droby_dump(peer) DRoby.new(name, peer.dump(component_model), peer.dump(master), peer.dump(model)) end
True if this is a dynamic service
# File lib/syskit/models/bound_data_service.rb, line 50 def dynamic?; false end
# File lib/syskit/models/bound_data_service.rb, line 261 def each_data_service(&block) self end
# File lib/syskit/models/bound_data_service.rb, line 270 def each_fullfilled_model(&block) model.each_fullfilled_model(&block) end
# File lib/syskit/models/bound_data_service.rb, line 125 def each_input_port return enum_for(:each_input_port) if !block_given? orogen_model.each_input_port do |p| yield(find_input_port(p.name)) end end
# File lib/syskit/models/bound_data_service.rb, line 118 def each_output_port return enum_for(:each_output_port) if !block_given? orogen_model.each_output_port do |p| yield(find_output_port(p.name)) end end
# File lib/syskit/models/bound_data_service.rb, line 342 def each_required_model return enum_for(:each_required_model) if !block_given? yield(model) end
Enumerates the data services that are slave of this one
# File lib/syskit/models/bound_data_service.rb, line 266 def each_slave_data_service(&block) component_model.each_slave_data_service(self, &block) end
# File lib/syskit/models/bound_data_service.rb, line 56 def eql?(other) other.kind_of?(self.class) && other.full_name == full_name && other.model == model && other.component_model == component_model end
# File lib/syskit/models/bound_data_service.rb, line 356 def find_data_service(name) component_model.each_slave_data_service(self) do |slave_m| if slave_m.name == name return slave_m end end nil end
# File lib/syskit/models/bound_data_service.rb, line 111 def find_input_port(name) name = name.to_str if (mapped = port_mappings_for_task[name]) && (port = component_model.find_input_port(mapped)) ports[name] ||= InputPort.new(self, port.orogen_model, name) end end
# File lib/syskit/models/bound_data_service.rb, line 104 def find_output_port(name) name = name.to_str if (mapped = port_mappings_for_task[name]) && (port = component_model.find_output_port(mapped)) ports[name] ||= OutputPort.new(self, port.orogen_model, name) end end
Returns the service port that maps to a task port
@return [nil,Port]
# File lib/syskit/models/bound_data_service.rb, line 225 def find_port_for_task_port(task_port) task_port_name = task_port.name port_mappings_for_task.each do |service_port_name, port_name| if port_name == task_port_name return find_port(service_port_name) end end nil end
# File lib/syskit/models/bound_data_service.rb, line 369 def find_through_method_missing(m, args) MetaRuby::DSLs.find_through_method_missing( self, m, args, '_srv'.freeze => :find_data_service) || super end
# File lib/syskit/models/bound_data_service.rb, line 205 def fullfilled_model [model] end
Returns true if self provides all models in models
# File lib/syskit/models/bound_data_service.rb, line 210 def fullfills?(models) if !models.respond_to?(:each) models = [models] end models.each do |required_m| required_m.each_fullfilled_model do |m| return false if !self.model.fullfills?(m) end end true end
# File lib/syskit/models/bound_data_service.rb, line 349 def has_data_service?(name) component_model.each_slave_data_service(self) do |slave_m| return true if slave_m.name == name end false end
# File lib/syskit/models/bound_data_service.rb, line 365 def has_through_method_missing?(m) MetaRuby::DSLs.has_through_method_missing?( self, m, '_srv'.freeze => :has_data_service?) || super end
# File lib/syskit/models/bound_data_service.rb, line 67 def hash; [self.class, full_name, component_model].hash end
# File lib/syskit/models/bound_data_service.rb, line 88 def initialize_copy(original) super @ports = Hash.new end
# File lib/syskit/models/bound_data_service.rb, line 161 def inspect; to_s end
Creates, in the given plan, a new task matching this service in the given context, and returns the instanciated data service
@return [Syskit::BoundDataService]
# File lib/syskit/models/bound_data_service.rb, line 320 def instanciate(plan, context = DependencyInjectionContext.new, options = Hash.new) bind(component_model.instanciate(plan, context, options)) end
True if this service is not a slave service
# File lib/syskit/models/bound_data_service.rb, line 47 def master?; !@master end
# File lib/syskit/models/bound_data_service.rb, line 274 def merge(other_model) m = other_model.merge(component_model) attach(m) end
- Orocos::Spec::TaskContext
-
the oroGen model for this service's
interface
# File lib/syskit/models/bound_data_service.rb, line 100 def orogen_model model.orogen_model end
Returns the port mappings that should be applied from one of the service models provided by {#model} to {#component_model}
@param [Model<DataService>] service_model the model of a service
provided by {#model}
@return [Hash<String,String>] mapping from the name of a port of
service_model to the name of a port on {#component_model}
# File lib/syskit/models/bound_data_service.rb, line 254 def port_mappings_for(service_model) if !(result = port_mappings[service_model]) raise ArgumentError, "#{service_model} is not provided by #{model.short_name}" end result end
Returns the port mappings that should be applied to convert a port from this service to {#component_model}
@return [Hash<String,String>] mapping from the name of a port of
self to the name of a port on {#component_model}
@see #port_mappings_for
# File lib/syskit/models/bound_data_service.rb, line 242 def port_mappings_for_task port_mappings_for(model) end
# File lib/syskit/models/bound_data_service.rb, line 167 def pretty_print(pp) pp.text "service #{name}(#{model.name}) of" pp.nest(2) do pp.breakable component_model.pretty_print(pp) end end
Returns the BoundDataService object that binds this provided service to an actual task
@return [Syskit::BoundDataService]
# File lib/syskit/models/bound_data_service.rb, line 328 def resolve(task) bind(component_model.resolve(task)) end
Whether two services are the same service bound to two different interfaces
When subclassing, the services are promoted to the new component interface that is being accessed, so in effect when one does
bound_m = task_m.test_srv sub_m = task_m.mew_submodel sub_bound_m = bound_m.test_srv
Then sub_bound_m != bound_m as sub_bound_m is bound to sub_m and bound_m is bound to task_m. This is important, as we sometimes want to compare services including which interface they're bound to.
However, in some cases, we want to know whether two services are actually issues from the same service definition, i.e. have been promoted from the same service. This method performs that comparison
@param [BoundDataService] other @return [Boolean]
# File lib/syskit/models/bound_data_service.rb, line 394 def same_service?(other) other.demoted == self.demoted end
The selection object that represents self being selected for requirements
@param [#to_instance_requirements] requirements the requirements
for which self is being selected
@return [InstanceSelection]
# File lib/syskit/models/bound_data_service.rb, line 404 def selected_for(requirements) InstanceSelection.new(nil, self.to_instance_requirements, requirements.to_instance_requirements) end
(see Syskit::Models::Component#self_port_to_component_port)
# File lib/syskit/models/bound_data_service.rb, line 94 def self_port_to_component_port(port) return component_model.find_port(port_mappings_for_task[port.name]) end
# File lib/syskit/models/bound_data_service.rb, line 163 def short_name "#{component_model.short_name}:#{full_name}" end
# File lib/syskit/models/bound_data_service.rb, line 52 def to_component_model; component_model.to_component_model end
Generates the InstanceRequirements object that
represents self best
@return [Syskit::InstanceRequirements]
# File lib/syskit/models/bound_data_service.rb, line 336 def to_instance_requirements req = component_model.to_instance_requirements req.select_service(self) req end
# File lib/syskit/models/bound_data_service.rb, line 157 def to_s "#{component_model.short_name}.#{full_name}" end