class OroGen::Loaders::Base

Definition of the base loader API

Attributes

interface_typelist[R]

The list of types that can be used on an oroGen interface

loaded_deployment_models[R]

Set of deployment models that are known to us

loaded_projects[R]

Set of projects loaded so far

@return [Hash<String,Spec::Project>]

loaded_task_models[R]

Set of task models that are known to us

loaded_typekits[R]

Set of typekits loaded so far

@return [Hash<String,Spec::Typekit>]

project_load_callbacks[R]

Set of callbacks that are called whenever a new typekit gets loaded

@return [Array<#call>]

registry[R]

The registry that includes types from all loaded typekits

root_loader[R]

The loader that should be used to resolve dependencies

typekit_load_callbacks[R]

Set of callbacks that are called whenever a new typekit gets loaded

@return [Array<#call>]

typekits_by_type_name[R]

A mapping from type names to the typekits that define them

Public Class Methods

new(root_loader = self) click to toggle source
# File lib/orogen/loaders/base.rb, line 50
def initialize(root_loader = self)
    @root_loader = root_loader || self
    if root_loader != self
        root_loader.added_child(self)
    end
    @typekit_load_callbacks = Array.new
    @project_load_callbacks = Array.new
    clear
end

Public Instance Methods

added_child(loader) click to toggle source
# File lib/orogen/loaders/base.rb, line 70
def added_child(loader)
end
clear() click to toggle source
# File lib/orogen/loaders/base.rb, line 60
def clear
    @loaded_projects = Hash.new
    @loaded_typekits = Hash.new
    @loaded_task_models = Hash.new
    @loaded_deployment_models = Hash.new
    @typekits_by_type_name = Hash.new
    @registry = Typelib::Registry.new
    @interface_typelist = Set.new
end
deployed_task_model_from_name(name, deployment_name = nil) click to toggle source

Returns the deployed task model for the given name

@param [String] name the deployed task name @param [String] deployment_name () the name of the deployment in which the

task is defined. It must be given only when more than one deployment
defines a task with the requested name

@return [OroGen::Spec::TaskDeployment] the deployed task model @raise [DeployedTaskModelNotFound] if no deployed tasks with that name exists @raise [DeployedTaskModelNotFound] if deployment_name was given, but the requested

task is not defined in this deployment

@raise [OroGen::AmbiguousName] if more than one task exists with that

name. In that case, you will have to provide the deployment name
explicitly using the second argument
# File lib/orogen/loaders/base.rb, line 207
def deployed_task_model_from_name(name, deployment_name = nil)
    if deployment_name
        deployment = deployment_model_from_name(deployment_name)
    else
        deployment_names = find_deployments_from_deployed_task_name(name)
        if deployment_names.empty?
            raise DeployedTaskModelNotFound, "cannot find a deployed task called #{name}"
        elsif deployment_names.size > 1
            raise AmbiguousName, "more than one deployment defines a deployed task called #{name}: #{deployment_names.map(&:name).sort.join(", ")}"
        end
        deployment = deployment_model_from_name(deployment_names.first)
    end

    if !(task = deployment.find_task_by_name(name))
        if deployment_name
            raise DeployedTaskModelNotFound, "deployment #{deployment_name} does not have a task called #{name}"
        else
            raise InternalError, "deployment #{deployment_name} was supposed to have a task called #{name} but does not"
        end
    end
    task
end
deployment_model_from_name(name) click to toggle source

Returns the deployment model for the given deployment name

@param [String] name the deployment name @return [OroGen::Spec::Deployment] the deployment model @raise [DeploymentModelNotFound] if no deployment with that name exists

# File lib/orogen/loaders/base.rb, line 176
def deployment_model_from_name(name)
    if model = loaded_deployment_models[name]
        return model
    end

    project_name = find_project_from_deployment_name(name)
    if !project_name
        raise DeploymentModelNotFound, "there is no deployment called #{name} on #{self}"
    end

    project = project_model_from_name(project_name)
    deployment = project.deployers[name]
    if !deployment
        raise InternalError, "cannot find the deployment called #{name} in #{project.name}. Candidates were #{project.deployers.map(&:name).sort.join(", ")}"
    end
    deployment
end
each_available_project_name() click to toggle source

Enumerates the names of all available projects

@yieldparam [String] project_name

# File lib/orogen/loaders/base.rb, line 545
def each_available_project_name
    return enum_for(__method__) if !block_given?
    nil
end
find_deployments_from_deployed_task_name(name) click to toggle source

Returns the set of deployments that contain a certain task

@param [String] name @return [Set<String>]

# File lib/orogen/loaders/base.rb, line 539
def find_deployments_from_deployed_task_name(name)
end
find_project_from_deployment_name(name) click to toggle source

Returns the project that defines the given deployment

@param [String] deployment_name the deployment we are looking for @return [String,nil]

# File lib/orogen/loaders/base.rb, line 532
def find_project_from_deployment_name(name)
end
find_task_library_from_task_model_name(name) click to toggle source

Returns the task library name in which a task model is defined

@param [String] model_name the name of the task model to look for @return [String,nil]

# File lib/orogen/loaders/base.rb, line 524
def find_task_library_from_task_model_name(name)
    raise NotImplementedError, "#{self.class} does not implement #find_task_library_from_task_model_name"
end
has_loaded_project?(name) click to toggle source
# File lib/orogen/loaders/base.rb, line 455
def has_loaded_project?(name)
    loaded_projects.has_key?(name)
end
has_loaded_typekit?(name) click to toggle source

Tests if a typekit with that name has been loaded

@param [String] name the typekit name @return [Boolean]

# File lib/orogen/loaders/base.rb, line 508
def has_loaded_typekit?(name)
    loaded_typekits.has_key?(name)
end
has_project?(name) click to toggle source

Tests if a project with that name exists

@param [String] name the project name @return [Boolean]

# File lib/orogen/loaders/base.rb, line 500
def has_project?(name)
    loaded_projects.has_key?(name)
end
has_typekit?(name) click to toggle source

Tests if a typekit with that name exists

@param [String] name the typekit name @return [Boolean]

# File lib/orogen/loaders/base.rb, line 516
def has_typekit?(name)
    loaded_typekits.has_key?(name)
end
imported_typekits_for(typename, definition_typekits: true) click to toggle source

Returns the typekit object that defines this type

@option options [Boolean] :definition_typekits (true) if true,

only the typekits that actually have the type in their typelist
are returned. Otherwise, every typekit that have it in their
registry are returned.

@return [Set<Spec::Typekit>] the list of typekits @raise [DefinitionTypekitNotFound] if no typekits define this type

# File lib/orogen/loaders/base.rb, line 350
def imported_typekits_for(typename, definition_typekits: true)
    if typename.respond_to?(:name)
        typename = typename.name
    end
    if typekits = typekits_by_type_name[typename]
        if definition_typekits
            definition_typekits = typekits.find_all { |tk| tk.include?(typename) }
            if definition_typekits.empty?
                raise DefinitionTypekitNotFound, "typekits #{typekits.map(&:name).sort.join(", ")} have #{typename} in their registries, but it seems that they got it from another typekit and I cannot find it. definition_typekits is true, I raise"
            end
            return definition_typekits.to_set
        else
            return typekits
        end
    end
    raise DefinitionTypekitNotFound, "#{typename} is not defined by any typekits loaded so far"
end
inspect() click to toggle source
# File lib/orogen/loaders/base.rb, line 571
def inspect
    to_s
end
interface_type?(typename) click to toggle source

Tests whether the given type can be used on an interface

@param [#name,String] typename the type @return [Boolean]

# File lib/orogen/loaders/base.rb, line 386
def interface_type?(typename)
    typename = typename.name if typename.respond_to?(:name)
    interface_typelist.include?(typename)
end
intermediate_type?(type) click to toggle source

Tests whether the given type can be used on an interface

@param (see OroGen::Spec::Typekit#intermediate_type?) @return (see OroGen::Spec::Typekit#intermediate_type?)

# File lib/orogen/loaders/base.rb, line 395
def intermediate_type?(type)
    type = resolve_type(type)
    !type.metadata.get('orogen:intermediate_type_of').empty?
end
intermediate_type_for(type) click to toggle source

Returns the intermediate type that is paired with the given type

@param (see OroGen::Spec::Typekit#opaque_type_for) @raise (see OroGen::Spec::Typekit#opaque_type_for) @return (see OroGen::Spec::Typekit#opaque_type_for)

# File lib/orogen/loaders/base.rb, line 416
def intermediate_type_for(type)
    type = resolve_type(type)
    intermediates = type.metadata.get('orogen:intermediate_type')
    registry.get(intermediates.first || type.name)
end
m_type?(type) click to toggle source

Returns whether this type is a m-type (intermediate type generated by oroGen)

@param (see OroGen::Spec::Typekit#m_type?) @raise (see OroGen::Spec::Typekit#m_type?) @return (see OroGen::Spec::Typekit#m_type?)

# File lib/orogen/loaders/base.rb, line 428
def m_type?(type)
    type = resolve_type(type)
    type.metadata.get('orogen:generated_type') == ['true']
end
on_project_load(initial_events = true, &block) click to toggle source

Registers a callback that should be called with newly registered projects

@param [Boolean] initial_events if true, the callbacks will be

called instantly with the projects that have already been loaded
# File lib/orogen/loaders/base.rb, line 113
def on_project_load(initial_events = true, &block)
    project_load_callbacks << block
    if initial_events
        current_set = loaded_projects.values.dup
        current_set.each do |p|
            block.call(p)
        end
    end
    block
end
on_typekit_load(initial_events = true, &block) click to toggle source

Registers a callback that should be called with newly registered typekits

@param [Boolean] initial_events if true, the callbacks will be

called instantly with the typekits that have already been loaded
# File lib/orogen/loaders/base.rb, line 309
def on_typekit_load(initial_events = true, &block)
    typekit_load_callbacks << block
    if initial_events
        current_set = loaded_typekits.values.dup
        current_set.each do |tk|
            block.call(tk)
        end
    end
end
opaque_type_for(type) click to toggle source

Returns the opaque type that is paired with the given type

@param (see OroGen::Spec::Typekit#opaque_type_for) @raise (see OroGen::Spec::Typekit#opaque_type_for) @return (see OroGen::Spec::Typekit#opaque_type_for)

# File lib/orogen/loaders/base.rb, line 405
def opaque_type_for(type)
    type = resolve_type(type)
    opaques = type.metadata.get('orogen:intermediate_type_of')
    registry.get(opaques.first || type.name)
end
project_model_from_name(name) click to toggle source

Returns the project model corresponding to the given name

@param [String] the project name @raise [ProjectNotFound] if there is no project with that

name.

@return [OroGen::Spec::Project]

# File lib/orogen/loaders/base.rb, line 79
def project_model_from_name(name)
    if project = loaded_projects[name]
        return project
    end

    name = name.to_str

    text, path = project_model_text_from_name(name)
    OroGen.info "loading oroGen project #{name}"
    project_model_from_text(text, name: name, path: path)
end
project_model_from_text(text, name: nil, path: nil) click to toggle source
# File lib/orogen/loaders/base.rb, line 91
def project_model_from_text(text, name: nil, path: nil)
    project = Spec::Project.new(root_loader)
    project.typekit =
        if has_typekit?(name)
            typekit_model_from_name(name)
        else
            Spec::Typekit.new(root_loader, name)
        end

    Loaders::Project.new(project).__eval__(path, text)
    if name && (project.name != name)
        raise ArgumentError, "got project #{project.name} while loading #{name}"
    end
    register_project_model(project)
    project
end
project_model_text_from_name(name) click to toggle source

Returns the textual representation of a project model

@param [String] the project name @raise [ProjectNotFound] if there is no project with that

name.

@return [(String,String)] the model as text, as well as a path to

the model file (or nil if there is no such file)
# File lib/orogen/loaders/base.rb, line 482
def project_model_text_from_name(name)
    raise NotImplementedError
end
register_deployment_model(model) click to toggle source

Registers a new deployment model

@param [Spec::Deployment] model @return [void]

# File lib/orogen/loaders/base.rb, line 471
def register_deployment_model(model)
    loaded_deployment_models[model.name] = model
end
register_project_model(project) click to toggle source

Registers this project's subobjects

# File lib/orogen/loaders/base.rb, line 434
def register_project_model(project)
    if loaded_projects.has_key?(project.name)
        raise AlreadyRegistered, "there is already a project called #{project.name} registered on #{self}"
    end

    loaded_projects[project.name] = project
    if root_loader != self
        return root_loader.register_project_model(project)
    end

    project.tasks.each do |_, task_model|
        register_task_context_model(task_model)
    end
    project.deployers.each do |_, deployer_model|
        register_deployment_model(deployer_model)
    end
    project_load_callbacks.each do |callback|
        callback.call(project)
    end
end
register_task_context_model(model) click to toggle source

Registers a new task model

@param [Spec::TaskContext] model @return [void]

# File lib/orogen/loaders/base.rb, line 463
def register_task_context_model(model)
    loaded_task_models[model.name] = model
end
register_type_model(type, interface = true) click to toggle source
# File lib/orogen/loaders/base.rb, line 297
def register_type_model(type, interface = true)
    registry.merge type.registry.minimal(type.name)
    if interface
        interface_typelist << type.name
    end
end
register_typekit_model(typekit) click to toggle source

Registers information from this typekit

Callbacks registered by {#on_typekit_load} gets called with the new typekit as argument

# File lib/orogen/loaders/base.rb, line 254
def register_typekit_model(typekit)
    if loaded_typekits.has_key?(typekit.name)
        raise AlreadyRegistered, "there is already a typekit called #{typekit.name} registered on #{self}"
    end

    loaded_typekits[typekit.name] = typekit
    if root_loader != self
        return root_loader.register_typekit_model(typekit)
    end

    registry.merge typekit.registry

    typekit.registry.each(with_aliases: false) do |type|
        self_type = registry.get(type.name)
        self_type.metadata.add('orogen:typekits', typekit.name)
        if typekit.include?(type.name)
            self_type.metadata.add('orogen:definition_typekits', typekit.name)
        end

        if type.contains_opaques?
            intermediate_type_name = typekit.intermediate_type_name_for(type)
            intermediate_type = registry.get(intermediate_type_name)
            self_type.metadata.add('orogen:intermediate_type',
                              intermediate_type_name)
            intermediate_type.metadata.add('orogen:intermediate_type_of',
                                           type.name)
            if !type.opaque?
                intermediate_type.metadata.set('orogen:generated_type',
                                               'true')
            end
        end
    end

    @interface_typelist |= typekit.interface_typelist
    typekit.registry.each(with_aliases: true) do |typename, _|
        typekits_by_type_name[typename] ||= Set.new
        typekits_by_type_name[typename] << typekit
    end
    typekit_load_callbacks.each do |callback|
        callback.call(typekit)
    end
end
remove_project_load_callback(callback) click to toggle source

Removes the given callback from the listeners to {on_project_load}

@param [Object] callback the value returned by {on_project_load}

for the callback that should be removed
# File lib/orogen/loaders/base.rb, line 128
def remove_project_load_callback(callback)
    project_load_callbacks.delete(callback)
end
resolve_interface_type(typename) click to toggle source

Returns the type object for typename, validating that we can use it in a task interface, i.e. that it will be registered in the RTT's typeinfo system

# File lib/orogen/loaders/base.rb, line 371
def resolve_interface_type(typename)
    type = resolve_type(typename)
    if type < Typelib::ArrayType
        raise InvalidInterfaceType.new(type), "static arrays are not valid interface types. Use an array in a structure or a std::vector"
    elsif !interface_type?(type)
        typekits = imported_typekits_for(type.name)
        raise NotExportedType.new(type, typekits), "#{type.name}, defined in the #{typekits.map(&:name).join(", ")} typekits, is never exported"
    end
    type
end
resolve_type(type, options = Hash.new) click to toggle source

Resolves a type object

@param [#name,String] type the type to be resolved @return [Model<Typelib::Type>] the corresponding type in

{#registry}

@raise Typelib::NotFound if the type cannot be found

# File lib/orogen/loaders/base.rb, line 325
def resolve_type(type, options = Hash.new)
    typename =
        if type.respond_to?(:name)
            type.name
        else type
        end
    registry.get(typename)
rescue Typelib::NotFound => e
    if define_dummy_types? || options[:define_dummy_type]
        type = registry.create_null(typename)
        register_type_model(type, interface: true)
        return type
    else raise e, "#{e.message} using #{self}", e.backtrace
    end
end
task_library_model_from_name(name) click to toggle source

Returns the task library model corresponding to the given name @param (see #project_model_from_name) @raise [ProjectNotFound] if there is no task library with that

name. This does including having a project with that name if the
project defines no tasks.

@return (see #project_model_from_name)

# File lib/orogen/loaders/base.rb, line 138
def task_library_model_from_name(name)
    project = project_model_from_name(name)
    if project.self_tasks.empty?
        raise ProjectNotFound, "there is an oroGen project called #{name}, but it defines no tasks"
    end
    project
end
task_model_from_name(name) click to toggle source

Returns the task model object corresponding to a model name

@param [String] name the task model name @return [Spec::TaskContext] @raise [TaskModelNotFound] if there are no such model @raise (see #project_model_from_name)

# File lib/orogen/loaders/base.rb, line 152
def task_model_from_name(name)
    if model = loaded_task_models[name]
        return model
    end

    tasklib_name = find_task_library_from_task_model_name(name)
    if !tasklib_name
        raise TaskModelNotFound, "no task model #{name} is registered"
    end

    tasklib = project_model_from_name(tasklib_name)
    result = tasklib.tasks[name]
    if !result
        raise InternalError, "while looking up model of #{name}: found project #{tasklib_name}, but this project does not actually have a task model called #{name}"
    end

    result
end
typekit_model_from_name(name) click to toggle source

Loads a typekit from its name

@param [String] name the typekit name @return [Spec::Typekit] the typekit @raise [TypekitNotFound] if the typekit cannot be found

# File lib/orogen/loaders/base.rb, line 235
def typekit_model_from_name(name)
    if typekit = loaded_typekits[name]
        return typekit
    end

    registry_xml, typelist_txt = typekit_model_text_from_name(name)
    typekit = Spec::Typekit.from_raw_data(root_loader, name, registry_xml, typelist_txt)
    if typekit.name != name
        raise InternalError, "inconsistency: got typekit #{typekit.name} while loading #{name}"
    end

    register_typekit_model(typekit)
    typekit
end
typekit_model_text_from_name(name) click to toggle source

Returns the textual representation of a typekit

@param [String] the typekit name @raise [TypekitNotFound] if there is no typekit with that name @return [(String,String)] the typekit registry as XML and the

typekit's typelist
# File lib/orogen/loaders/base.rb, line 492
def typekit_model_text_from_name(name)
    raise NotImplementedError
end
typelib_type_for(t) click to toggle source
# File lib/orogen/loaders/base.rb, line 550
def typelib_type_for(t)
    if t.respond_to?(:name)
        return t if !t.contains_opaques?
        t = t.name
    end

    if registry.include?(t)
        type = registry.get(t)
        if type.contains_opaques?
            intermediate_type_for(type)
        elsif type.null?
            # 't' is an opaque type and there are no typelib marshallers
            # to convert it to something we can manipulate, raise
            raise Typelib::NotFound, "#{t} is a null type and there are no typelib marshallers registered in RTT to convert it to a typelib-compatible type"
        else type
        end
    else
        raise Typelib::NotFound, "#{t} cannot be found in the currently loaded registries"
    end
end