Module: Lutaml::Model::Serialize::Initialization
- Included in:
- ClassMethods
- Defined in:
- lib/lutaml/model/serialize/initialization.rb
Overview
Handles initialization and namespace methods for Serialize::ClassMethods
Extracted from serialize.rb to improve code organization. Provides methods for class initialization and namespace handling.
Instance Method Summary collapse
-
#add_custom_handling_methods_to_model(klass) ⇒ Object
Add custom handling methods to a model class.
-
#add_format_specific_model_methods(_klass) ⇒ Object
Hook for format-specific model methods.
-
#allocate_for_deserialization(register = nil) ⇒ Object
Allocate an instance for deserialization without calling initialize.
-
#attributes(register = nil) ⇒ Hash
Get all attributes for this model.
-
#cast(value) ⇒ Object
Cast a value (pass-through implementation).
-
#choice(min: 1, max: 1, format: nil, &block) ⇒ Object
Define a choice constraint.
-
#choice_attributes(register = nil) ⇒ Array
Get all choice attributes for this model.
-
#class_attributes ⇒ Hash
Raw class-level attributes without register merging.
-
#clear_cache(register_id = nil) ⇒ Object
Clear all cached data for this model class.
-
#deep_duplicate_choice_attributes(source_class, register = nil) ⇒ Array
Deep duplicate choice attributes from a source class.
-
#ensure_format_mapping_imports!(_register = nil) ⇒ Object
Hook for format-specific mapping import resolution.
-
#ensure_imports!(register = nil) ⇒ Object
Ensure all imports are resolved.
-
#ensure_register_methods_defined(register_id) ⇒ Object
Define register-specific attribute methods on the class itself.
-
#included(base) ⇒ Object
Handle inclusion by extending with ClassMethods.
-
#inherited(subclass) ⇒ Object
Handle inheritance by copying parent’s configuration.
-
#initialize_attrs(source_class) ⇒ Object
Initialize class attributes from a source class.
-
#lutaml_default_register ⇒ Symbol?
Get or set the default register for this Model class.
-
#model(klass = nil) ⇒ Class
Get or set the model class.
-
#namespace(_ns_class = nil) ⇒ Class?
Class-level namespace getter/setter.
-
#namespace_prefix ⇒ String?
Get the default namespace prefix for this Model.
-
#namespace_uri ⇒ String?
Get the namespace URI for this Model.
-
#reference_resolvable? ⇒ Boolean
Whether instances of this class should be registered in the global Store for reference resolution.
-
#register(name) ⇒ Symbol?
Convert register parameter to symbol.
-
#register_record(register_id = nil) ⇒ Hash?
Get the register record for a specific register ID.
-
#set_register_context(register_id) ⇒ void
Set the register context for this Model class.
-
#skip_reference_registration ⇒ Object
Opt out of Store registration for this class.
Instance Method Details
#add_custom_handling_methods_to_model(klass) ⇒ Object
Add custom handling methods to a model class
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 223 def add_custom_handling_methods_to_model(klass) Utils.add_method_if_not_defined(klass, :using_default_for) do |attribute_name| @using_default ||= {} @using_default[attribute_name] = true end Utils.add_method_if_not_defined(klass, :value_set_for) do |attribute_name| @using_default ||= {} @using_default[attribute_name] = false end Utils.add_method_if_not_defined(klass, :values_set_for) do |attribute_names| @using_default ||= {} attribute_names.each { |name| @using_default[name] = false } end Utils.add_method_if_not_defined(klass, :using_default?) do |attribute_name| @using_default ||= {} !!@using_default[attribute_name] end # Hook for format-specific model methods (e.g., XML adds ordered, mixed, element_order) add_format_specific_model_methods(klass) end |
#add_format_specific_model_methods(_klass) ⇒ Object
Hook for format-specific model methods. XML overrides via FormatConversion prepend to add XML accessors.
256 257 258 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 256 def add_format_specific_model_methods(_klass) # No-op by default end |
#allocate_for_deserialization(register = nil) ⇒ Object
Allocate an instance for deserialization without calling initialize.
Skips the expensive initialize_attributes pass (which iterates all attributes to set defaults). The XML mapping pipeline sets values directly via rule.deserialize instead. Uses Hash.new(true) as the default for @using_default so that using_default? returns true for all attributes until value_set_for is called.
324 325 326 327 328 329 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 324 def allocate_for_deserialization(register = nil) instance = allocate register_id = extract_register_id(register) instance.finalize_deserialization(register_id) instance end |
#attributes(register = nil) ⇒ Hash
Get all attributes for this model
Merges class-level attributes with register-specific attributes.
121 122 123 124 125 126 127 128 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 121 def attributes(register = nil) ensure_imports!(register) if finalized? if @register_records&.any? @attributes.merge(@register_records[extract_register_id(register)][:attributes]) else @attributes end end |
#cast(value) ⇒ Object
Cast a value (pass-through implementation)
264 265 266 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 264 def cast(value) value end |
#choice(min: 1, max: 1, format: nil, &block) ⇒ Object
Define a choice constraint
291 292 293 294 295 296 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 291 def choice(min: 1, max: 1, format: nil, &block) @choice_attributes << Choice.new(self, min, max, format: format).tap do |c| c.instance_eval(&block) end end |
#choice_attributes(register = nil) ⇒ Array
Get all choice attributes for this model
Merges class-level choice attributes with register-specific choice attributes.
143 144 145 146 147 148 149 150 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 143 def choice_attributes(register = nil) ensure_imports!(register) if finalized? if @register_records&.any? @choice_attributes + @register_records[extract_register_id(register)][:choice_attributes] else @choice_attributes end end |
#class_attributes ⇒ Hash
Raw class-level attributes without register merging. Used by initialize_attrs during class inheritance.
133 134 135 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 133 def class_attributes @attributes end |
#clear_cache(register_id = nil) ⇒ Object
Clear all cached data for this model class
Centralized caching (Phase 11.5):
-
Type caches: GlobalContext.resolver
-
Mapping caches: TransformationRegistry
-
Transformation caches: TransformationRegistry
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 180 def clear_cache(register_id = nil) # Clear centralized type cache in GlobalContext.resolver if defined?(Lutaml::Model::GlobalContext) GlobalContext.resolver.clear_cache(register_id) end # Clear per-Attribute type caches (stale entries from GC'd TypeContext objects) class_attributes.each_value(&:clear_type_cache) @register_records&.each_value do |record| record[:attributes]&.each_value(&:clear_type_cache) end # Clear centralized mapping and transformation caches # (Single Source of Truth - no longer uses instance variables) TransformationRegistry.instance.clear # Clear Transform cache (uses class identity as key) Transform.invalidate_for(self, register_id) # Clear import resolution guard flags so imports can be re-resolved instance_variables.each do |ivar| ivar_s = ivar.to_s remove_instance_variable(ivar) if ivar_s.start_with?("@_imports_resolved_") || ivar_s == "@_register_methods_defined" end end |
#deep_duplicate_choice_attributes(source_class, register = nil) ⇒ Array
Deep duplicate choice attributes from a source class
108 109 110 111 112 113 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 108 def deep_duplicate_choice_attributes(source_class, register = nil) choice_attrs = Array(source_class.choice_attributes) choice_attrs.map do |choice_attr| choice_attr.deep_duplicate(self, register) end end |
#ensure_format_mapping_imports!(_register = nil) ⇒ Object
Hook for format-specific mapping import resolution. Override in format modules (e.g., XML prepends to resolve XML mapping imports).
168 169 170 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 168 def ensure_format_mapping_imports!(_register = nil) # No-op by default; XML overrides via prepend end |
#ensure_imports!(register = nil) ⇒ Object
Ensure all imports are resolved
155 156 157 158 159 160 161 162 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 155 def ensure_imports!(register = nil) ensure_model_imports!(register) ensure_choice_imports!(register) ensure_restrict_attributes!(register) # Hook for format-specific mapping import resolution. # XML overrides this to call mappings[:xml]&.ensure_mappings_imported!(register) ensure_format_mapping_imports!(register) end |
#ensure_register_methods_defined(register_id) ⇒ Object
Define register-specific attribute methods on the class itself.
Called once per (class, register) combination. Replaces per-instance singleton class allocation with class-level method definitions, preserving Ruby’s inline method cache optimization.
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 338 def ensure_register_methods_defined(register_id) return if register_id == :default @_register_methods_defined ||= {} return if @_register_methods_defined[register_id] reg_record = register_records[register_id] return unless reg_record default_attrs = class_attributes || {} reg_record_attrs = reg_record[:attributes] || {} reg_record_attrs.each do |name, attr| next if default_attrs.key?(name) next if method_defined?(name, false) if attr.collection? define_collection_register_methods(name) else define_scalar_register_methods(name) end end @_register_methods_defined[register_id] = true end |
#included(base) ⇒ Object
Handle inclusion by extending with ClassMethods
84 85 86 87 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 84 def included(base) base.extend(ClassMethods) base.initialize_attrs(self) end |
#inherited(subclass) ⇒ Object
Handle inheritance by copying parent’s configuration
76 77 78 79 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 76 def inherited(subclass) super subclass.initialize_attrs(self) end |
#initialize_attrs(source_class) ⇒ Object
Initialize class attributes from a source class
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 92 def initialize_attrs(source_class) @mappings = Utils.deep_dup(source_class.mappings) || {} @attributes = Utils.deep_dup(source_class.class_attributes) || {} @choice_attributes = deep_duplicate_choice_attributes(source_class) @register_records = Utils.deep_dup( source_class.register_records, ) || ::Hash.new do |hash, key| hash[key] = { attributes: {}, choice_attributes: [] } end model(self) end |
#lutaml_default_register ⇒ Symbol?
Get or set the default register for this Model class.
Override in subclasses to specify a preferred default register context. This allows versioned schemas (e.g., MML v2, v3) to use their own register by default when instances are created without explicit register.
69 70 71 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 69 def lutaml_default_register nil end |
#model(klass = nil) ⇒ Class
Get or set the model class
211 212 213 214 215 216 217 218 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 211 def model(klass = nil) if klass @model = klass add_custom_handling_methods_to_model(klass) else @model end end |
#namespace(_ns_class = nil) ⇒ Class?
Class-level namespace getter/setter.
No-op by default. When XML format is loaded, this is overridden via prepend to provide XML namespace handling.
18 19 20 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 18 def namespace(_ns_class = nil) @namespace_class end |
#namespace_prefix ⇒ String?
Get the default namespace prefix for this Model
32 33 34 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 32 def namespace_prefix nil end |
#namespace_uri ⇒ String?
Get the namespace URI for this Model
25 26 27 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 25 def namespace_uri nil end |
#reference_resolvable? ⇒ Boolean
Whether instances of this class should be registered in the global Store for reference resolution. Defaults to true for backward compatibility. Use ‘skip_reference_registration` to opt out for classes that never participate in cross-referencing.
272 273 274 275 276 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 272 def reference_resolvable? return true unless instance_variable_defined?(:@skip_reference_registration) !@skip_reference_registration end |
#register(name) ⇒ Symbol?
Convert register parameter to symbol
310 311 312 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 310 def register(name) name&.to_sym end |
#register_record(register_id = nil) ⇒ Hash?
Get the register record for a specific register ID
302 303 304 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 302 def register_record(register_id = nil) register_records[extract_register_id(register_id)] end |
#set_register_context(register_id) ⇒ void
This method returns an undefined value.
Set the register context for this Model class.
This is called by Register#register_model to ensure the class knows its register context for proper instance initialization.
43 44 45 46 47 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 43 def set_register_context(register_id) return if instance_variable_defined?(:@register) @register = register_id end |
#skip_reference_registration ⇒ Object
Opt out of Store registration for this class. Instances will not be tracked in the global Store, saving memory and registration overhead for classes that are never resolved by reference (no xml_id or similar attributes).
282 283 284 |
# File 'lib/lutaml/model/serialize/initialization.rb', line 282 def skip_reference_registration @skip_reference_registration = true end |