class Lutaml::UmlRepository::Queries::ClassQuery

classes = query.in_package(“ModelRoot::i-UR::urf”)
@example Getting classes in a package
classes = query.find_by_stereotype(“featureType”)
@example Finding classes by stereotype
klass = query.find_by_qname(“ModelRoot::i-UR::urf::Building”)
query = ClassQuery.new(document, indexes)
@example Finding a class by qualified name
using the qualified_names and stereotypes indexes.
Provides methods to find and query classes, data types, and enums
Query service for class/classifier operations.

def find_by_qname(qualified_name_string)

Returns:
  • (Lutaml::Uml::Class, Lutaml::Uml::DataType, ) - Lutaml::Uml::Class, Lutaml::Uml::DataType,

Parameters:
  • qualified_name_string (String) -- The qualified name
def find_by_qname(qualified_name_string)
  if qualified_name_string.nil? || qualified_name_string.empty?
    return nil
  end
  indexes[:qualified_names][qualified_name_string]
end

def find_by_stereotype(stereotype)

Returns:
  • (Array) - Array of class objects with the stereotype

Parameters:
  • stereotype (String) -- The stereotype to search for
def find_by_stereotype(stereotype)
  return [] if stereotype.nil? || stereotype.empty?
  indexes[:stereotypes][stereotype] || []
end

def in_package(package_path_string, recursive: false)

Other tags:
    Example: Recursive query -
    Example: Non-recursive query -

Returns:
  • (Array) - Array of class objects in the package

Parameters:
  • recursive (Boolean) -- Whether to include classes from nested
  • package_path_string (String) -- The package path
def in_package(package_path_string, recursive: false)
  return [] if package_path_string.nil? || package_path_string.empty?
  pkg_to_classes = indexes[:package_to_classes]
  if pkg_to_classes
    in_package_indexed(package_path_string, pkg_to_classes,
                       recursive: recursive)
  else
    in_package_scan(package_path_string, recursive: recursive)
  end
end

def in_package_indexed(package_path_string, pkg_to_classes, recursive:)

O(1) indexed lookup for in_package
def in_package_indexed(package_path_string, pkg_to_classes, recursive:)
  is_absolute = package_path_string.start_with?("::")
  search_segs = package_path_string.split("::").reject(&:empty?)
  results = []
  pkg_to_classes.each do |path, classes|
    results.concat(classes) if indexed_path_matches?(
      path, package_path_string, is_absolute, search_segs, recursive
    )
  end
  results
end

def in_package_scan(package_path_string, recursive:)

Fallback: original O(n) scan
def in_package_scan(package_path_string, recursive:)
  package_path = Lutaml::Uml::PackagePath.new(package_path_string)
  is_absolute = package_path.absolute?
  indexes[:qualified_names].each_value.select do |klass|
    scan_matches_package?(klass, package_path, is_absolute, recursive)
  end
end

def indexed_absolute_match?(path, package_path_string, recursive)

def indexed_absolute_match?(path, package_path_string, recursive)
  if recursive
    path == package_path_string ||
      path.start_with?("#{package_path_string}::")
  else
    path == package_path_string
  end
end

def indexed_path_matches?(path, package_path_string, is_absolute,

def indexed_path_matches?(path, package_path_string, is_absolute,
                          search_segs, recursive)
  if is_absolute
    indexed_absolute_match?(path, package_path_string, recursive)
  else
    indexed_relative_match?(path.split("::"), search_segs, recursive)
  end
end

def indexed_relative_match?(path_segs, search_segs, recursive)

def indexed_relative_match?(path_segs, search_segs, recursive)
  if recursive
    segments_overlap?(path_segs, search_segs)
  else
    segments_end_with?(path_segs, search_segs)
  end
end

def match_absolute_path?(qname, package_path, recursive)

def match_absolute_path?(qname, package_path, recursive)
  qname = Lutaml::Uml::QualifiedName.new(qname)
  if recursive
    qname.package_path.starts_with?(package_path)
  else
    qname.package_path == package_path
  end
end

def match_relative_path?(qname_string, package_path, recursive)

def match_relative_path?(qname_string, package_path, recursive)
  qname = Lutaml::Uml::QualifiedName.new(qname_string)
  class_pkg_segs = qname.package_path.segments
  search_segs = package_path.segments
  if recursive
    segments_overlap?(class_pkg_segs, search_segs)
  else
    segments_end_with?(class_pkg_segs, search_segs)
  end
end

def resolve_qname_for(klass)

def resolve_qname_for(klass)
  indexes[:qualified_names].find { |_, v| v == klass }&.first
end

def scan_matches_package?(klass, package_path, is_absolute, recursive)

def scan_matches_package?(klass, package_path, is_absolute, recursive)
  qname = resolve_qname_for(klass)
  return false unless qname
  if is_absolute
    match_absolute_path?(qname, package_path, recursive)
  else
    match_relative_path?(qname, package_path, recursive)
  end
end

def segments_end_with?(class_segs, search_segs)

def segments_end_with?(class_segs, search_segs)
  class_segs.size >= search_segs.size &&
    class_segs[-search_segs.size..] == search_segs
end

def segments_overlap?(class_segs, search_segs)

def segments_overlap?(class_segs, search_segs)
  (0..(class_segs.size - search_segs.size)).any? do |i|
    class_segs[i, search_segs.size] == search_segs
  end
end