Class: Lutaml::Model::AdapterResolver
- Inherits:
-
Object
- Object
- Lutaml::Model::AdapterResolver
- Defined in:
- lib/lutaml/model/adapter_resolver.rb
Overview
Single authority for adapter resolution: (format, type_name) → adapter class.
Consolidates adapter metadata, loading, validation, and auto-detection that was previously spread across Config, Configuration, and FormatRegistry.
Resolution chain (in order):
1. Thread-local AdapterScope override
2. Explicitly configured type (from Config.xml_adapter_type =)
3. Lazy auto-detected type (cached after first probe)
4. Default from format metadata
5. Raise FormatAdapterNotSpecifiedError
Class Method Summary collapse
-
.adapter_for(format) ⇒ Class?
Resolve the adapter class for a format using the full resolution chain.
-
.configured_type(format) ⇒ Symbol?
Get the configured type name for a format.
-
.register_fixed(format, adapter_class, adapter_name) ⇒ void
Register a fixed adapter class for a format with a single adapter.
-
.register_metadata(format, options) ⇒ void
Register adapter metadata for a format (available adapters, default).
-
.reset! ⇒ void
Clear all state (for testing reset).
-
.resolved_adapter_class(format, type_name) ⇒ Class
Load and resolve an adapter class by type name.
-
.set_adapter_class(format, adapter_class) ⇒ void
Store a pre-resolved adapter class for a format.
-
.set_adapter_type(format, type_name) ⇒ Class
Set the adapter type for a format (validates and loads).
Class Method Details
.adapter_for(format) ⇒ Class?
Resolve the adapter class for a format using the full resolution chain.
38 39 40 41 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 38 def adapter_for(format) # 1. Thread-local scope override scope_override = AdapterScope.override_for(format) if scope_override return resolved_adapter_class(format, scope_override) end # 2. Explicitly configured type — a named type is an explicit pin # and must never fall through to auto-detection: detection loads # optional engines (e.g. yeptris) into the process even when the # user pinned a standard adapter, which crashes platforms where # the engine's build is broken. FIXED_ADAPTER_TYPE with no # resolved class means "unset" (set_adapter_class(format, nil)) # and keeps the old detect-through behavior. configured = configured_type(format) if configured adapter = resolved[format] return adapter if adapter return load_and_cache(format, configured) if configured != FIXED_ADAPTER_TYPE end # 3. Lazy auto-detection (cached) detected = detected_types[format] if detected.nil? && !detected_formats.key?(format) result = detect_adapter_for(format) if result detected_formats[format] = true detected_types[format] = result return load_and_cache(format, result) end detected_formats[format] = true elsif detected return load_and_cache(format, detected) end # 4. Default from metadata default = .dig(format, :default) if default return load_and_cache(format, default) end # 5. No adapter available nil end |
.configured_type(format) ⇒ Symbol?
Get the configured type name for a format.
156 157 158 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 156 def configured_type(format) configured_types[format] end |
.register_fixed(format, adapter_class, adapter_name) ⇒ void
This method returns an undefined value.
Register a fixed adapter class for a format with a single adapter.
Used for key-value formats (json, yaml, hash, etc.) that have exactly one adapter. Creates metadata so validation works.
143 144 145 146 147 148 149 150 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 143 def register_fixed(format, adapter_class, adapter_name) [format] = { available: [adapter_name], default: adapter_name, } resolved[format] = adapter_class configured_types[format] = adapter_name end |
.register_metadata(format, options) ⇒ void
This method returns an undefined value.
Register adapter metadata for a format (available adapters, default).
Called by FormatRegistry.register for formats with selectable adapters.
130 131 132 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 130 def (format, ) [format] = end |
.reset! ⇒ void
This method returns an undefined value.
Clear all state (for testing reset).
165 166 167 168 169 170 171 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 165 def reset! @metadata = nil @configured_types = nil @resolved = nil @detected_types = nil @detected_formats = nil end |
.resolved_adapter_class(format, type_name) ⇒ Class
Load and resolve an adapter class by type name. Used for per-operation overrides (from_xml adapter: :ox).
115 116 117 118 119 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 115 def resolved_adapter_class(format, type_name) type_name = type_name.to_sym validate!(format, type_name) load_adapter(format, type_name) end |
.set_adapter_class(format, adapter_class) ⇒ void
This method returns an undefined value.
Store a pre-resolved adapter class for a format.
Used by FormatRegistry.register for key-value formats that have a fixed adapter class (not selectable by type name).
104 105 106 107 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 104 def set_adapter_class(format, adapter_class) resolved[format] = adapter_class configured_types[format] = FIXED_ADAPTER_TYPE end |
.set_adapter_type(format, type_name) ⇒ Class
Set the adapter type for a format (validates and loads).
89 90 91 92 93 94 |
# File 'lib/lutaml/model/adapter_resolver.rb', line 89 def set_adapter_type(format, type_name) type_name = type_name.to_sym validate!(format, type_name) configured_types[format] = type_name resolved[format] = load_adapter(format, type_name) end |