class Syskit::InstanceSelection

A representation of a selection matching a given requirement

Attributes

component[R]

The selected task, if one is specified explicitly

@return [Syskit::Component]

required[R]
InstanceRequirements

the required instance

selected[R]
InstanceRequirements

the selected instance. It can only refer to

a single component model. This model is available with {#component_model}

@see #selected_model

service_selection[R]
{Model<DataService> => Models::BoundDataService}

a mapping from

the services in {#required} to the services of {#component_model}.

Public Class Methods

compute_service_selection(selected, required, mappings) click to toggle source

Computes the service selection that will allow to replace a placeholder representing the required models by the given component model. The additional mappings are only used as hints.

@param [Model<Component>] component_m the component model @param [Array<Model<Component>,Model<DataService>>] required

the set of models that are required

@param [{Model<DataService>=>Models::BoundDataService}] mappings a mapping

from data service models to the corresponding selected model on
the component model

@return [{Model<DataService>=>Models::BoundDataService}] the

mapping from the data service models in required_models to the
corresponding bound data services in component_m

@raise [ArgumentError] if a service in mappings is either not a

service of component_model, or does not fullfill the data service
it is selected for

@raise (see Syskit::Models::Component#find_data_service_from_type)

# File lib/syskit/instance_selection.rb, line 99
def self.compute_service_selection(selected, required, mappings)
    mappings = mappings.dup
    if selected.service
        # Save this selection explicitly
        mappings[selected.service.model] = selected.service
    end

    selected_component_model = selected.model.to_component_model
    required_component_model, required_service_models =
        required.component_model || Syskit::Component,
        required.each_required_service_model.to_a

    mappings[required_component_model] =
        selected_component_model

    required_service_models.each do |required_m|
        if selected_m = mappings[required_m]
            # Verify that it is of the right type
            if !selected_component_model.fullfills?(selected_m.component_model)
                raise ArgumentError, "#{selected_m} was explicitly selected for #{required_m}, but is not a service of the selected component model #{selected_component_model}"
            elsif !selected_m.fullfills?(required_m)
                raise ArgumentError, "#{selected_m} was explicitly selected for #{required_m}, but does not provide it"
            end
            mappings[required_m] = selected_m.attach(selected_component_model)
        else
            selected_m = selected_component_model.find_data_service_from_type(required_m)
            if !selected_m
                raise ArgumentError, "selected model #{selected} does not provide required service #{required_m.short_name}"
            end
        end

        mappings[required_m] = selected_m
    end
    mappings
end
new(component = nil, selected = InstanceRequirements.new([Component]), required = InstanceRequirements.new, mappings = Hash.new) click to toggle source
# File lib/syskit/instance_selection.rb, line 20
def initialize(component = nil, selected = InstanceRequirements.new([Component]), required = InstanceRequirements.new, mappings = Hash.new)
    @component = component

    selected = @selected = autoselect_service_if_needed(selected, required, mappings)
    required = @required = required.dup
    @service_selection =
        InstanceSelection.compute_service_selection(selected, required, mappings)
end

Public Instance Methods

autoselect_service_if_needed(selected, required, mappings) click to toggle source
# File lib/syskit/instance_selection.rb, line 46
def autoselect_service_if_needed(selected, required, mappings)
    return selected.dup if selected.service

    if required_srv = required.service
        if srv = selected.find_data_service(required_srv.name)
            srv
        elsif m = mappings[required.service.model]
            selected = selected.dup
            selected.select_service(m)
        else
            selected.find_data_service_from_type(required_srv.model)
        end

    elsif !required.component_model
        required_services = required.each_required_service_model.to_a
        if required_services.size == 1
            required_srv = required_services.first
            if m = mappings[required_srv]
                selected = selected.dup
                selected.select_service(m)
            else
                selected.find_data_service_from_type(required_srv)
            end
        else selected.dup
        end

    else selected.dup
    end
end
bind(task) click to toggle source
# File lib/syskit/instance_selection.rb, line 176
def bind(task)
    selected.bind(task)
end
component_model() click to toggle source

Returns the selected component model

# File lib/syskit/instance_selection.rb, line 77
def component_model
    selected.base_model
end
each_fullfilled_model(&block) click to toggle source
# File lib/syskit/instance_selection.rb, line 180
def each_fullfilled_model(&block)
    required.each_fullfilled_model(&block)
end
fullfills?(set) click to toggle source
# File lib/syskit/instance_selection.rb, line 184
def fullfills?(set)
    selected.fullfills?(set)
end
initialize_copy(old) click to toggle source
# File lib/syskit/instance_selection.rb, line 29
def initialize_copy(old)
    @component = old.component
    @selected = old.selected.dup
    @required = old.required.dup
    @service_selection = service_selection.dup
end
instanciate(plan, context = Syskit::DependencyInjectionContext.new, options = Hash.new) click to toggle source

If this selection does not yet have an associated task, instanciate one

# File lib/syskit/instance_selection.rb, line 162
def instanciate(plan, context = Syskit::DependencyInjectionContext.new, options = Hash.new)
    if component
        # We have an explicitly selected component. We just need to
        # bind the bound data service if there is one
        component = plan[self.component]
        if selected_service = selected.service
            selected_service.bind(component)
        else component
        end
    else
        selected.instanciate(plan, context, options)
    end
end
port_mappings() click to toggle source

Compute the combined port mappings given the service selection in {#service_selection}.

@raise [AmbiguousPortMappings] if two services that were separate

in {#required} used the same port name
# File lib/syskit/instance_selection.rb, line 140
def port_mappings
    if @port_mappings then return @port_mappings end

    mappings = Hash.new
    service_selection.each do |req_m, sel_m|
        mappings.merge!(sel_m.port_mappings_for(req_m)) do |req_name, sel_name1, sel_name2|
            if sel_name1 != sel_name2
                # need to find who has the same port ...
                service_selection.each_key do |other_m|
                    if req_m.has_port?(req_name)
                        raise AmbiguousPortMappings.new(other_m, req_m, req_name)
                    end
                end
            else sel_name1
            end
        end
    end
    @port_mappings = mappings
end
pretty_print(pp) click to toggle source
# File lib/syskit/instance_selection.rb, line 192
def pretty_print(pp)
    pp.text "Instance selection for "
    pp.nest(2) do
        pp.breakable
        pp.text "Component"
        if component
            pp.nest(2) do
                pp.breakable
                component.pretty_print(pp)
            end
        end
        pp.breakable
        pp.text "Required"
        pp.nest(2) do
            pp.breakable
            required.pretty_print(pp)
        end
        pp.breakable
        pp.text "Selected"
        pp.nest(2) do
            pp.breakable
            selected.pretty_print(pp)
        end
        pp.breakable
        pp.text "Services"
        if !service_selection.empty?
            pp.nest(2) do
                pp.breakable
                pp.seplist(service_selection) do |sel|
                    pp.text "#{sel[0].short_name} => #{sel[1].short_name}"
                end
            end
        end
    end
end
selected_model() click to toggle source

Returns the simplest model representation for {selected}

It mostly either returns {selected} or {selected}.model if {InstanceRequirements#plain?} returns resp. false or true

@return [BoundDataService,Model<Component>,InstanceRequirements]

# File lib/syskit/instance_selection.rb, line 42
def selected_model
    selected.simplest_model_representation
end
to_s() click to toggle source
# File lib/syskit/instance_selection.rb, line 188
def to_s
    "#<#{self.class}: #{required} selected=#{selected} service_selection=#{service_selection}>"
end