Class: Roby::RelationSpace

Inherits:
Module show all
Defined in:
lib/roby/relations.rb

Overview

A relation space is a module which handles a list of relations and applies them to a set of classes. In this context, a relation is both a Ruby module which gets included in the classes this space is applied on, and a RelationGraph object which holds the object graphs.

See the files in roby/relations to see definitions of new relations

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Module

#define_under, #droby_dump, #planning_library

Constructor Details

#initializeRelationSpace

Returns a new instance of RelationSpace.



383
384
385
386
387
# File 'lib/roby/relations.rb', line 383

def initialize
    @relations = Array.new
    @applied   = Array.new
    super
end

Instance Attribute Details

#appliedObject (readonly)

The set of klasses on which the relations have been applied



381
382
383
# File 'lib/roby/relations.rb', line 381

def applied
  @applied
end

#relationsObject (readonly)

The set of relations included in this relation space



379
380
381
# File 'lib/roby/relations.rb', line 379

def relations
  @relations
end

Instance Method Details

#apply_on(klass) ⇒ Object

This relation applies on klass. It mainly means that a relation defined on this RelationSpace will define the relation-access methods and include its support module (if any) in klass.



392
393
394
395
396
397
398
399
# File 'lib/roby/relations.rb', line 392

def apply_on(klass)
    klass.include DirectedRelationSupport
    each_relation do |graph|
  klass.include graph.support
    end

    applied << klass
end

#children_of(obj, strict = true, relations = nil) ⇒ Object

Returns the set of objects that are reachable from obj through any of the relations. Note that b will be included in the result if there is an edge obj => a in one relation and another edge a => b in another relation

If strict is true, obj is not included in the returned set



421
422
423
424
425
# File 'lib/roby/relations.rb', line 421

def children_of(obj, strict = true, relations = nil)
    set = compute_children_of([obj].to_value_set, relations || self.relations)
    set.delete(obj) if strict
    set
end

#compute_children_of(current, relations) ⇒ Object

Internal implementation method for children_of



428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/roby/relations.rb', line 428

def compute_children_of(current, relations) # :nodoc:
    old_size = current.size
    for rel in relations
  next if (rel.parent && relations.include?(rel.parent))

  components = rel.generated_subgraphs(current, false)
  for c in components
      current.merge c
  end
    end

    if current.size == old_size
  return current
    else
  return compute_children_of(current, relations)
    end
end

#each_relationObject

Yields the relations that are defined on this space



402
403
404
405
406
# File 'lib/roby/relations.rb', line 402

def each_relation
    for rel in relations
  yield(rel)
    end
end

#each_root_relationObject

Yields the root relations that are defined on this space



409
410
411
412
413
# File 'lib/roby/relations.rb', line 409

def each_root_relation
    for rel in relations
  yield(rel) unless rel.parent
    end
end

#relation(relation_name, options = {}, &block) ⇒ Object

Options

child_name

define a each_#{child_name} method to iterate on the vertex children. Uses the relation name by default (a Child relation would define a each_child method)

parent_name

define a each_#{parent_name} method to iterate on the vertex parents. If none is given, no method is defined

subsets

a list of subgraphs. See RelationGraph#superset_of

noinfo

if the relation embeds some additional information. If true, the child iterator method (each_#{child_name}) will yield (child, info) instead of only child [false]

graph

the relation graph class

distribute

if true, the relation can be seen by remote peers [true]

single_child

if the relations accepts only one child per vertex [false]. If this option is set, defines a #{child_name} method which returns the only child or nil



470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
# File 'lib/roby/relations.rb', line 470

def relation(relation_name, options = {}, &block)
    options = validate_options options,
    :child_name => relation_name.to_s.underscore,
    :const_name => relation_name,
    :parent_name => nil,
    :subsets => ValueSet.new,
    :noinfo => false,
    :graph => RelationGraph,
    :distribute => true,
    :dag => true,
    :single_child => false,
    :weak => false

    # Check if this relation is already defined. If it is the case, reuse it.
    # This is needed mostly by the reloading code
    if const_defined?(options[:const_name])
  graph = const_get(options[:const_name])
  mod   = graph.support

    else
  graph = options[:graph].new "#{self.name}::#{options[:const_name]}", options
  mod = Module.new do
      singleton_class.class_eval do
    define_method("__r_#{relation_name}__") { graph }
      end
      class_eval "@@__r_#{relation_name}__ = __r_#{relation_name}__"
  end
  const_set(options[:const_name], graph)
  relations << graph
    end

    mod.class_eval(&block) if block_given?

    if parent_enumerator = options[:parent_name]
  mod.class_eval "  def each_\#{parent_enumerator}(&iterator)\n      self.each_parent_object(@@__r_\#{relation_name}__, &iterator)\n  end\n  EOD\n    end\n\n    if options[:noinfo]\n  mod.class_eval <<-EOD\n  def each_\#{options[:child_name]}\n      each_child_object(@@__r_\#{relation_name}__) { |child| yield(child) }\n  end\n  def find_\#{options[:child_name]}\n      each_child_object(@@__r_\#{relation_name}__) do |child|\n    return child if yield(child)\n      end\n      nil\n  end\n  EOD\n    else\n  mod.class_eval <<-EOD\n  def each_\#{options[:child_name]}\n      each_child_object(@@__r_\#{relation_name}__) do |child|\n    yield(child, self[child, @@__r_\#{relation_name}__])\n      end\n  end\n  def find_\#{options[:child_name]}\n      each_child_object(@@__r_\#{relation_name}__) do |child|\n    return child if yield(child, self[child, @@__r_\#{relation_name}__])\n      end\n      nil\n  end\n  EOD\n    end\n    mod.class_eval <<-EOD\n    def add_\#{options[:child_name]}(to, info = nil)\n  add_child_object(to, @@__r_\#{relation_name}__, info)\n  self\n    end\n    def remove_\#{options[:child_name]}(to)\n  remove_child_object(to, @@__r_\#{relation_name}__)\n  self\n    end\n    EOD\n\n    if options[:single_child]\n  mod.class_eval <<-EOD\n  def \#{options[:child_name]}\n      each_child_object(@@__r_\#{relation_name}__) do |child_task|\n    return child_task\n      end\n      nil\n  end\n  EOD\n    end\n\n    graph.support = mod\n    applied.each { |klass| klass.include mod }\n\n    graph\nend\n"