Class: Lutaml::Xsd::SchemaRepository::TypeIndex

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

Overview

Internal helper for indexing and looking up type definitions across multiple schemas

Instance Method Summary collapse

Constructor Details

#initializeTypeIndex

Returns a new instance of TypeIndex.



9
10
11
12
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 9

def initialize
  @index = {}
  @schema_files = {}
end

Instance Method Details

#allHash

Get all indexed types

Returns:

  • (Hash)

    The complete index



136
137
138
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 136

def all
  @index.dup
end

#build_from_schemas(schemas) ⇒ Object

Build index from parsed schemas

Parameters:

  • schemas (Hash)

    Hash of schema_file => Schema object



16
17
18
19
20
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 16

def build_from_schemas(schemas)
  schemas.each do |file_path, schema|
    index_schema(schema, file_path)
  end
end

#clearObject

Clear the index



156
157
158
159
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 156

def clear
  @index.clear
  @schema_files.clear
end

#find(clark_key) ⇒ Hash?

Find a type by Clark notation key

Parameters:

  • clark_key (String)

    The Clark notation key (e.g., “namespaceLocalName”)

Returns:

  • (Hash, nil)

    Type information or nil if not found



91
92
93
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 91

def find(clark_key)
  @index[clark_key]
end

#find_all_in_namespace(namespace) ⇒ Array<Hash>

Get all types in a namespace

Parameters:

  • namespace (String)

    The namespace URI

Returns:

  • (Array<Hash>)

    List of type information hashes



109
110
111
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 109

def find_all_in_namespace(namespace)
  @index.select { |key, _| key.start_with?("{#{namespace}}") }.values
end

#find_by_namespace_and_name(namespace, local_name) ⇒ Hash?

Find a type by namespace and local name

Parameters:

  • namespace (String)

    The namespace URI

  • local_name (String)

    The local type name

Returns:

  • (Hash, nil)

    Type information or nil if not found



99
100
101
102
103
104
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 99

def find_by_namespace_and_name(namespace, local_name)
  return nil if local_name.nil?

  clark_key = build_clark_key(namespace, local_name)
  find(clark_key)
end

#index_inline_complex_types(schema, namespace, file_path) ⇒ Object

Index inline/anonymous complex types defined within elements

Parameters:

  • schema (Schema)

    The schema to index

  • namespace (String)

    The namespace URI

  • file_path (String)

    Path to the schema file



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 63

def index_inline_complex_types(schema, namespace, file_path)
  return unless schema.respond_to?(:element) && schema.element

  elements = schema.element.is_a?(Array) ? schema.element : [schema.element]
  elements.compact.each do |element|
    next unless element.respond_to?(:complex_type) && element.complex_type

    inline_ct = element.complex_type
    # Only index if it doesn't already have a name (truly anonymous)
    next if inline_ct.name

    # Generate a synthetic name based on the element name
    inline_name = "#{element.name}_type"
    clark_key = build_clark_key(namespace, inline_name)
    @index[clark_key] = {
      type: :complex_type,
      definition: inline_ct,
      namespace: namespace,
      schema_file: file_path,
      inline_of_element: element.name,
    }
    @schema_files[file_path] ||= true
  end
end

#index_schema(schema, file_path) ⇒ Object

Index a single schema

Parameters:

  • schema (Schema)

    The schema to index

  • file_path (String)

    Path to the schema file



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 25

def index_schema(schema, file_path)
  return unless schema

  namespace = schema.target_namespace

  # Index simple types
  index_collection(schema.simple_type, namespace, file_path,
                   :simple_type)

  # Index complex types
  index_collection(schema.complex_type, namespace, file_path,
                   :complex_type)

  # Index top-level elements
  index_collection(schema.element, namespace, file_path, :element)

  # Index attribute groups
  index_collection(schema.attribute_group, namespace, file_path,
                   :attribute_group)

  # Index groups
  index_collection(schema.group, namespace, file_path, :group)

  # Index top-level attributes
  index_collection(schema.attribute, namespace, file_path, :attribute)

  # Index inline/anonymous complex types from elements
  index_inline_complex_types(schema, namespace, file_path)

  # NOTE: imported and included schemas are already parsed and available
  # in the processed_schemas cache. We'll index them when build_from_schemas
  # iterates over all schemas in the cache.
end

#statisticsHash

Get statistics about indexed types

Returns:

  • (Hash)

    Statistics



142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 142

def statistics
  type_counts = Hash.new(0)
  @index.each_value do |info|
    type_counts[info[:type]] += 1
  end

  {
    total_types: @index.size,
    by_type: type_counts,
    namespaces: namespace_count,
  }
end

#suggest_similar(namespace, local_name, limit: 5) ⇒ Array<String>

Get suggestions for similar type names (for error messages)

Parameters:

  • namespace (String)

    The namespace URI

  • local_name (String)

    The local type name

  • limit (Integer) (defaults to: 5)

    Maximum number of suggestions

Returns:

  • (Array<String>)

    List of suggested type names



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/lutaml/xsd/schema_repository/type_index.rb', line 118

def suggest_similar(namespace, local_name, limit: 5)
  types_in_namespace = find_all_in_namespace(namespace)
  return [] if types_in_namespace.empty?

  # Simple similarity: check if name is contained or contains the search term
  similar = types_in_namespace.select do |type_info|
    name = type_info[:definition]&.name
    next false unless name

    name.downcase.include?(local_name.downcase) ||
      local_name.downcase.include?(name.downcase)
  end

  similar.filter_map { |info| info[:definition]&.name }.take(limit)
end