class Orocos::RobyPlugin::InstanceSelection

A representation of a selection matching a given requirement

Attributes

port_mappings[RW]
requirements[R]
selected_services[RW]
selected_task[RW]

Public Class Methods

compute_service_selection(task_model, required_services, user_call) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1343
def self.compute_service_selection(task_model, required_services, user_call)
    result = Hash.new
    required_services.each do |required|
        next if !required.kind_of?(DataServiceModel)
        candidate_services =
            task_model.find_all_services_from_type(required)

        if candidate_services.size > 1
            throw :invalid_selection if !user_call
            raise AmbiguousServiceSelection.new(task_model, required, candidate_services)
        elsif candidate_services.empty?
            throw :invalid_selection if !user_call
            raise NoMatchingService.new(task_model, required)
        end
        result[required] = candidate_services.first
    end
    result
end
from_object(object, requirements, user_call = true) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1362
def self.from_object(object, requirements, user_call = true)
    result = InstanceSelection.new(requirements.dup)
    required_model = requirements.models

    object_requirements = InstanceRequirements.new
    case object
    when InstanceRequirements
        result.requirements.merge(object)
        if object.service
            required_model.each do |required|
                result.selected_services[required] = object.service
            end
        end
    when InstanceSelection
        result.selected_task = object.selected_task
        result.selected_services = object.selected_services
        result.port_mappings = object.port_mappings
        result.requirements.merge(object.requirements)
    when DataServiceInstance
        if !object.provided_service_model
            raise InternalError, "#{object} has no provided service model"
        end
        required_model.each do |required|
            result.selected_services[required] = object.provided_service_model
        end
        result.selected_task = object.task
        object_requirements.require_model(object.task.model)
        object_requirements.select_service(object.provided_service_model)
    when ProvidedDataService
        required_model.each do |required|
            result.selected_services[required] = object
        end
        object_requirements.require_model(object.component_model)
        object_requirements.select_service(object)
    when DataServiceModel
        object_requirements.require_model(object)
    when Component
        result.selected_task = object
        result.selected_services = compute_service_selection(object.model, required_model, user_call)
        object_requirements.require_model(object.model)
    else
        if object < Component
            object_requirements.require_model(object)
            result.selected_services = compute_service_selection(object, required_model, user_call)
        else
            throw :invalid_selection if !user_call
            raise ArgumentError, "invalid selection #{object}: expected a device name, a task instance or a model"
        end
    end

    result.requirements.merge(object_requirements)
    result
end
new(requirements) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1261
def initialize(requirements)
    @requirements = requirements
    @selected_services = Hash.new
    @port_mappings = Hash.new
end
select_service_by_name(task_model, service_name) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1326
def self.select_service_by_name(task_model, service_name)
    if !(candidate = task_model.find_data_service(service_name))
        # Look for child services. Watch out for ambiguities
        candidates = task_model.each_data_service.find_all do |name, srv|
            srv.name == service_name
        end
        if candidates.size > 1
            raise AmbiguousServiceSelection.new(task_model, service_name, candidates.map(&:last))
        elsif candidates.empty?
            raise UnknownServiceName.new(task_model, service_name)
        else
            candidate = candidates.first.last
        end
    end
    candidate
end

Public Instance Methods

each_fullfilled_model(&block) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1416
def each_fullfilled_model(&block)
    requirements.each_fullfilled_model(&block)
end
fullfills?(set) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1420
def fullfills?(set)
    requirements.fullfills?(set)
end
instanciate(engine, context, options = Hash.new) click to toggle source

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

# File lib/orocos/roby/instance_spec.rb, line 1276
def instanciate(engine, context, options = Hash.new)
    requirements.narrow_model

    options[:task_arguments] ||= requirements.arguments
    if requirements.models.size == 1 && requirements.models.first.kind_of?(Class)
        @selected_task = requirements.models.first.instanciate(engine, context, options)
    else
        @selected_task = requirements.create_placeholder_task
    end

    selected_task.requirements.merge(self.requirements)
    selected_task
rescue InstanciationError => e
    e.instanciation_chain << requirements
    raise
end
pretty_print(pp) click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1428
def pretty_print(pp)
    pp.text "InstanceSelection"
    pp.breakable
    pp.text "Selected: "
    selected_task.pretty_print(pp)
    pp.breakable
    pp.text "Selected Services: "
    if !selected_services.empty?
        pp.nest(2) do
            pp.breakable
            pp.seplist(selected_services) do |sel|
                pp.text "#{sel[0]} => #{sel[1]}"
            end
        end
    end
    pp.breakable
    pp.text "For: "
    pp.nest(2) do
        pp.breakable
        requirements.pretty_print(pp)
    end
end
select_services_for(service_list) click to toggle source

Do an explicit service selection to match requirements in service_list. New services get selected only if relevant services are not already selected in selected_services

# File lib/orocos/roby/instance_spec.rb, line 1296
def select_services_for(service_list)
    if selected_task
        base_object = selected_task.model
    elsif (base_object = requirements.models.find { |m| m <= Component })
        # Remove from service_list the services that are not
        # provided by the component model we found. This is possible
        # at this stage, as the model list can contain both
        # a component model and a list of services.
        service_list = service_list.find_all do |srv|
            requirements.models.find { |m| m.fullfills?(srv) }
        end
    end
    
    # At this stage, the selection only contains data services. We
    # therefore cannot do any explicit service selection and return.
    if !base_object
        return
    end

    service_list.each do |srv|
        matching_service =
            selected_services.keys.find { |sel| sel.fullfills?(srv) }
        if matching_service
            selected_services[srv] = selected_services[matching_service]
        else
            selected_services.merge!(self.class.compute_service_selection(base_object, [srv], true))
        end
    end
end
to_component() click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1267
def to_component
    if selected_task
        return selected_task
    end
    raise ArgumentError, "#{self} has no selected component, cannot convert it"
end
to_s() click to toggle source
# File lib/orocos/roby/instance_spec.rb, line 1424
def to_s
    "#<#{self.class}: #{requirements} selected_task=#{selected_task} selected_services=#{selected_services}>"
end