Class: Orocos::ConfigurationManager

Inherits:
Object
  • Object
show all
Extended by:
Logger::Forward, Logger::Hierarchy
Defined in:
lib/orocos/configurations.rb

Overview

Class that manages a set of configurations

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(loader = Orocos.default_loader) ⇒ ConfigurationManager

Returns a new instance of ConfigurationManager



1077
1078
1079
1080
# File 'lib/orocos/configurations.rb', line 1077

def initialize(loader = Orocos.default_loader)
    @loader = loader
    @conf   = Hash.new
end

Instance Attribute Details

#conf{String=>TaskConfigurations} (readonly)

A mapping from the task model names to the corresponding TaskConfigurations object

Returns:



1075
1076
1077
# File 'lib/orocos/configurations.rb', line 1075

def conf
  @conf
end

#loaderObject (readonly)

Returns the value of attribute loader



1069
1070
1071
# File 'lib/orocos/configurations.rb', line 1069

def loader
  @loader
end

Instance Method Details

#apply(task, names = Array.new, options = Hash.new) ⇒ Object

Applies the specified configuration on task

Parameters:

  • options (Hash) (defaults to: Hash.new)

    a customizable set of options

  • task (TaskContext)

    the task on which the configuration should be applied

Options Hash (options):

  • :model_name (String) — default: task.model.name

    the name of the model that should be used to resolve the configurations

  • :override (Boolean) — default: false

    see the documentation of TaskConfigurations#apply



1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
# File 'lib/orocos/configurations.rb', line 1177

def apply(task, names=Array.new, options = Hash.new)
    if options == true || options == false
        # Backward compatibility
        options = Hash[:override => options]
    end
    options, find_options = Kernel.filter_options options, :override => false, :model_name => task.model.name

    model_name = options[:model_name]
    if model_name.nil?
        raise ArgumentError, "applying configuration on #{task.name} failed. #{task.class} has no model name."
    end
    task_conf = find_task_configuration_object(task, find_options.merge(:model_name => model_name))
    if names = resolve_requested_configuration_names(model_name, task_conf, names)
        ConfigurationManager.info "applying configuration #{names.join(", ")} on #{task.name} of type #{model_name}"
        task_conf.apply(task, names, options[:override])
    else
        ConfigurationManager.info "required default configuration on #{task.name} of type #{model_name}, but #{model_name} has no registered configurations"
    end
    true
end

#find_task_configuration_object(task, options = Hash.new) ⇒ Object



1160
1161
1162
1163
1164
1165
1166
# File 'lib/orocos/configurations.rb', line 1160

def find_task_configuration_object(task, options = Hash.new)
    if !task.model
        raise ArgumentError, "cannot use ConfigurationManager#apply for non-orogen tasks"
    end
    options = Kernel.validate_options options, :model_name => task.model.name
    conf[options[:model_name]]
end

#load_dir(dir) ⇒ {String=>Array<String>}

Loads all configuration files present in the given directory

The directory is assumed to be populated with files of the form

orogen_project::TaskName.yml

each file being a YAML file that follows the format described in the documentation of TaskConfigurations. It will ignore files that do not match this pattern, as well as file that refer to task models that cannot be found.

Parameters:

  • dir (String)

    the path to the directory

Returns:

  • ({String=>Array<String>})

    a mapping from the task model name to the list of configuration sections that got modified or added. Note that the set of sections is guaranteed to not be empty



1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
# File 'lib/orocos/configurations.rb', line 1097

def load_dir(dir)
    if !File.directory?(dir)
        raise ArgumentError, "#{dir} is not a directory"
    end

    changed = Hash.new
    Dir.glob(File.join(dir, '*.yml')) do |file|
        next if !File.file?(file)

        changed_configurations =
            begin load_file(file)
            rescue OroGen::TaskModelNotFound
                ConfigurationManager.warn "ignoring configuration file #{file} as there are no corresponding task model"
                next
            end

        if changed_configurations
            changed.merge!(changed_configurations) do |model_name, old, new|
                old.concat(new).uniq
            end

            changed_configurations.each do |model_name, conf|
                ConfigurationManager.info "  configuration #{conf} of #{model_name} changed"
            end
        end
    end
    changed
end

#load_file(file, model = nil) ⇒ {String=>Array<String>}?

Loads configuration from a YAML file

Parameters:

  • file (String)

    the path to the file

  • model (String, OroGen::Spec) (defaults to: nil)

    it is either an oroGen task context model or the name of such a model If nil, the model is inferred from the file name, which is expected to be of the form orogen_project::TaskName.yml

Returns:

  • ({String=>Array<String>}, nil)

    if some configuration sections changed or got added, the method returns a mapping from the task model name to the list of modified sections. Otherwise, it returns false

Raises:

  • ArgumentError if the file does not exist

  • OroGen::TaskModelNotFound if the task model cannot be found



1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
# File 'lib/orocos/configurations.rb', line 1138

def load_file(file, model = nil)
    if !File.file?(file)
        raise ArgumentError, "#{file} does not exist or is not a file"
    end

    if !model || model.respond_to?(:to_str)
        model_name = model || File.basename(file, '.yml')
        model = loader.task_model_from_name(model_name)
    end

    ConfigurationManager.info "loading configuration file #{file} for #{model.name}"
    conf[model.name] ||= TaskConfigurations.new(model)

    changed_configurations = conf[model.name].load_from_yaml(file)
    ConfigurationManager.info "  #{model.name} available configurations: #{conf[model.name].sections.keys.join(", ")}"
    if changed_configurations.empty?
        return false
    else
        Hash[model.name => changed_configurations]
    end
end

#resolve(task_model_name, conf_names = Array.new, override = false) ⇒ Object

Returns a resolved configuration value for a task model name

Parameters:

  • task_model_name (String)

    the name of the task model

  • conf_names (Array<String>) (defaults to: Array.new)

    the name of the configuration sections

  • override (Boolean) (defaults to: false)

    if true, values that are set by early elements in conf_names will be overriden if set in later elements. Otherwise, ArgumentError is thrown when this happens.

Returns:



1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
# File 'lib/orocos/configurations.rb', line 1266

def resolve(task_model_name, conf_names = Array.new, override = false)
    if task_model_name.respond_to?(:model)
        task_model_name = task_model_name.model.name
    end
    task_conf = conf[task_model_name]
    if conf_names = resolve_requested_configuration_names(task_model_name, task_conf, conf_names)
        task_conf.conf(conf_names, override)
    else Hash.new
    end
end

#resolve_requested_configuration_names(model_name, task_conf, names) ⇒ Object



1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
# File 'lib/orocos/configurations.rb', line 1198

def resolve_requested_configuration_names(model_name, task_conf, names)
    if !task_conf
        if names == ['default'] || names == []
            return
        else
            section_name = names.find { |n| n != 'default' }
            raise TaskConfigurations::SectionNotFound.new(section_name), "no configuration available for #{model_name} (expected #{names.join(", ")})"
        end
    end

    # If no names are given try to figure them out
    if !names || names.empty?
        if(task_conf.sections.size == 1)
            [task_conf.sections.keys.first]
        else
            ["default"]
        end
    else Array(names)
    end
end

#save(task, path, name) ⇒ Object

Saves the configuration for a task and dumps it to a YAML file

This method adds the current configuration of the given task to the existing configuration(s) for the task's model, and saves all of them in a YAML file.

Deprecated.

old signature. One should use the option hash now.

Parameters:

  • task (TaskContext)

    the task whose configuration should be saved

  • path (String)

    the file or directory it should be saved to. If it is a directory, the configuration is saved in a file whose name is based on the task's model name (project_name::TaskName.yml). Otherwise, it is saved in the file. The directories leading to the file must exist.

  • options (Hash) (defaults to: Hash.new)

    a customizable set of options

Options Hash (options):

  • :model (Object) — default: task.model

    the oroGen model used to dump the configuration

  • :name (Object) — default: task.name

    the name of the section that should be created



1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
# File 'lib/orocos/configurations.rb', line 1238

def save(task, path, options = Hash.new)
    if options.respond_to?(:to_str) || !options # for backward compatibility
        options = Hash[:name => options]
    end
    options, find_options = Kernel.filter_options options,
        :name => nil,
        :model => task.model

    model_name = options[:model].name
    task_conf = find_task_configuration_object(task, find_options.merge(:model_name => model_name))
    if !task_conf
        task_conf = conf[model_name] = TaskConfigurations.new(options[:model])
    end
    name = options[:name] || task.name
    task_conf.extract(name, task)
    task_conf.save(name, path, task_model: task.model)
end