Class: Lutaml::Uml::InheritanceWalker

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/uml/inheritance_walker.rb

Overview

Service class for safely walking UML generalization chains.

Walks from a class up through its generalization hierarchy (parent classes), collecting information about each ancestor. Supports cycle detection to prevent infinite loops in malformed models.

Examples:

walker = InheritanceWalker.new(repository)
walker.walk(klass) do |ancestor, level|
  puts "#{'-' * level} #{ancestor.name}"
end

Instance Method Summary collapse

Constructor Details

#initialize(repository) ⇒ InheritanceWalker

Returns a new instance of InheritanceWalker.

Parameters:

  • repository (#supertype_of)

    Object responding to #supertype_of(class)



18
19
20
21
# File 'lib/lutaml/uml/inheritance_walker.rb', line 18

def initialize(repository)
  @repository = repository
  @visited = Set.new
end

Instance Method Details

#ancestors_of(klass) ⇒ Array<Lutaml::Uml::Class>

Get all ancestors of a class in order (immediate parent first).

Parameters:

Returns:



59
60
61
62
63
# File 'lib/lutaml/uml/inheritance_walker.rb', line 59

def ancestors_of(klass)
  result = []
  walk(klass) { |ancestor, _level| result << ancestor }
  result
end

#supertype_of(klass) ⇒ Lutaml::Uml::Class?

Get the direct supertype (immediate parent) of a class.

Parameters:

Returns:



51
52
53
# File 'lib/lutaml/uml/inheritance_walker.rb', line 51

def supertype_of(klass)
  @repository.supertype_of(klass)
end

#walk(klass) {|ancestor, level| ... } ⇒ Array<[klass, level]>

Walk the generalization chain from a starting class.

Examples:

walker.walk(D.class) do |parent, level|
  puts "#{'  ' * (level - 1)}Parent #{level}: #{parent.name}"
end

Parameters:

Yields:

  • (ancestor, level)

    Yields each ancestor class and its depth (1-based)

Returns:

  • (Array<[klass, level]>)

    Array of [ancestor_class, level] pairs in visiting order



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/lutaml/uml/inheritance_walker.rb', line 33

def walk(klass)
  return [] unless klass.respond_to?(:generalization) && klass.generalization

  ancestors = []
  @visited.clear
  collect_ancestors(klass, ancestors)
  ancestors.reverse_each.with_index(1) do |ancestor, level|
    break if @visited.include?(ancestor.xmi_id)
    @visited.add(ancestor.xmi_id)
    yield(ancestor, level) if block_given?
  end
  ancestors.reverse_each.with_index(1)
end