Class: Syskit::Models::BoundDataService
- Extended by:
- InstanceRequirements::Auto
- Includes:
- MetaRuby::DSLs::FindThroughMethodMissing, Base, PortAccess
- Defined in:
- lib/syskit/models/bound_data_service.rb
Overview
Representation of a data service as provided by a component model
Instances of this class are usually created by Component#provides. Note that bound dynamic services are instances of BoundDynamicDataService instead.
At the component instance level, each BoundDataService is represented by a corresponding BoundDataService, whose 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
Direct Known Subclasses
Defined Under Namespace
Classes: DRoby
Constant Summary
Constants included from InstanceRequirements::Auto
InstanceRequirements::Auto::METHODS
Instance Attribute Summary collapse
-
#component_model ⇒ Object
readonly
The task model which provides this service.
-
#demoted ⇒ Object
readonly
The original service from which self has been promoted.
-
#full_name ⇒ Object
readonly
The service's full name, i.e.
-
#master ⇒ Object
readonly
The master service (if there is one).
-
#model ⇒ Object
readonly
The service model.
-
#name ⇒ Object
readonly
The service name.
-
#port_mappings ⇒ Object
readonly
The mappings needed between the ports in the service interface and the actual ports on the component.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#as(service_model) ⇒ BoundDataService
Returns a view of this service as a provider of
service_model
. -
#as_real_model ⇒ BoundDataService
Returns the actual bound data service when the receiver is the return value of #as.
-
#attach(new_component_model, verify: true) ⇒ Object
Returns the bound data service object that represents self being attached to a new component model.
-
#bind(task) ⇒ Syskit::BoundDataService
Returns the BoundDataService object that binds this provided service to an actual task.
- #connect_to(other, policy = Hash.new) ⇒ Object
- #dependency_injection_names ⇒ Object
- #droby_dump(peer) ⇒ Object
-
#dynamic? ⇒ Boolean
True if this is a dynamic service.
- #each_data_service(&block) ⇒ Object
- #each_fullfilled_model(&block) ⇒ Object
- #each_input_port ⇒ Object
- #each_output_port ⇒ Object
- #each_required_model {|model| ... } ⇒ Object
-
#each_slave_data_service(&block) ⇒ Object
Enumerates the data services that are slave of this one.
- #eql?(other) ⇒ Boolean
- #find_data_service(name) ⇒ Object
- #find_input_port(name) ⇒ Object
- #find_output_port(name) ⇒ Object
-
#find_port_for_task_port(task_port) ⇒ nil, Port
Returns the service port that maps to a task port.
- #find_through_method_missing(m, args) ⇒ Object
- #fullfilled_model ⇒ Object
-
#fullfills?(models) ⇒ Boolean
Returns true if self provides all models in models.
- #has_data_service?(name) ⇒ Boolean
- #has_through_method_missing?(m) ⇒ Boolean
- #hash ⇒ Object
-
#initialize(name, component_model, master, model, port_mappings) ⇒ BoundDataService
constructor
A new instance of BoundDataService.
- #initialize_copy(original) ⇒ Object
- #inspect ⇒ Object
-
#instanciate(plan, context = DependencyInjectionContext.new, options = Hash.new) ⇒ Syskit::BoundDataService
Creates, in the given plan, a new task matching this service in the given context, and returns the instanciated data service.
-
#master? ⇒ Boolean
True if this service is not a slave service.
- #merge(other_model) ⇒ Object
-
#orogen_model ⇒ Object
- Orocos::Spec::TaskContext
-
the oroGen model for this service's interface.
-
#port_mappings_for(service_model) ⇒ Hash<String,String>
Returns the port mappings that should be applied from one of the service models provided by #model to #component_model.
-
#port_mappings_for_task ⇒ Hash<String,String>
Returns the port mappings that should be applied to convert a port from this service to #component_model.
- #pretty_print(pp) ⇒ Object
-
#resolve(task) ⇒ Object
deprecated
Deprecated.
use #bind instead
-
#same_service?(other) ⇒ Boolean
Whether two services are the same service bound to two different interfaces.
-
#selected_for(requirements) ⇒ InstanceSelection
The selection object that represents self being selected for requirements.
-
#self_port_to_component_port(port) ⇒ Models::Port
Resolves the given port model into a component model where #component_model is a proper component (e.g. not a BoundDataService).
- #short_name ⇒ Object
- #to_component_model ⇒ Object
-
#to_instance_requirements ⇒ Syskit::InstanceRequirements
Generates the InstanceRequirements object that represents
self
best. - #to_s ⇒ Object
Methods included from PortAccess
#each_port, #find_port, #has_dynamic_input_port?, #has_dynamic_output_port?, #has_input_port?, #has_output_port?, #has_port?, #port_by_name
Constructor Details
#initialize(name, component_model, master, model, port_mappings) ⇒ BoundDataService
Returns a new instance of BoundDataService
74 75 76 77 78 79 80 81 82 83 84 85 86 |
# 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 |
Instance Attribute Details
#component_model ⇒ Object (readonly)
The task model which provides this service
31 32 33 |
# File 'lib/syskit/models/bound_data_service.rb', line 31 def component_model @component_model end |
#demoted ⇒ Object (readonly)
The original service from which self has been promoted
See Syskit::Models::BoundDataService for more details on promotion
72 73 74 |
# File 'lib/syskit/models/bound_data_service.rb', line 72 def demoted @demoted end |
#full_name ⇒ Object (readonly)
The service's full name, i.e. the name with which it is referred to in the task model
44 45 46 |
# File 'lib/syskit/models/bound_data_service.rb', line 44 def full_name @full_name end |
#master ⇒ Object (readonly)
The master service (if there is one)
35 36 37 |
# File 'lib/syskit/models/bound_data_service.rb', line 35 def master @master end |
#model ⇒ Object (readonly)
The service model
37 38 39 |
# File 'lib/syskit/models/bound_data_service.rb', line 37 def model @model end |
#name ⇒ Object (readonly)
The service name
33 34 35 |
# File 'lib/syskit/models/bound_data_service.rb', line 33 def name @name end |
#port_mappings ⇒ Object (readonly)
The mappings needed between the ports in the service interface and the actual ports on the component
40 41 42 |
# File 'lib/syskit/models/bound_data_service.rb', line 40 def port_mappings @port_mappings end |
Instance Method Details
#==(other) ⇒ Object
[View source]
63 64 65 |
# File 'lib/syskit/models/bound_data_service.rb', line 63 def ==(other) eql?(other) end |
#as(service_model) ⇒ BoundDataService
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
184 185 186 187 188 189 190 191 192 193 194 195 |
# 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 |
#as_real_model ⇒ BoundDataService
Returns the actual bound data service when the receiver is the return value of #as
201 202 203 |
# File 'lib/syskit/models/bound_data_service.rb', line 201 def as_real_model component_model.find_data_service(full_name) end |
#attach(new_component_model, verify: true) ⇒ Object
Returns the bound data service object that represents self being attached to a new component model
134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# 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 |
#bind(task) ⇒ Syskit::BoundDataService
Returns the BoundDataService object that binds this provided service to an actual task
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# 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? 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 |
#connect_to(other, policy = Hash.new) ⇒ Object
[View source]
149 150 151 |
# File 'lib/syskit/models/bound_data_service.rb', line 149 def connect_to(other, policy = Hash.new) Syskit.connect(self, other, policy) end |
#dependency_injection_names ⇒ Object
[View source]
54 |
# File 'lib/syskit/models/bound_data_service.rb', line 54 def dependency_injection_names; Array.new end |
#droby_dump(peer) ⇒ Object
[View source]
417 418 419 |
# File 'lib/syskit/models/bound_data_service.rb', line 417 def droby_dump(peer) DRoby.new(name, peer.dump(component_model), peer.dump(master), peer.dump(model)) end |
#dynamic? ⇒ Boolean
True if this is a dynamic service
50 |
# File 'lib/syskit/models/bound_data_service.rb', line 50 def dynamic?; false end |
#each_data_service(&block) ⇒ Object
[View source]
261 262 263 |
# File 'lib/syskit/models/bound_data_service.rb', line 261 def each_data_service(&block) self end |
#each_fullfilled_model(&block) ⇒ Object
[View source]
270 271 272 |
# File 'lib/syskit/models/bound_data_service.rb', line 270 def each_fullfilled_model(&block) model.each_fullfilled_model(&block) end |
#each_input_port ⇒ Object
[View source]
125 126 127 128 129 130 |
# 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 |
#each_output_port ⇒ Object
[View source]
118 119 120 121 122 123 |
# 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 |
#each_required_model {|model| ... } ⇒ Object
341 342 343 344 |
# File 'lib/syskit/models/bound_data_service.rb', line 341 def each_required_model return enum_for(:each_required_model) if !block_given? yield(model) end |
#each_slave_data_service(&block) ⇒ Object
Enumerates the data services that are slave of this one
266 267 268 |
# 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 |
#eql?(other) ⇒ Boolean
56 57 58 59 60 61 |
# 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 |
#find_data_service(name) ⇒ Object
[View source]
355 356 357 358 359 360 361 362 |
# File 'lib/syskit/models/bound_data_service.rb', line 355 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 |
#find_input_port(name) ⇒ Object
[View source]
111 112 113 114 115 116 |
# 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 |
#find_output_port(name) ⇒ Object
[View source]
104 105 106 107 108 109 |
# 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 |
#find_port_for_task_port(task_port) ⇒ nil, Port
Returns the service port that maps to a task port
225 226 227 228 229 230 231 232 233 |
# 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 |
#find_through_method_missing(m, args) ⇒ Object
[View source]
368 369 370 371 372 |
# File 'lib/syskit/models/bound_data_service.rb', line 368 def find_through_method_missing(m, args) MetaRuby::DSLs.find_through_method_missing( self, m, args, '_srv'.freeze => :find_data_service) || super end |
#fullfilled_model ⇒ Object
[View source]
205 206 207 |
# File 'lib/syskit/models/bound_data_service.rb', line 205 def fullfilled_model [model] end |
#fullfills?(models) ⇒ Boolean
Returns true if self provides all models in models
210 211 212 213 214 215 216 217 218 219 220 |
# 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 |
#has_data_service?(name) ⇒ Boolean
348 349 350 351 352 353 |
# File 'lib/syskit/models/bound_data_service.rb', line 348 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 |
#has_through_method_missing?(m) ⇒ Boolean
364 365 366 367 |
# File 'lib/syskit/models/bound_data_service.rb', line 364 def has_through_method_missing?(m) MetaRuby::DSLs.has_through_method_missing?( self, m, '_srv'.freeze => :has_data_service?) || super end |
#hash ⇒ Object
[View source]
67 |
# File 'lib/syskit/models/bound_data_service.rb', line 67 def hash; [self.class, full_name, component_model].hash end |
#initialize_copy(original) ⇒ Object
[View source]
88 89 90 91 |
# File 'lib/syskit/models/bound_data_service.rb', line 88 def initialize_copy(original) super @ports = Hash.new end |
#inspect ⇒ Object
[View source]
161 |
# File 'lib/syskit/models/bound_data_service.rb', line 161 def inspect; to_s end |
#instanciate(plan, context = DependencyInjectionContext.new, options = Hash.new) ⇒ Syskit::BoundDataService
Creates, in the given plan, a new task matching this service in the given context, and returns the instanciated data service
327 328 329 |
# File 'lib/syskit/models/bound_data_service.rb', line 327 def instanciate(plan, context = DependencyInjectionContext.new, = Hash.new) bind(component_model.instanciate(plan, context, )) end |
#master? ⇒ Boolean
True if this service is not a slave service
47 |
# File 'lib/syskit/models/bound_data_service.rb', line 47 def master?; !@master end |
#merge(other_model) ⇒ Object
[View source]
274 275 276 277 |
# File 'lib/syskit/models/bound_data_service.rb', line 274 def merge(other_model) m = other_model.merge(component_model) attach(m) end |
#orogen_model ⇒ Object
- Orocos::Spec::TaskContext
-
the oroGen model for this service's
interface
100 101 102 |
# File 'lib/syskit/models/bound_data_service.rb', line 100 def orogen_model model.orogen_model end |
#port_mappings_for(service_model) ⇒ Hash<String,String>
Returns the port mappings that should be applied from one of the service models provided by #model to #component_model
254 255 256 257 258 259 |
# 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 |
#port_mappings_for_task ⇒ Hash<String,String>
Returns the port mappings that should be applied to convert a port from this service to #component_model
242 243 244 |
# File 'lib/syskit/models/bound_data_service.rb', line 242 def port_mappings_for_task port_mappings_for(model) end |
#pretty_print(pp) ⇒ Object
[View source]
167 168 169 170 171 172 173 |
# 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 |
#resolve(task) ⇒ Object
use #bind instead
317 318 319 320 321 |
# File 'lib/syskit/models/bound_data_service.rb', line 317 def resolve(task) Roby.warn_deprecated "#{__method__} is deprecated, use "\ "BoundDataService#bind instead" bind(task) end |
#same_service?(other) ⇒ Boolean
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
393 394 395 |
# File 'lib/syskit/models/bound_data_service.rb', line 393 def same_service?(other) other.demoted == self.demoted end |
#selected_for(requirements) ⇒ InstanceSelection
The selection object that represents self being selected for requirements
403 404 405 |
# File 'lib/syskit/models/bound_data_service.rb', line 403 def selected_for(requirements) InstanceSelection.new(nil, self.to_instance_requirements, requirements.to_instance_requirements) end |
#self_port_to_component_port(port) ⇒ Models::Port
Resolves the given port model into a component model where #component_model is a proper component (e.g. not a BoundDataService)
It is not meant to be used directly. Use Port#to_component_port instead
94 95 96 |
# 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 |
#short_name ⇒ Object
[View source]
163 164 165 |
# File 'lib/syskit/models/bound_data_service.rb', line 163 def short_name "#{component_model.short_name}:#{full_name}" end |
#to_component_model ⇒ Object
[View source]
52 |
# File 'lib/syskit/models/bound_data_service.rb', line 52 def to_component_model; component_model.to_component_model end |
#to_instance_requirements ⇒ Syskit::InstanceRequirements
Generates the InstanceRequirements object that represents self
best
335 336 337 338 339 |
# File 'lib/syskit/models/bound_data_service.rb', line 335 def to_instance_requirements req = component_model.to_instance_requirements req.select_service(self) req end |
#to_s ⇒ Object
[View source]
157 158 159 |
# File 'lib/syskit/models/bound_data_service.rb', line 157 def to_s "#{component_model.short_name}.#{full_name}" end |