Class: Lutaml::UmlRepository::Queries::PackageQuery

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

Overview

Query service for package operations.

Provides methods to find, list, and navigate package hierarchies using the package_paths index for efficient lookups.

Examples:

Finding a package by path

query = PackageQuery.new(document, indexes)
package = query.find_by_path("ModelRoot::i-UR::urf")

Listing child packages

packages = query.list("ModelRoot::i-UR", recursive: false)

Building a package tree

tree = query.tree("ModelRoot", 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

#find_by_path(path_string) ⇒ Lutaml::Uml::Package, ...

Find a single package by its path.

Supports multiple search strategies:

  1. Exact full path match (e.g., “ModelRoot::i-UR::uro”)

  2. Simple name match (e.g., “uro”)

  3. Partial path match (e.g., “i-UR::uro”)

Examples:

Exact path

package = query.find_by_path("ModelRoot::i-UR::urf")

Simple name

package = query.find_by_path("urf")

Partial path

package = query.find_by_path("i-UR::urf")

Parameters:

  • path_string (String)

    The package path (e.g., “ModelRoot::i-UR”)

Returns:



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/lutaml/uml_repository/queries/package_query.rb', line 42

def find_by_path(path_string) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
  return nil if path_string.nil? || path_string.empty?

  # Strategy 1: Try exact match first (most common case)
  exact_match = indexes[:package_paths][path_string.to_s]
  return exact_match if exact_match

  # Strategy 2 & 3: Search for simple name or partial path match
  search_segments = path_string.to_s.split("::")
  matches = []

  indexes[:package_paths].each do |full_path, package|
    full_segments = full_path.to_s.split("::")

    # Simple name match: last segment matches
    if search_segments.length == 1
      matches << package if full_segments.last == search_segments.first
    # Partial path match: ends with search path
    elsif full_segments.last(search_segments.length) == search_segments
      matches << package
    end
  end

  # Return single match, or nil if no match or ambiguous
  matches.length == 1 ? matches.first : nil
end

#list(parent_path_string, recursive: false) ⇒ Array<Lutaml::Uml::Package>

List packages at a specific path.

Examples:

Non-recursive listing

packages = query.list("ModelRoot::i-UR", recursive: false)
# Returns only direct children of i-UR

Recursive listing

packages = query.list("ModelRoot", recursive: true)
# Returns all packages under ModelRoot

Parameters:

  • parent_path_string (String)

    The parent package path

  • recursive (Boolean) (defaults to: false)

    Whether to include nested packages recursively (default: false)

Returns:



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/lutaml/uml_repository/queries/package_query.rb', line 82

def list(parent_path_string, recursive: false) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
  return [] if parent_path_string.nil? || parent_path_string.empty?

  parent_path = Lutaml::Uml::PackagePath.new(parent_path_string.to_s)
  results = []

  indexes[:package_paths].each do |path_string, package|
    path = Lutaml::Uml::PackagePath.new(path_string)

    # Skip the parent itself
    next if path == parent_path

    # Check if this path is under the parent
    next unless path.starts_with?(parent_path)

    if recursive
      # Include all descendants
      results << package
    elsif path.depth == parent_path.depth + 1
      # Include only direct children (depth = parent_depth + 1)
      results << package
    end
  end

  results
end

#tree(root_path_string, max_depth: nil) ⇒ Hash?

Build a hierarchical tree structure of packages.

Examples:

tree = query.tree("ModelRoot::i-UR", max_depth: 2)
# => {
#   name: "i-UR",
#   path: "ModelRoot::i-UR",
#   classes_count: 0,
#   diagrams_count: 0,
#   children: [
#     {
#       name: "urf",
#       path: "ModelRoot::i-UR::urf",
#       classes_count: 15,
#       diagrams_count: 2,
#       children: []
#     }
#   ]
# }

Parameters:

  • root_path_string (String)

    The root package path to start from

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

    Maximum depth to traverse (nil for unlimited)

Returns:

  • (Hash, nil)

    Tree structure with package information, or nil if root not found



133
134
135
136
137
138
139
140
# File 'lib/lutaml/uml_repository/queries/package_query.rb', line 133

def tree(root_path_string, max_depth: nil)
  return nil if root_path_string.nil? || root_path_string.empty?

  root_package = find_by_path(root_path_string.to_s)
  return nil unless root_package

  build_tree_node(root_path_string.to_s, root_package, max_depth, 0)
end