Class: Lutaml::UmlRepository::Queries::InheritanceQuery

Inherits:
BaseQuery
  • Object
show all
Defined in:
lib/lutaml/uml_repository/queries/inheritance_query.rb

Overview

Query service for inheritance operations.

Provides methods to navigate class inheritance hierarchies using the inheritance_graph index, which maps parent qualified names to arrays of child qualified names.

Examples:

Getting a class’s parent

query = InheritanceQuery.new(document, indexes)
parent = query.supertype("ModelRoot::Child")

Getting all ancestors

ancestors = query.ancestors("ModelRoot::GrandChild")
# => [Parent, GrandParent, ...]

Getting descendants

descendants = query.descendants("ModelRoot::Parent", max_depth: 2)

Instance Method Summary collapse

Methods inherited from BaseQuery

#initialize

Constructor Details

This class inherits a constructor from Lutaml::UmlRepository::Queries::BaseQuery

Instance Method Details

#ancestors(class_or_qname) ⇒ Array

Get all ancestor classes up to the root.

Returns ancestors in order from immediate parent to root.

Examples:

ancestors = query.ancestors("ModelRoot::GrandChild")
# => [Parent, GrandParent]

Parameters:

  • class_or_qname (Lutaml::Uml::Class, String)

    The class object or qualified name string

Returns:

  • (Array)

    Array of ancestor class objects, ordered from nearest to furthest



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 87

def ancestors(class_or_qname)
  result = []
  current = class_or_qname

  loop do
    parent = supertype(current)
    break unless parent

    result << parent
    current = parent
  end

  result
end

#descendants(class_or_qname, max_depth: nil) ⇒ Array

Get all descendant classes.

Examples:

descendants = query.descendants("ModelRoot::Parent", max_depth: 2)

Parameters:

  • class_or_qname (Lutaml::Uml::Class, String)

    The class object or qualified name string

  • max_depth (Integer, nil) (defaults to: nil)

    Maximum depth to traverse (nil for unlimited)

Returns:

  • (Array)

    Array of descendant class objects



122
123
124
125
126
127
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 122

def descendants(class_or_qname, max_depth: nil)
  qname_string = resolve_qname(class_or_qname)
  return [] unless qname_string

  collect_descendants(qname_string, max_depth, 0)
end

#find_ancestors(class_xmi_id) ⇒ Array

Get all ancestor classes up to the root by class XMI ID.

Parameters:

  • class_xmi_id (String)

    The XMI ID of the class

Returns:

  • (Array)

    Array of ancestor class objects



106
107
108
109
110
111
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 106

def find_ancestors(class_xmi_id)
  qualified_name, _klass = find_class_by_id(class_xmi_id)
  return [] unless qualified_name

  ancestors(qualified_name)
end

#has_circular_inheritance?(class_or_id, visited: Set.new) ⇒ Boolean

Check if a class has circular inheritance.

Parameters:

  • class_or_id (Lutaml::Uml::Class, String)

    The class object, qualified name, or xmi_id

Returns:

  • (Boolean)

    true if circular inheritance detected



190
191
192
193
194
195
196
197
198
199
200
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 190

def has_circular_inheritance?(class_or_id, visited: Set.new)
  qname = resolve_to_qname(class_or_id)
  return false unless qname
  return true if visited.include?(qname)

  visited.add(qname)
  child_qnames = indexes[:inheritance_graph][qname] || []
  child_qnames.any? do |child_qname|
    has_circular_inheritance?(child_qname, visited: visited.dup)
  end
end

#inheritance_tree(class_or_id) ⇒ Hash?

Build inheritance tree for a class.

Parameters:

  • class_or_id (Lutaml::Uml::Class, String)

    The class object, qualified name, or xmi_id

Returns:

  • (Hash, nil)

    Tree structure with :class and :children keys



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 167

def inheritance_tree(class_or_id)
  klass = resolve_by_id_or_qname(class_or_id)
  return nil unless klass

  qname = resolve_qname(klass)
  return nil unless qname

  child_qnames = indexes[:inheritance_graph][qname] || []
  child_trees = child_qnames.filter_map do |child_qname|
    inheritance_tree(child_qname)
  end

  {
    class: klass,
    children: child_trees,
  }
end

#resolve_class(class_or_qname) ⇒ Lutaml::Uml::Class?

Resolve a class or qualified name to a class object.

or nil if not found

Parameters:

  • class_or_qname (Lutaml::Uml::Class, String)

    The class object or qualified name string

Returns:



135
136
137
138
139
140
141
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 135

def resolve_class(class_or_qname)
  if class_or_qname.is_a?(String)
    indexes[:qualified_names][class_or_qname]
  else
    class_or_qname
  end
end

#resolve_qname(class_or_qname) ⇒ String?

Resolve a class or qualified name to a qualified name string.

Parameters:

  • class_or_qname (Lutaml::Uml::Class, String)

    The class object or qualified name string

Returns:

  • (String, nil)

    The qualified name string, or nil if not found



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 148

def resolve_qname(class_or_qname)
  if class_or_qname.is_a?(String) &&
      indexes[:qualified_names].key?(class_or_qname)
    return class_or_qname
  end

  # Search for the class in the index
  qname, _klass = indexes[:qualified_names].find do |_name, entity|
    entity == class_or_qname
  end

  qname.nil? ? nil : qname
end

#subtypes(class_or_qname, recursive: false) ⇒ Array Also known as: find_children

Get direct child classes (subtypes).

Examples:

Direct children only

children = query.subtypes("ModelRoot::Parent", recursive: false)

All descendants

all_descendants = query.subtypes(
"ModelRoot::Parent", recursive: true)

Parameters:

  • class_or_qname (Lutaml::Uml::Class, String)

    The class object or qualified name string

  • recursive (Boolean) (defaults to: false)

    Whether to include all descendants (default: false)

Returns:

  • (Array)

    Array of child class objects



64
65
66
67
68
69
70
71
72
73
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 64

def subtypes(class_or_qname, recursive: false)
  qname_string = resolve_qname(class_or_qname)
  return [] unless qname_string

  if recursive
    descendants(class_or_qname)
  else
    direct_subtypes(qname_string)
  end
end

#supertype(class_or_qname) ⇒ Lutaml::Uml::Class? Also known as: find_parent

Get the direct parent class (supertype).

or nil if no parent

Examples:

parent = query.supertype("ModelRoot::Child")
# Or
parent = query.supertype(child_class)

Parameters:

  • class_or_qname (Lutaml::Uml::Class, String)

    The class object or qualified name string

Returns:



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/lutaml/uml_repository/queries/inheritance_query.rb', line 36

def supertype(class_or_qname)
  klass = resolve_class(class_or_qname)
  return nil unless valid_supertype_target?(klass)

  parent_name = extract_parent_name(klass.generalization)
  return nil unless parent_name
  return nil if parent_name == klass.name

  parent_qname = resolve_parent_qname(class_or_qname, parent_name)
  return nil unless parent_qname

  indexes[:qualified_names][parent_qname]
end