Class: Lutaml::Xsd::TypeSearcher

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/xsd/type_searcher.rb

Overview

Search engine for finding types in a schema repository Supports searching by name, documentation, or both with relevance ranking

Defined Under Namespace

Classes: SearchResult

Instance Method Summary collapse

Constructor Details

#initialize(repository) ⇒ TypeSearcher

Initialize searcher with a repository

Parameters:



46
47
48
49
# File 'lib/lutaml/xsd/type_searcher.rb', line 46

def initialize(repository)
  @repository = repository
  @type_index = repository.instance_variable_get(:@type_index)
end

Instance Method Details

#search(query, in_field: "both", namespace: nil, category: nil, limit: 20) ⇒ Array<SearchResult>

Search for types matching the query

Parameters:

  • query (String)

    The search query

  • in_field (String) (defaults to: "both")

    Where to search: “name”, “documentation”, or “both”

  • namespace (String, nil) (defaults to: nil)

    Filter by namespace URI

  • category (String, Symbol, nil) (defaults to: nil)

    Filter by category

  • limit (Integer) (defaults to: 20)

    Maximum number of results to return

Returns:



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/lutaml/xsd/type_searcher.rb', line 58

def search(query, in_field: "both", namespace: nil, category: nil,
limit: 20)
  return [] if query.nil? || query.strip.empty?

  query = query.strip.downcase
  results = []

  # Get all types from the index
  all_types = @type_index.all

  all_types.each_value do |type_info|
    # Apply namespace filter
    next if namespace && type_info[:namespace] != namespace

    # Apply category filter
    if category
      category_sym = category.to_sym
      next if type_info[:type] != category_sym
    end

    # Extract type information
    definition = type_info[:definition]
    next unless definition&.name

    local_name = definition.name
    type_namespace = type_info[:namespace]
    type_category = type_info[:type]
    schema_file = type_info[:schema_file]

    # Build qualified name
    prefix = @repository.namespace_to_prefix(type_namespace)
    qualified_name = prefix ? "#{prefix}:#{local_name}" : local_name

    # Extract documentation
    documentation = extract_documentation(definition)

    # Calculate relevance score based on search field
    score_result = calculate_relevance(
      query: query,
      local_name: local_name,
      documentation: documentation,
      in_field: in_field,
    )

    # Skip if no match
    next if score_result[:score].zero?

    # Create search result
    results << SearchResult.new(
      qualified_name: qualified_name,
      local_name: local_name,
      namespace: type_namespace,
      category: type_category,
      schema_file: schema_file,
      documentation: documentation,
      relevance_score: score_result[:score],
      match_type: score_result[:match_type],
      definition: definition,
    )
  end

  # Sort by relevance score (highest first), then by name
  results.sort! do |a, b|
    if a.relevance_score == b.relevance_score
      a.qualified_name <=> b.qualified_name
    else
      b.relevance_score <=> a.relevance_score
    end
  end

  # Apply limit
  results.take(limit)
end