Class: Roby::Actions::Models::MethodAction

Inherits:
Action show all
Includes:
DRoby::V5::Actions::Models::MethodActionDumper
Defined in:
lib/roby/actions/models/method_action.rb,
lib/roby/droby/enable.rb

Overview

Action defined by a method on an Interface

Defined Under Namespace

Classes: InvalidReturnedType

Constant Summary

Constants inherited from Action

Action::Void, Action::VoidClass

Instance Attribute Summary collapse

Attributes inherited from Action

#arguments, #doc, #name, #returned_type

Instance Method Summary collapse

Methods included from DRoby::V5::Actions::Models::MethodActionDumper

#proxy

Methods included from DRoby::V5::Actions::Models::InterfaceActionDumper

#droby_dump!, #proxy_from_existing

Methods inherited from Action

#advanced, #as_plan, #each_arg, #find_arg, #has_arg?, #has_required_arg?, #initialize_copy, #new, #normalize_arguments, #optional_arg, #overloads, #pretty_print, #pretty_print_arguments, #required_arg, #returned_task_type, #returns, #to_action, #to_action_model, #validate_can_overload

Methods included from DRoby::V5::Actions::Models::ActionDumper

#droby_dump, #droby_dump!, #proxy, #proxy!

Constructor Details

#initialize(action_interface_model, doc = nil) ⇒ MethodAction

Returns a new instance of MethodAction.



37
38
39
40
# File 'lib/roby/actions/models/method_action.rb', line 37

def initialize(action_interface_model, doc = nil)
    super(doc)
    @action_interface_model = action_interface_model
end

Instance Attribute Details

#action_interface_modelObject

The action interface on which this action is defined



35
36
37
# File 'lib/roby/actions/models/method_action.rb', line 35

def action_interface_model
  @action_interface_model
end

Instance Method Details

#==(other) ⇒ Object



42
43
44
45
46
# File 'lib/roby/actions/models/method_action.rb', line 42

def ==(other)
    other.kind_of?(self.class) &&
        other.action_interface_model == action_interface_model &&
        other.name == name
end

#detect_unknown_arguments(arguments) ⇒ Object

Raises:

  • (ArgumentError)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/roby/actions/models/method_action.rb', line 70

def detect_unknown_arguments(arguments)
    known_arguments = self.arguments.map(&:name).map(&:to_sym)
    invalid_arg = arguments
                  .each_key.find { |k| !known_arguments.include?(k) }
    return unless invalid_arg

    expected_arguments =
        if known_arguments.empty?
            "The action accepts no arguments"
        else
            "The action accepts the following arguments: "\
            "#{known_arguments.sort.join(', ')}"
        end

    raise ArgumentError,
          "unknown argument '#{invalid_arg}' given to action #{self}. "\
          "#{expected_arguments}"
end

#instanciate(plan, arguments = {}) ⇒ Object

Instanciate this action on the given plan



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/roby/actions/models/method_action.rb', line 49

def instanciate(plan, arguments = {})
    arguments = arguments.transform_keys(&:to_sym)
    detect_unknown_arguments(arguments)
    required_and_default_arguments(arguments)

    action_interface = action_interface_model.new(plan)
    result =
        if self.arguments.empty?
            action_interface.send(name)
        else
            action_interface.send(name, **arguments)
        end

    result = validate_returned_task_type(result)
    plan.add(result)

    # Make the planning task inherit the model/argument flags
    update_planning_task(result)
    result
end

#plan_pattern(job_id: nil, **arguments) ⇒ Object

Returns the plan pattern that will deploy this action on the plan



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/roby/actions/models/method_action.rb', line 144

def plan_pattern(job_id: nil, **arguments)
    job_argument =
        if job_id
            { job_id: job_id }
        else
            {}
        end

    planner = Roby::Actions::Task.new(
        action_model: self,
        action_arguments: arguments,
        **job_argument
    )
    planner.planning_result_task
end

#rebind(action_interface_model) ⇒ Action

Create a new action model that is bound to a different interface model

Parameters:

  • action_interface_model (Models::Interface)

    the new model

  • force (Boolean)

    the rebind will happen only if the new interface model is a submodel of the current one. If force is true, it will be done regardless.

Returns:

  • (Action)

    the rebound action model



135
136
137
138
139
140
141
# File 'lib/roby/actions/models/method_action.rb', line 135

def rebind(action_interface_model)
    rebound = dup
    if action_interface_model <= self.action_interface_model
        rebound.action_interface_model = action_interface_model
    end
    rebound
end

#required_and_default_arguments(arguments) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/roby/actions/models/method_action.rb', line 89

def required_and_default_arguments(arguments)
    self.arguments.each do |arg|
        arg_sym = arg.name.to_sym
        next if arguments.key?(arg_sym)

        if arg.required
            raise ArgumentError,
                  "required argument '#{arg.name}' not given to action "\
                  "#{self}"
        elsif arg.default
            arguments[arg_sym] = arg.default
        end
    end
end

#to_sObject



160
161
162
# File 'lib/roby/actions/models/method_action.rb', line 160

def to_s
    "#{action_interface_model.name}.#{name}"
end

#update_planning_task(result) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/roby/actions/models/method_action.rb', line 116

def update_planning_task(result)
    return unless (planning_task = result.planning_task)

    if planning_task.respond_to?(:action_model=)
        planning_task.action_model ||= self
    end
    if planning_task.respond_to?(:action_arguments=)
        planning_task.action_arguments ||= arguments
    end
    nil
end

#validate_returned_task_type(result) ⇒ Object

Raises:

  • (e)


104
105
106
107
108
109
110
111
112
113
114
# File 'lib/roby/actions/models/method_action.rb', line 104

def validate_returned_task_type(result)
    result = result.as_plan
    return result if result.fullfills?(returned_task_type)

    e = InvalidReturnedType.new(
        action_interface_model, name, result, returned_task_type
    )

    raise e, "action '#{self}' was expected to return a task of "\
             "type #{returned_task_type}, but returned #{result}"
end