Class: Lutaml::Model::GlobalContext

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/lutaml/model/global_context.rb

Overview

GlobalContext provides global state management and context coordination.

Architecture Overview:

  • Register: User-facing API for type registration (primary user interface)
  • GlobalRegister: User-facing API for register management
  • GlobalContext: Internal coordinator for context management

Users typically interact with Register and GlobalRegister. GlobalContext is used internally and for advanced use cases.

This class:

  • Manages named contexts via ContextRegistry
  • Provides type resolution via CachedTypeResolver
  • Manages imports via ImportRegistry
  • Manages format-specific registries (e.g., XML namespace registry)
  • Provides reset! for test isolation
  • Provides with_context for scoped operations

Examples:

Test isolation

GlobalContext.reset!  # Clears ALL caches and non-default contexts

Thread-safe context switching

GlobalContext.with_context(:my_app) do
  # Code here uses :my_app as default context
end

See Also:

Constant Summary collapse

THREAD_CONTEXT_KEY =

Thread-local storage for context switching

:lutaml_model_context

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGlobalContext

Initialize the GlobalContext with default components.



59
60
61
62
63
64
65
66
67
68
# File 'lib/lutaml/model/global_context.rb', line 59

def initialize
  @registry = ContextRegistry.new
  @resolver = CachedTypeResolver.new(delegate: TypeResolver)
  @imports = ImportRegistry.new
  @format_registries = {}
  @default_context_id = :default
  @namespace_register_map = {} # namespace_uri => register_id
  @mutex = Mutex.new
  @context_generation = 0
end

Instance Attribute Details

#default_context_idSymbol

Returns The current default context ID.

Returns:

  • (Symbol)

    The current default context ID



47
48
49
# File 'lib/lutaml/model/global_context.rb', line 47

def default_context_id
  @default_context_id
end

#format_registriesHash{Symbol => Object} (readonly)

Returns Format-specific registries.

Returns:

  • (Hash{Symbol => Object})

    Format-specific registries



53
54
55
# File 'lib/lutaml/model/global_context.rb', line 53

def format_registries
  @format_registries
end

#importsImportRegistry (readonly)

Returns The import registry.

Returns:



44
45
46
# File 'lib/lutaml/model/global_context.rb', line 44

def imports
  @imports
end

#namespace_register_mapHash{String => Symbol} (readonly)

Returns Namespace URI to register ID mapping.

Returns:

  • (Hash{String => Symbol})

    Namespace URI to register ID mapping



50
51
52
# File 'lib/lutaml/model/global_context.rb', line 50

def namespace_register_map
  @namespace_register_map
end

#registryContextRegistry (readonly)

Returns The context registry.

Returns:



38
39
40
# File 'lib/lutaml/model/global_context.rb', line 38

def registry
  @registry
end

#resolverCachedTypeResolver (readonly)

Returns The cached type resolver.

Returns:



41
42
43
# File 'lib/lutaml/model/global_context.rb', line 41

def resolver
  @resolver
end

Instance Method Details

#bind_register_to_namespace(register_id, namespace_uri) ⇒ void

This method returns an undefined value.

Bind a register to a namespace URI.

This enables reverse lookup: given a namespace URI, find the register.

Parameters:

  • register_id (Symbol)

    The register ID

  • namespace_uri (String)

    The namespace URI



294
295
296
297
298
# File 'lib/lutaml/model/global_context.rb', line 294

def bind_register_to_namespace(register_id, namespace_uri)
  @mutex.synchronize do
    @namespace_register_map[namespace_uri] = register_id.to_sym
  end
end

#clear_cachesvoid

This method returns an undefined value.

Clear caches only (keep registrations).



214
215
216
217
218
# File 'lib/lutaml/model/global_context.rb', line 214

def clear_caches
  @resolver.clear_all_caches
  Register.clear_resolve_cache
  Transform.clear_cache!
end

#clear_format_registry!(format) ⇒ void

This method returns an undefined value.

Clear a specific format registry.

Parameters:

  • format (Symbol)

    The format



248
249
250
251
# File 'lib/lutaml/model/global_context.rb', line 248

def clear_format_registry!(format)
  reg = @format_registries[format]
  reg&.clear! if reg.is_a?(FormatRegistry)
end

#clear_xml_namespace_registry!void

This method returns an undefined value.

Backward-compatible clear for XML namespace registry.



264
265
266
# File 'lib/lutaml/model/global_context.rb', line 264

def clear_xml_namespace_registry!
  clear_format_registry!(:xml)
end

#context(id = nil) ⇒ TypeContext

Get a context by ID, or the default if no ID provided.

Parameters:

  • id (Symbol, nil) (defaults to: nil)

    The context ID (optional)

Returns:



103
104
105
106
107
108
109
# File 'lib/lutaml/model/global_context.rb', line 103

def context(id = nil)
  if id
    @registry.lookup(id.to_sym)
  else
    default_context
  end
end

#context_generationInteger

Bumped whenever a named context is registered, replaced, unregistered, or the registry is reset. Callers that cache a resolution keyed on a context ID compare this generation to invalidate — a replaced context under the same ID must not keep answering from a stale cache.

Returns:

  • (Integer)


77
78
79
# File 'lib/lutaml/model/global_context.rb', line 77

def context_generation
  @context_generation
end

#create_context(id:, registry: nil, fallback_to: [], substitutions: []) ⇒ TypeContext

Create and register a new context.

Parameters:

  • id (Symbol)

    The context ID

  • registry (TypeRegistry, nil) (defaults to: nil)

    Optional type registry

  • fallback_to (Array<Symbol, TypeContext>) (defaults to: [])

    Fallback contexts

  • substitutions (Array<TypeSubstitution, Hash>) (defaults to: [])

    Type substitutions

Returns:



151
152
153
154
155
156
157
158
159
160
# File 'lib/lutaml/model/global_context.rb', line 151

def create_context(id:, registry: nil, fallback_to: [], substitutions: [])
  context = @registry.create(
    id: id,
    registry: registry,
    fallback_to: fallback_to,
    substitutions: substitutions,
  )
  @context_generation += 1
  context
end

#default_contextTypeContext

Get the current default context.

Returns:



84
85
86
87
# File 'lib/lutaml/model/global_context.rb', line 84

def default_context
  context_id = Thread.current[THREAD_CONTEXT_KEY] || @default_context_id
  @registry.lookup(context_id) || @registry.lookup(:default)
end

#format_registry_for(format) ⇒ Object?

Get a format-specific registry.

Parameters:

  • format (Symbol)

    The format

Returns:

  • (Object, nil)

    The registry or nil if not registered



240
241
242
# File 'lib/lutaml/model/global_context.rb', line 240

def format_registry_for(format)
  @format_registries[format]
end

#register_context(context) ⇒ void

This method returns an undefined value.

Register a context.

Parameters:



136
137
138
139
140
141
142
# File 'lib/lutaml/model/global_context.rb', line 136

def register_context(context)
  @registry.register(context)
  # A replacement under an existing id must not keep answering from
  # the resolver's [context.id, name]-keyed cache.
  @resolver.clear_cache(context.id)
  @context_generation += 1
end

#register_for_namespace(namespace_uri) ⇒ Register?

Get register for a namespace URI.

Parameters:

  • namespace_uri (String)

    The namespace URI

Returns:

  • (Register, nil)

    The register or nil if not bound



314
315
316
317
318
319
# File 'lib/lutaml/model/global_context.rb', line 314

def register_for_namespace(namespace_uri)
  register_id = @namespace_register_map[namespace_uri]
  return nil unless register_id

  GlobalRegister.lookup(register_id)
end

#register_format_registry(format, registry) ⇒ void

This method returns an undefined value.

Register a format-specific registry. Format plugins call this at load time to register their registries.

Parameters:

  • format (Symbol)

    The format (e.g., :xml)

  • registry (Object)

    The registry instance (must respond to #clear!)



230
231
232
233
234
# File 'lib/lutaml/model/global_context.rb', line 230

def register_format_registry(format, registry)
  @mutex.synchronize do
    @format_registries[format] = registry
  end
end

#register_id_for_namespace(namespace_uri) ⇒ Symbol?

Get register ID for a namespace URI.

Parameters:

  • namespace_uri (String)

    The namespace URI

Returns:

  • (Symbol, nil)

    The register ID or nil if not bound



305
306
307
# File 'lib/lutaml/model/global_context.rb', line 305

def register_id_for_namespace(namespace_uri)
  @namespace_register_map[namespace_uri]
end

#reset!void

This method returns an undefined value.

Reset ALL global state (for testing).

This clears:

  • All non-default contexts
  • All type resolution caches
  • All pending imports
  • All format-specific registries
  • All namespace-register mappings


197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/lutaml/model/global_context.rb', line 197

def reset!
  @mutex.synchronize do
    @registry.clear
    @resolver.clear_all_caches
    @imports.reset!
    @format_registries.each_value do |reg|
      reg.clear! if reg.is_a?(FormatRegistry)
    end
    @namespace_register_map.clear
    @default_context_id = :default
    @context_generation += 1
  end
end

#resolvable?(name, context_id = nil) ⇒ Boolean

Check if a type is resolvable.

Parameters:

  • name (Symbol, String, Class)

    The type name or class

  • context_id (Symbol, nil) (defaults to: nil)

    Optional context ID

Returns:

  • (Boolean)

    true if resolvable



127
128
129
130
# File 'lib/lutaml/model/global_context.rb', line 127

def resolvable?(name, context_id = nil)
  ctx = context(context_id)
  @resolver.resolvable?(name, ctx)
end

#resolve_type(name, context_id = nil) ⇒ Class

Resolve a type name to a class using the default context.

Parameters:

  • name (Symbol, String, Class)

    The type name or class

  • context_id (Symbol, nil) (defaults to: nil)

    Optional context ID (uses default if not provided)

Returns:

  • (Class)

    The resolved type class

Raises:



117
118
119
120
# File 'lib/lutaml/model/global_context.rb', line 117

def resolve_type(name, context_id = nil)
  ctx = context(context_id)
  @resolver.resolve(name, ctx)
end

#resolve_type_with_namespace(type_name, namespace_uri = nil, context_id = nil) ⇒ Class?

Resolve type using namespace-aware lookup.

If a namespace is specified and a register is bound to that namespace, uses that register for type resolution. Falls back to standard resolution.

Parameters:

  • type_name (Symbol, String)

    The type name

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

    The namespace URI (optional)

  • context_id (Symbol, nil) (defaults to: nil)

    Optional explicit context

Returns:

  • (Class, nil)

    The resolved type or nil



331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/lutaml/model/global_context.rb', line 331

def resolve_type_with_namespace(type_name, namespace_uri = nil,
context_id = nil)
  # If namespace specified, try namespace-aware resolution
  if namespace_uri
    register = register_for_namespace(namespace_uri)
    if register
      result = register.resolve_in_namespace(type_name, namespace_uri)
      return result if result
    end
  end

  # Fallback to standard resolution
  resolve_type(type_name, context_id)
end

#statsHash

Get statistics about the global context.

Returns:

  • (Hash)

    Statistics including registry, resolver, and imports



271
272
273
274
275
276
277
278
279
280
# File 'lib/lutaml/model/global_context.rb', line 271

def stats
  {
    contexts: @registry.context_ids,
    default_context_id: @default_context_id,
    resolver_cache_size: @resolver.cache_stats[:size],
    imports: @imports.stats,
    format_registries: @format_registries.keys,
    namespace_register_map_size: @namespace_register_map.size,
  }
end

#unregister_context(id) ⇒ TypeContext?

Unregister a context and clear its caches.

Parameters:

  • id (Symbol)

    The context ID

Returns:



166
167
168
169
170
# File 'lib/lutaml/model/global_context.rb', line 166

def unregister_context(id)
  @resolver.clear_cache(id)
  @registry.unregister(id)
  @context_generation += 1
end

#with_context(context_id) { ... } ⇒ Object

Execute a block with a specific context as default.

Parameters:

  • context_id (Symbol)

    The context ID to use

Yields:

  • Block to execute with the context

Returns:

  • (Object)

    The block's return value



177
178
179
180
181
182
183
184
185
# File 'lib/lutaml/model/global_context.rb', line 177

def with_context(context_id)
  previous = Thread.current[THREAD_CONTEXT_KEY]
  Thread.current[THREAD_CONTEXT_KEY] = context_id.to_sym
  begin
    yield
  ensure
    Thread.current[THREAD_CONTEXT_KEY] = previous
  end
end

#xml_namespace_registryObject?

Backward-compatible accessor for XML namespace registry. Delegates to the generic format_registries hash.

Returns:

  • (Object, nil)

    The XML namespace class registry



257
258
259
# File 'lib/lutaml/model/global_context.rb', line 257

def xml_namespace_registry
  @format_registries[:xml]
end