Class: Roby::Queries::PlanObjectMatcher

Inherits:
MatcherBase show all
Includes:
DRoby::V5::Queries::PlanObjectMatcherDumper
Defined in:
lib/roby/queries/plan_object_matcher.rb,
lib/roby/droby/enable.rb

Overview

Predicate that matches characteristics on a plan object

Instance Attribute Summary collapse

Attributes inherited from MatcherBase

#neg_predicates, #predicates

Instance Method Summary collapse

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

#droby_dump

Methods inherited from MatcherBase

#&, #add_neg_predicate, #add_predicate, declare_class_methods, #describe_failed_match, #each, #each_in_plan, #indexed_query?, #match, match_predicate, match_predicates, #negate, #reset, #to_a, #to_set, #|

Constructor Details

#initialize(instance = nil) ⇒ PlanObjectMatcher

Initializes an empty TaskMatcher object



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

def initialize(instance = nil)
    super()

    @instance               = instance
    @model                  = []
    @predicates             = []
    @neg_predicates         = []
    @indexed_predicates     = []
    @indexed_neg_predicates = []
    @owners                 = []
    @parents                = {}
    @children               = {}
    @scope = :global
end

Instance Attribute Details

#childrenHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Per relation list of out-edges that the matched object is expected to have

Returns:

  • (Hash)


40
41
42
# File 'lib/roby/queries/plan_object_matcher.rb', line 40

def children
  @children
end

#indexed_neg_predicatesArray<Symbol> (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set of predicates that should be false on the object, and for which the index maintains a set of objects for which it is true

Returns:

  • (Array<Symbol>)


56
57
58
# File 'lib/roby/queries/plan_object_matcher.rb', line 56

def indexed_neg_predicates
  @indexed_neg_predicates
end

#indexed_predicatesArray<Symbol> (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set of predicates that should be true on the object, and for which the index maintains a set of objects for which it is true

Returns:

  • (Array<Symbol>)


48
49
50
# File 'lib/roby/queries/plan_object_matcher.rb', line 48

def indexed_predicates
  @indexed_predicates
end

#instancenil, Object (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The actual instance that should match

Returns:



12
13
14
# File 'lib/roby/queries/plan_object_matcher.rb', line 12

def instance
  @instance
end

#modelArray<Class> (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A set of models that should be provided by the object

Returns:



19
20
21
# File 'lib/roby/queries/plan_object_matcher.rb', line 19

def model
  @model
end

#ownersArray<DRobyID> (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set of owners that the object should have

Returns:

  • (Array<DRobyID>)


26
27
28
# File 'lib/roby/queries/plan_object_matcher.rb', line 26

def owners
  @owners
end

#parentsHash (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Per-relation list of in-edges that the matched object is expected to have

Returns:

  • (Hash)


33
34
35
# File 'lib/roby/queries/plan_object_matcher.rb', line 33

def parents
  @parents
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.



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

def scope
  @scope
end

Instance Method Details

#===(object) ⇒ Boolean

Tests whether the given object matches this predicate

Parameters:

Returns:

  • (Boolean)


305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/roby/queries/plan_object_matcher.rb', line 305

def ===(object)
    return if instance && object != instance
    return if !model.empty? && !object.fullfills?(model)
    return unless @parents.all? { |s| matches_parent_constraints?(object, s) }
    return unless @children.all? { |s| matches_child_constraints?(object, s) }

    return unless predicates.all? { |pred| object.send(pred) }
    return if neg_predicates.any? { |pred| object.send(pred) }

    if !owners.empty? && !object.owners.all? { |o| owners.include?(o) }
        return false
    end

    true
end

#executable?Object

:method: not_executable

Matches if the object is not executable

See also #executable, PlanObject#executable?



167
# File 'lib/roby/queries/plan_object_matcher.rb', line 167

match_predicates :executable?

#global_scopeObject

Changes the scope of this query

See Also:



102
103
104
105
# File 'lib/roby/queries/plan_object_matcher.rb', line 102

def global_scope
    @scope = :global
    self
end

#global_scope?Boolean

Whether this query is using the global scope

Returns:

  • (Boolean)


108
109
110
# File 'lib/roby/queries/plan_object_matcher.rb', line 108

def global_scope?
    @scope == :global
end

#handle_parent_child_arguments(other_query, relation, relation_options) ⇒ Object

Helper method for #with_child and #with_parent



172
173
174
# File 'lib/roby/queries/plan_object_matcher.rb', line 172

def handle_parent_child_arguments(other_query, relation, relation_options)
    [relation, [other_query.match, relation_options]]
end

#handle_parent_child_match(object, match_spec) ⇒ Object

Helper method for handling parent/child matches in #===



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/roby/queries/plan_object_matcher.rb', line 238

def handle_parent_child_match(object, match_spec)
    relation, matchers = *match_spec
    return false if !relation && object.relations.empty?

    if relation
        matchers.all? do |m, relation_options|
            yield(relation, m, relation_options)
        end
    else
        relations = object.relations
        matchers.all? do |m, relation_options|
            relations.any? do |rel|
                yield(rel, m, relation_options)
            end
        end
    end
end

#local_scopeObject

Changes the scope of this query

See Also:



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

def local_scope
    @scope = :local
    self
end

#local_scope?Boolean

Whether this query is limited to its plan

Returns:

  • (Boolean)

See Also:



95
96
97
# File 'lib/roby/queries/plan_object_matcher.rb', line 95

def local_scope?
    @scope == :local
end

#matches_child_constraints?(object, child_spec) ⇒ Boolean

Returns:

  • (Boolean)


272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/roby/queries/plan_object_matcher.rb', line 272

def matches_child_constraints?(object, child_spec)
    handle_parent_child_match(
        object, child_spec
    ) do |relation, m, relation_options|
        object
            .each_child_object(relation)
            .any? do |child|
                m === child &&
                    (
                        !relation_options ||
                        relation_options === object[child, relation]
                    )
            end
    end
end

#matches_parent_constraints?(object, parent_spec) ⇒ Boolean

Returns:

  • (Boolean)


256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/roby/queries/plan_object_matcher.rb', line 256

def matches_parent_constraints?(object, parent_spec)
    handle_parent_child_match(
        object, parent_spec
    ) do |relation, m, relation_options|
        object
            .each_parent_object(relation)
            .any? do |parent|
                m === parent &&
                    (
                        !relation_options ||
                        relation_options === parent[object, relation]
                    )
            end
    end
end

#not_self_ownedObject

Filters out locally-owned tasks

Matches if the object is owned by the local plan manager.



139
140
141
142
# File 'lib/roby/queries/plan_object_matcher.rb', line 139

def not_self_owned
    add_neg_predicate(:self_owned?)
    self
end

#owned_by(*ids) ⇒ Object

Filters on ownership

Matches if the object is owned by the listed peers.

Use #self_owned to match if it is owned by the local plan manager.



123
124
125
126
# File 'lib/roby/queries/plan_object_matcher.rb', line 123

def owned_by(*ids)
    @owners |= ids
    self
end

#self_ownedObject

Filters locally-owned tasks

Matches if the object is owned by the local plan manager.



131
132
133
134
# File 'lib/roby/queries/plan_object_matcher.rb', line 131

def self_owned
    add_predicate(:self_owned?)
    self
end

#to_sObject



288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/roby/queries/plan_object_matcher.rb', line 288

def to_s
    description =
        if instance
            instance.to_s
        elsif model.size == 1
            model.first.to_s
        else
            "(#{model.map(&:to_s).join(',')})"
        end
    ([description] + predicates.map(&:to_s) +
     neg_predicates.map { |p| "not_#{p}" }).join(".")
end

#with_child(other_query, relation = nil, relation_options = nil) ⇒ Object

Filters based on the object’s children

Matches if this object has at least one child which matches query.

If relation is given, then only the children in this relation are considered. Moreover, relation options can be used to restrict the search even more.

Examples:

parent.depends_on(child)
TaskMatcher.new.
    with_child(TaskMatcher.new.pending) === parent # => true
TaskMatcher.new
.with_child(
    TaskMatcher.new.pending,
    Roby::TaskStructure::Dependency
) === parent # => true
TaskMatcher.new
.with_child(
    TaskMatcher.new.pending,
    Roby::TaskStructure::PlannedBy
) === parent # => false

TaskMatcher.new.
    with_child(TaskMatcher.new.pending,
               Roby::TaskStructure::Dependency,
               roles: ["trajectory_following"]) === parent # => false
parent.depends_on child, role: "trajectory_following"
TaskMatcher.new.
    with_child(TaskMatcher.new.pending,
               Roby::TaskStructure::Dependency,
               roles: ["trajectory_following"]) === parent # => true


210
211
212
213
214
215
216
217
# File 'lib/roby/queries/plan_object_matcher.rb', line 210

def with_child(other_query, relation = nil, relation_options = nil)
    relation, spec = handle_parent_child_arguments(
        other_query, relation, relation_options
    )
    (@children[relation] ||= []) << spec
    @indexed_query = false
    self
end

#with_instance(instance) ⇒ Object

Match an instance explicitely



113
114
115
116
# File 'lib/roby/queries/plan_object_matcher.rb', line 113

def with_instance(instance)
    @instance = instance
    self
end

#with_model(model) ⇒ Object

Filters on the task model

Will match if the task is an instance of model or one of its subclasses.



148
149
150
151
# File 'lib/roby/queries/plan_object_matcher.rb', line 148

def with_model(model)
    @model = Array(model)
    self
end

#with_parent(other_query, relation = nil, relation_options = nil) ⇒ Object

Filters based on the object’s parents

Matches if this object has at least one parent which matches query.

If relation is given, then only the parents in this relation are considered. Moreover, relation options can be used to restrict the search even more.

See examples for #with_child



228
229
230
231
232
233
234
235
# File 'lib/roby/queries/plan_object_matcher.rb', line 228

def with_parent(other_query, relation = nil, relation_options = nil)
    relation, spec = handle_parent_child_arguments(
        other_query, relation, relation_options
    )
    (@parents[relation] ||= []) << spec
    @indexed_query = false
    self
end