Class: Roby::RelationSpace
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
-
#applied ⇒ Object
readonly
The set of klasses on which the relations have been applied.
-
#relations ⇒ Object
readonly
The set of relations included in this relation space.
Instance Method Summary collapse
-
#apply_on(klass) ⇒ Object
This relation applies on klass.
-
#children_of(obj, strict = true, relations = nil) ⇒ Object
Returns the set of objects that are reachable from
objthrough any of the relations. -
#compute_children_of(current, relations) ⇒ Object
Internal implementation method for
children_of. -
#each_relation ⇒ Object
Yields the relations that are defined on this space.
-
#each_root_relation ⇒ Object
Yields the root relations that are defined on this space.
-
#initialize ⇒ RelationSpace
constructor
A new instance of RelationSpace.
-
#relation(relation_name, options = {}, &block) ⇒ Object
Options child_name:: define a
each_#{child_name}method to iterate on the vertex children.
Methods inherited from Module
#define_under, #droby_dump, #planning_library
Constructor Details
#initialize ⇒ RelationSpace
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
#applied ⇒ Object (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 |
#relations ⇒ Object (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_relation ⇒ Object
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_relation ⇒ Object
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 aeach_childmethod) - 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, = {}, &block) = , :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?([:const_name]) graph = const_get([:const_name]) mod = graph.support else graph = [:graph].new "#{self.name}::#{options[:const_name]}", 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([:const_name], graph) relations << graph end mod.class_eval(&block) if block_given? if parent_enumerator = [: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" |