Class: Roby::Queries::Query

Inherits:
TaskMatcher show all
Includes:
Enumerable, DRoby::V5::Queries::QueryDumper
Defined in:
lib/roby/queries/query.rb,
lib/roby/droby/enable.rb

Overview

A query is a TaskMatcher that applies on a plan. It should, in general, be preferred to TaskMatcher as it uses task indexes to be more efficient.

Queries cache their result. I.e. once #each has been called to get the query results, the query will always return the same results until #reset has been called.

Instance Attribute Summary collapse

Attributes inherited from TaskMatcher

#arguments

Attributes inherited from PlanObjectMatcher

#children, #indexed_neg_predicates, #indexed_predicates, #instance, #model, #owners, #parents

Attributes inherited from MatcherBase

#neg_predicates, #predicates

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DRoby::V5::Queries::QueryDumper

#droby_dump

Methods included from Enumerable

#empty?

Methods inherited from TaskMatcher

#abstract?, #find_event, #handle_parent_child_arguments, #indexed_query?, #method_missing, #respond_to_missing?, #to_s, #which_fullfills, #with_arguments, #with_model_arguments

Methods included from DRoby::V5::Queries::TaskMatcherDumper

#droby_dump

Methods inherited from PlanObjectMatcher

#executable?, #filter, #handle_parent_child_arguments, #handle_parent_child_match, #indexed_query?, match_predicate, #not_self_owned, #owned_by, #self_owned, #to_s, #with_child, #with_instance, #with_model, #with_parent

Methods included from DRoby::V5::Queries::PlanObjectMatcherDumper

#droby_dump

Methods inherited from MatcherBase

#&, declare_class_methods, #describe_failed_match, #indexed_query?, #match, match_predicate, match_predicates, #negate, #|

Constructor Details

#initialize(plan = nil) ⇒ Query

Create a query object on the given plan



14
15
16
17
18
19
20
# File 'lib/roby/queries/query.rb', line 14

def initialize(plan = nil)
    @scope = :global
    @plan = plan
    super()
    @plan_predicates = Set.new
    @neg_plan_predicates = Set.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Roby::Queries::TaskMatcher

Instance Attribute Details

#neg_plan_predicatesObject (readonly)

The set of predicates of Plan which must return false for #=== to return true.



91
92
93
# File 'lib/roby/queries/query.rb', line 91

def neg_plan_predicates
  @neg_plan_predicates
end

#planObject

The plan this query acts on



11
12
13
# File 'lib/roby/queries/query.rb', line 11

def plan
  @plan
end

#plan_predicatesObject (readonly)

The set of predicates of Plan which must return true for #=== to return true



88
89
90
# File 'lib/roby/queries/query.rb', line 88

def plan_predicates
  @plan_predicates
end

#scopeObject (readonly)

Search scope for queries on transactions. If equal to :local, the query will apply only on the scope of the searched transaction, otherwise it applies on a virtual plan that is the result of the transaction stack being applied.

The default is :global.

See #local_scope and #global_scope



34
35
36
# File 'lib/roby/queries/query.rb', line 34

def scope
  @scope
end

Class Method Details

.match_plan_predicates(names) ⇒ Object

For each name in names, define the #name and #not_name methods on Query objects. When one of these methods is called on a Query object, plan.name?(task) must return true (resp. false) for the task to match.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/roby/queries/query.rb', line 98

def match_plan_predicates(names)
    names.each do |name, predicate_name|
        predicate_name ||= name
        class_eval "        def \#{name}\n            if neg_plan_predicates.include?(:\#{predicate_name})\n                raise ArgumentError, \"trying to match (\#{name} & !\#{name})\"\n            end\n            plan_predicates << :\#{predicate_name}\n            self\n        end\n        def not_\#{name}\n            if plan_predicates.include?(:\#{predicate_name})\n                raise ArgumentError, \"trying to match (\#{name} & !\#{name})\"\n            end\n            neg_plan_predicates << :\#{predicate_name}\n            self\n        end\n        EOD\n    end\nend\n", __FILE__, __LINE__+1

Instance Method Details

#===(task) ⇒ Object

True if task matches the query. Call #result_set to have the set of tasks which match in the given plan.



163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/roby/queries/query.rb', line 163

def ===(task)
    for pred in plan_predicates
        return unless plan.send(pred, task)
    end
    for neg_pred in neg_plan_predicates
        return if plan.send(neg_pred, task)
    end

    return unless super

    true
end

#each(&block) ⇒ Object

Iterates on all the tasks in the given plan which match the query

This set is cached, i.e. #each will yield the same task set until #reset is called.



180
181
182
183
# File 'lib/roby/queries/query.rb', line 180

def each(&block)
    return enum_for(__method__) if !block_given?
    plan.query_each(result_set, &block)
end

#global_scopeObject

Changes the scope of this query. See #scope.



42
43
44
45
# File 'lib/roby/queries/query.rb', line 42

def global_scope
    @scope = :global
    self
end

#indexed_sets(index) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/roby/queries/query.rb', line 59

def indexed_sets(index)
    positive_sets, negative_sets = super

    if plan_predicates.include?(:mission_task?)
        positive_sets << plan.mission_tasks
    elsif neg_plan_predicates.include?(:mission_task?)
        negative_sets << plan.mission_tasks
    end

    if plan_predicates.include?(:permanent_task?)
        positive_sets << plan.permanent_tasks
    elsif neg_plan_predicates.include?(:permanent_task?)
        negative_sets << plan.permanent_tasks
    end
    return positive_sets, negative_sets
end

#local_scopeObject

Changes the scope of this query. See #scope.



37
38
39
40
# File 'lib/roby/queries/query.rb', line 37

def local_scope
    @scope = :local
    self
end

#mission_task?Object

:method: not_permanent

Filters out permanent tasks

Matches tasks in plan that are not declared as permanent tasks



149
# File 'lib/roby/queries/query.rb', line 149

match_plan_predicates mission: :mission_task?

#queryObject



22
23
24
# File 'lib/roby/queries/query.rb', line 22

def query
    self
end

#resetObject

Reinitializes the cached query result.

Queries cache their result, i.e. #each will always return the same task set. #reset makes sure that the next call to #each will return the same value.



81
82
83
84
# File 'lib/roby/queries/query.rb', line 81

def reset
    @result_set = nil
    self
end

#result_setObject

The set of tasks which match in plan. This is a cached value, so use #reset to actually recompute this set.



55
56
57
# File 'lib/roby/queries/query.rb', line 55

def result_set
    @result_set ||= plan.query_result_set(self)
end

#roots(relation) ⇒ Object

Filters tasks which have no parents in the query itself.

Will filter out tasks which have parents in relation that are included in the query result.



156
157
158
159
# File 'lib/roby/queries/query.rb', line 156

def roots(relation)
    @result_set = plan.query_roots(result_set, relation)
    self
end