module Lutaml::Model::Serialize::Initialization
def add_custom_handling_methods_to_model(klass)
-
klass(Class) -- The model class
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
def add_format_specific_model_methods(_klass)
-
_klass(Class) -- The model class
def add_format_specific_model_methods(_klass) # No-op by default end
def allocate_for_deserialization(register = nil)
-
(Object)- The allocated instance
Parameters:
-
register(Symbol, nil) -- The register context
def allocate_for_deserialization(register = nil) instance = allocate register_id = extract_register_id(register) instance.finalize_deserialization(register_id) instance end
def attributes(register = nil)
-
(Hash)- The attributes hash
Parameters:
-
register(Symbol, nil) -- The register context
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
def cast(value)
-
(Object)- The same value
Parameters:
-
value(Object) -- The value to cast
def cast(value) value end
def choice(min: 1, max: 1, format: nil, &block)
-
block(Proc) -- The choice definition block -
max(Integer) -- Maximum number of choices -
min(Integer) -- Minimum number of choices
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
def choice_attributes(register = nil)
-
(Array)- The choice attributes array
Parameters:
-
register(Symbol, nil) -- The register context
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
def class_attributes
-
(Hash)- The raw attributes hash
def class_attributes @attributes end
def clear_cache(register_id = nil)
-
register_id(Symbol, nil) -- If provided, only clear cache for this specific context
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
def deep_duplicate_choice_attributes(source_class, register = nil)
-
(Array)- The duplicated choice attributes
Parameters:
-
source_class(Class) -- The source class
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
def define_collection_register_methods(name)
def define_collection_register_methods(name) define_method(name) do |*args| if args.empty? current = instance_variable_get(:"@#{name}") current.equal?(LAZY_EMPTY_COLLECTION) ? [] : current else value = args.first current = instance_variable_get(:"@#{name}") current = [] if current.equal?(LAZY_EMPTY_COLLECTION) new_value = current.is_a?(Array) ? current + [value] : value instance_variable_set(:"@#{name}", new_value) record_mutation(name, value) value end end define_method(:"#{name}=") do |value| value_set_for(name) reg_attr = resolve_register_attr(name) value = reg_attr.cast_value(value, lutaml_register) current = instance_variable_get(:"@#{name}") if current.equal?(LAZY_EMPTY_COLLECTION) && (value.nil? || Lutaml::Model::Utils.uninitialized?(value)) # Sentinel stays — no allocation for empty collections else instance_variable_set(:"@#{name}", value) end record_mutation_collection(name, value) end end
def define_scalar_register_methods(name)
def define_scalar_register_methods(name) define_method(name) do |*args| if args.empty? instance_variable_get(:"@#{name}") else public_send(:"#{name}=", args.first) args.first end end define_method(:"#{name}=") do |value| value_set_for(name) reg_attr = resolve_register_attr(name) value = reg_attr.cast_value(value, lutaml_register) instance_variable_set(:"@#{name}", value) record_mutation(name, value) end end
def ensure_format_mapping_imports!(_register = nil)
-
_register(Symbol, nil) -- The register context
def ensure_format_mapping_imports!(_register = nil) # No-op by default; XML overrides via prepend end
def ensure_imports!(register = nil)
-
register(Symbol, nil) -- The register context
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
def ensure_register_methods_defined(register_id)
-
register_id(Symbol) -- The register ID
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
def extract_register_id(register)
-
(Symbol)- The normalized register ID
Parameters:
-
register(Symbol, String, nil) -- The register identifier
def extract_register_id(register) register&.to_sym || lutaml_default_register || Lutaml::Model::Config.default_register end
def included(base)
-
base(Class) -- The including class
def included(base) base.extend(ClassMethods) base.initialize_attrs(self) end
def inherited(subclass)
-
subclass(Class) -- The inheriting class
def inherited(subclass) super subclass.initialize_attrs(self) end
def initialize_attrs(source_class)
-
source_class(Class) -- The source class to copy from
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
def lutaml_default_register
-
(Symbol, nil)- The default register ID or nil to use Config.default_register
def lutaml_default_register nil end
def model(klass = nil)
-
(Class)- The model class
Parameters:
-
klass(Class, nil) -- The model class to set
def model(klass = nil) if klass @model = klass add_custom_handling_methods_to_model(klass) else @model end end
def namespace(_ns_class = nil)
-
(Class, nil)- the namespace class
Parameters:
-
_ns_class(Class, nil) -- Namespace class (handled by format modules)
def namespace(_ns_class = nil) @namespace_class end
def namespace_prefix
-
(String, nil)- the namespace prefix
def namespace_prefix nil end
def namespace_uri
-
(String, nil)- the namespace URI
def namespace_uri nil end
def reference_resolvable?
backward compatibility. Use `skip_reference_registration` to
global Store for reference resolution. Defaults to true for
Whether instances of this class should be registered in the
def reference_resolvable? return true unless instance_variable_defined?(:@skip_reference_registration) !@skip_reference_registration end
def register(name)
-
(Symbol, nil)- The register name as a symbol
Parameters:
-
name(Symbol, String, nil) -- The register name
def register(name) name&.to_sym end
def register_record(register_id = nil)
-
(Hash, nil)- The register record hash or nil
Parameters:
-
register_id(Symbol, nil) -- The register context
def register_record(register_id = nil) register_records[extract_register_id(register_id)] end
def set_register_context(register_id)
-
(void)-
Parameters:
-
register_id(Symbol) -- The register ID
def set_register_context(register_id) return if instance_variable_defined?(:@register) @register = register_id end
def skip_reference_registration
memory and registration overhead for classes that are never
Instances will not be tracked in the global Store, saving
Opt out of Store registration for this class.
def skip_reference_registration @skip_reference_registration = true end