Skip to content

Commit bbfbd92

Browse files
committed
fix: handling of placeholder models in dependency injection
The placeholder models (of which the most obvious instance is the profile tag) were handled as normal component models by DependencyInjection. This led to their selection to be reduced to component models as well, which fails if there are ambiguities and one want to select a particular service, that is some_tag => component_m.my_srv Rewrite the selection logic to use the placeholder-friendly API (each_required_model and fullfills?)
1 parent 53c3be2 commit bbfbd92

File tree

3 files changed

+449
-376
lines changed

3 files changed

+449
-376
lines changed

lib/syskit/dependency_injection.rb

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -202,31 +202,65 @@ def self.normalize_selection(selection)
202202
next
203203
end
204204

205-
if value.respond_to?(:fullfills?) && !value.fullfills?(key)
206-
raise ArgumentError,
207-
"found #{value.name}(of class #{value.class}) " \
208-
"as a selection for #{key.name}, but " \
209-
"#{value.name} does not fullfill #{key.name}"
205+
normalized[key] = normalize_component_model_selection(key, value)
206+
end
207+
normalized
208+
end
209+
210+
# @api private
211+
#
212+
# Helper for normalize_selection when the key is a component model (e.g.
213+
# "real" component model, data service model or placeholder model)
214+
#
215+
# @param [Class<AbstractComponent>] key
216+
# @param [String,SpecialDIValue,#fullfills?] value
217+
# @return [String,SpecialDIValue,#fullfills?] normalized selected value
218+
def self.normalize_component_model_selection(key, value)
219+
if value.respond_to?(:to_str)
220+
return value
221+
elsif value.kind_of?(SpecialDIValue)
222+
return value
223+
end
224+
225+
unless value.fullfills?(key)
226+
raise ArgumentError,
227+
"found #{value.name}(of class #{value.class}) " \
228+
"as a selection for #{key.name}, but " \
229+
"#{value.name} does not fullfill #{key.name}"
230+
end
231+
232+
required_component_m = nil
233+
required_services_m = []
234+
required_component_m, required_services_m =
235+
key.each_required_model.partition do |m|
236+
m <= Component
210237
end
238+
if required_services_m.size > 1
239+
raise NotImplementedError,
240+
"there is no support (yet) to select for multiple services"
241+
elsif !required_component_m && required_services_m.empty?
242+
raise NotImplementedError, "nothing to select in #{key}"
243+
end
211244

212-
if key <= Component
213-
if value.kind_of?(Models::BoundDataService)
214-
value = value.component_model
215-
elsif value.kind_of?(Syskit::BoundDataService)
216-
value = value.component
217-
end
218-
normalized[key] = value
219-
elsif key <= DataService
220-
if value.respond_to?(:find_data_service_from_type)
221-
value = value.find_data_service_from_type(key)
222-
end
223-
normalized[key] = value
224-
else
225-
raise NotImplementedError,
226-
"should not have get there, but did"
245+
required_component_m = required_component_m.first
246+
required_service_m = required_services_m.first
247+
248+
if required_service_m && !required_component_m
249+
if value.respond_to?(:find_data_service_from_type)
250+
value =
251+
value.find_data_service_from_type(required_services_m.first)
252+
end
253+
254+
value
255+
else
256+
if value.kind_of?(Models::BoundDataService)
257+
value = value.component_model
258+
elsif value.kind_of?(Syskit::BoundDataService)
259+
value = value.component
227260
end
261+
262+
value
228263
end
229-
normalized
230264
end
231265

232266
# Add a list of objects to the default list.

0 commit comments

Comments
 (0)