class OroGen::Spec::Typekit

A typekit, i.e. a subpart of the system that handles a set of types

Typekits provide (at model time) definitions of types, and (at runtime) the support to marshal/unmarshal them on transports

Attributes

imported_typekits[R]
interface_typelist[R]
loader[R]
name[R]
opaque_registry[R]
opaques[R]
registry[R]
typelist[R]

Public Class Methods

from_raw_data(loader, name, registry_xml, typelist_txt) click to toggle source
# File lib/orogen/spec/typekit.rb, line 71
def self.from_raw_data(loader, name, registry_xml, typelist_txt)
    typekit_registry = Typelib::Registry.new
    Typelib::Registry.add_standard_cxx_types(typekit_registry)
    typekit_registry.merge_xml(registry_xml)

    typekit_typelist, typekit_interface_typelist = parse_typelist(typelist_txt)
    typekit = self.new(loader, name,
                  typekit_registry,
                  typekit_typelist,
                  typekit_interface_typelist)

    listener = OpaqueInfoListener.new(typekit_registry)
    REXML::Document.parse_stream(registry_xml, listener)
    typekit.opaques.concat(listener.opaques)
    typekit.opaque_registry.merge(listener.registry)

    typekit
end
new(loader, name, registry = Typelib::Registry.new, typelist = [], interface_typelist = []) click to toggle source
# File lib/orogen/spec/typekit.rb, line 90
def initialize(loader, name, registry = Typelib::Registry.new, typelist = [], interface_typelist = [])
    @loader = loader
    @name, @registry = name, registry
    @typelist = typelist.to_set
    @interface_typelist = interface_typelist.to_set
    @opaques = Array.new
    @opaque_registry = Typelib::Registry.new
    @imported_typekits = Set.new
end
parse_typelist(typelist_txt) click to toggle source
# File lib/orogen/spec/typekit.rb, line 23
def self.parse_typelist(typelist_txt)
    raw_typelist = typelist_txt.split("\n").map(&:strip)
    typekit_typelist, typekit_interface_typelist = [], []
    raw_typelist.each do |decl|
        # using non greedy kleene star to match first expression: .*?
        # to handle following patterns:
        # /string
        # /unsigned char[8]
        # /unsigned char[8] 0 
        if decl =~ /^(.*) (\d)$/
            type, is_interface = $1, ($2 == '1')
        else
            type, is_interface = decl, true
        end

        typekit_typelist << type
        if is_interface
            typekit_interface_typelist << type
        end
    end
    return typekit_typelist, typekit_interface_typelist
end

Public Instance Methods

defines_array_of?(type) click to toggle source
# File lib/orogen/spec/typekit.rb, line 111
def defines_array_of?(type)
    typename = if type.respond_to?(:name) then type.name
               else type.to_str
               end

    typelist.any? { |str| str =~ /#{Regexp.quote(typename)}(\[\d+\])+/ }
end
find_opaque_for_intermediate(type) click to toggle source

Finds the opaque (or opaque-containing) type for which the given type is an intermediate

@return [Type,nil] the type, or nil if 'type' is not used as an

intermediate
# File lib/orogen/spec/typekit.rb, line 159
def find_opaque_for_intermediate(type)
    type = resolve_type(type.name)
    if m_type?(type)
        # Yuk
        begin
            if @intermediate_to_opaque && (result = @intermediate_to_opaque[type.name])
                result
            elsif type.name =~ /_m$/
                resolve_type(type.name.gsub(/_m$/, ''))
            else raise Typelib::NotFound
            end
        rescue Typelib::NotFound
            # This is a pretty expensive operation and is seldom
            # needed, so avoid doing it unnecessarily
            @intermediate_to_opaque ||= Hash.new
            @indexed_intermediates ||= Set.new
            registry.each do |t|
                if !@indexed_intermediates.include?(t) && t.contains_opaques?
                    @indexed_intermediates << t
                    @intermediate_to_opaque[intermediate_type_name_for(t)] = t
                end
            end
            @intermediate_to_opaque[type.name]
        end
    elsif type <= Typelib::ContainerType
        if opaque_deference = find_opaque_for_intermediate(type.deference)
            resolve_type("#{type.container_kind}<#{opaque_deference.name}>")
        end
    elsif opaque_def = opaques.find { |spec| resolve_type(spec.intermediate).eql? type }
        opaque_def.type
    end
end
has_opaques?() click to toggle source
# File lib/orogen/spec/typekit.rb, line 100
def has_opaques?
    if @has_opaques.nil?
        @has_opaques = registry.any? { |t| includes?(t) && t.opaque? }
    end
    @has_opaques
end
include?(type) click to toggle source
# File lib/orogen/spec/typekit.rb, line 125
def include?(type)
    typename = if type.respond_to?(:name) then type.name
               else type.to_str
               end
    typelist.include?(typename)
end
includes?(type) click to toggle source

@deprecated use {#include} instead

# File lib/orogen/spec/typekit.rb, line 121
def includes?(type)
    include?(type)
end
inspect() click to toggle source
# File lib/orogen/spec/typekit.rb, line 282
def inspect
    "#<OroGen::Spec::Typekit #{name}>"
end
interface_type?(type) click to toggle source
# File lib/orogen/spec/typekit.rb, line 132
def interface_type?(type)
    typename = if type.respond_to?(:name) then type.name
               else type.to_str
               end
    interface_typelist.include?(typename)
end
intermediate_type?(type) click to toggle source

Checks if a type is used as an intermediate

# File lib/orogen/spec/typekit.rb, line 256
def intermediate_type?(type)
    !!find_opaque_for_intermediate(type)
end
intermediate_type_for(type_def) click to toggle source

Gets the intermediate type for a given type

@param [Type,String] type_def the type or type name @return [Type] the type of the intermediate, or 'type_def' itself

if 'type_def' is not an opaque

@raises Typelib::NotFound if the expected intermediate type cannot

be found
# File lib/orogen/spec/typekit.rb, line 239
def intermediate_type_for(type_def)
    typename = intermediate_type_name_for(type_def)
    return resolve_type(typename)
end
intermediate_type_name_for(type_def) click to toggle source

Computes the name of the type that should be used as an intermediate for the given type

@param [String,Type] type_def the type or type name @param [Boolean] is_normalized if true, the provided type name is

supposed to be normalized. Otherwise, an (expensive) normalization
will be computed if it cannot be found as-is in the typekit's
registry

@return [String] the normalized name of the intermediate type, or

the type's name if 'type' is not an opaque
# File lib/orogen/spec/typekit.rb, line 202
def intermediate_type_name_for(type_def)
    type = resolve_type(type_def)
    if type.opaque?
        opaque_specification(type_def).intermediate
    elsif type.contains_opaques?
        if type < Typelib::ArrayType
            "#{intermediate_type_name_for(type.deference)}[#{type.length}]"
        elsif type < Typelib::ContainerType
            "#{type.container_kind}<#{intermediate_type_name_for(type.deference)}>"
        else
            path = Typelib.split_typename(type.name)
            path.map! do |p|
                p.gsub(/[<>\[\], \/]/, '_')
            end
            "/" + path.join("/") + "_m"
        end
    else type.name
    end
end
m_type?(type) click to toggle source

Checks if a type is an oroGen-generated type used as an intermediate

# File lib/orogen/spec/typekit.rb, line 262
def m_type?(type)
    typename = type.name
    if type.name =~ /_m$/
        return true
    end

    if type.respond_to?(:deference)
        while type.respond_to?(:deference)
            type = type.deference
        end
        m_type?(type)
    else
        false
    end
end
method_missing(m, *args, &block) click to toggle source

Adds to the API of self the create_* methods on Typelib::Registry. All create_ methods are available, as well as the corresponding create_interface_XXX which both creates the type and declares it as a valid interface type

@example create a null type

typekit.create_interface_null('/NewType')
Calls superclass method
# File lib/orogen/spec/typekit.rb, line 300
def method_missing(m, *args, &block)
    case m.to_s
    when /^create_(interface_)?(\w+)$/
        interface = !!$1
        category  = $2
        type = registry.send("create_#{category}", *args, &block)
        typelist << type.name
        if interface
            interface_typelist << type.name
        end
        type
    else super
    end
end
opaque_specification(type_def) click to toggle source

Get the opaque definition for a given type

@param [Type,String] the type or type name @return [OpaqueDefinition]

# File lib/orogen/spec/typekit.rb, line 143
def opaque_specification(type_def)
    type = resolve_type(type_def)
    raise "#{type} is unknown" unless type
    raise "#{type} is not opaque" unless type.opaque?
    if result = opaques.find { |opaque_def| opaque_def.type.eql? type }
        result
    else
        raise InternalError, "#{self}#opaque_specification called for type #{type.name}, but could not find the corresponding opaque specification"
    end
end
opaque_type_for(type) click to toggle source

Gets the opaque type for a given type

@param [#name,String] type the type or type name @return [Model<Typelib::Type>] the type of the opaque, or the

given type if it is not an intermediate type

@raises Typelib::NotFound if the expected intermediate type cannot

be found
# File lib/orogen/spec/typekit.rb, line 251
def opaque_type_for(type)
    find_opaque_for_intermediate(type) || resolve_type(type)
end
resolve_type(type) click to toggle source

Returns a matching type in {#registry}

@param [#name,String] type @return [Model<Typelib::Type>] @raise Typelib::NotFound

# File lib/orogen/spec/typekit.rb, line 227
def resolve_type(type)
    type = type.name if type.respond_to?(:name)
    registry.get(type)
end
respond_to_missing?(m, include_private = false) click to toggle source
Calls superclass method
# File lib/orogen/spec/typekit.rb, line 286
def respond_to_missing?(m, include_private = false)
    if super then return super
    elsif m.to_s =~ /^create_(interface_)?(\w+)$/
        registry.respond_to?("create_#{$2}")
    end
end
self_types() click to toggle source
# File lib/orogen/spec/typekit.rb, line 107
def self_types
    typelist.map { |name| registry.get(name) }
end
to_s() click to toggle source
# File lib/orogen/spec/typekit.rb, line 278
def to_s
    "#<OroGen::Spec::Typekit #{name}>"
end