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

Instance Method Details

#add_custom_handling_methods_to_model(klass) ⇒ Object

Add custom handling methods to a model class

Parameters:

  • klass (Class)

    The model class



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/lutaml/model/serialize/initialization.rb', line 205

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,
                                  :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.

Parameters:

  • _klass (Class)

    The model class



232
233
234
# File 'lib/lutaml/model/serialize/initialization.rb', line 232

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.

Parameters:

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

    The register context

Returns:

  • (Object)

    The allocated instance



282
283
284
285
286
287
288
289
# File 'lib/lutaml/model/serialize/initialization.rb', line 282

def allocate_for_deserialization(register = nil)
  instance = allocate
  register_id = extract_register_id(register)
  instance.init_deserialization_state(register_id)
  instance.send(:define_singleton_attribute_methods)
  instance.send(:register_in_reference_store)
  instance
end

#attributes(register = nil) ⇒ Hash

Get all attributes for this model

Merges class-level attributes with register-specific attributes.

Parameters:

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

    The register context

Returns:

  • (Hash)

    The attributes hash



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)

Parameters:

  • value (Object)

    The value to cast

Returns:

  • (Object)

    The same value



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

def cast(value)
  value
end

#choice(min: 1, max: 1, format: nil, &block) ⇒ Object

Define a choice constraint

Parameters:

  • min (Integer) (defaults to: 1)

    Minimum number of choices

  • max (Integer) (defaults to: 1)

    Maximum number of choices

  • block (Proc)

    The choice definition block



249
250
251
252
253
254
# File 'lib/lutaml/model/serialize/initialization.rb', line 249

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.

Parameters:

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

    The register context

Returns:

  • (Array)

    The choice attributes array



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

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

#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

Parameters:

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

    If provided, only clear cache for this specific context



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/lutaml/model/serialize/initialization.rb', line 173

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 centralized mapping and transformation caches
  # (Single Source of Truth - no longer uses instance variables)
  TransformationRegistry.instance.clear

  # Clear import resolution guard flags so imports can be re-resolved
  instance_variables.each do |ivar|
    remove_instance_variable(ivar) if ivar.to_s.start_with?("@_imports_resolved_")
  end
end

#deep_duplicate_choice_attributes(source_class, register = nil) ⇒ Array

Deep duplicate choice attributes from a source class

Parameters:

  • source_class (Class)

    The source class

Returns:

  • (Array)

    The duplicated choice attributes



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.instance_variable_get(:@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).

Parameters:

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

    The register context



161
162
163
# File 'lib/lutaml/model/serialize/initialization.rb', line 161

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

Parameters:

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

    The register context



148
149
150
151
152
153
154
155
# File 'lib/lutaml/model/serialize/initialization.rb', line 148

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

#included(base) ⇒ Object

Handle inclusion by extending with ClassMethods

Parameters:

  • base (Class)

    The including class



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

Parameters:

  • subclass (Class)

    The inheriting class



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

Parameters:

  • source_class (Class)

    The source class to copy from



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.instance_variable_get(:@mappings)) || {}
  @attributes = Utils.deep_dup(source_class.instance_variable_get(:@attributes)) || {}
  @choice_attributes = deep_duplicate_choice_attributes(source_class)
  @register_records = Utils.deep_dup(
    source_class.instance_variable_get(:@register_records),
  ) || ::Hash.new do |hash, key|
         hash[key] = { attributes: {}, choice_attributes: [] }
       end
  instance_variable_set(:@model, self)
end

#lutaml_default_registerSymbol?

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.

Examples:

module Mml
  class V2Base < Lutaml::Model::Serializable
    def self.lutaml_default_register
      :mml_v2
    end
  end
end

class Mml::V2::Math < V2Base
  # Mml::V2::Math.new uses :mml_v2 by default
end

Returns:

  • (Symbol, nil)

    The default register ID or nil to use Config.default_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

Parameters:

  • klass (Class, nil) (defaults to: nil)

    The model class to set

Returns:

  • (Class)

    The model class



193
194
195
196
197
198
199
200
# File 'lib/lutaml/model/serialize/initialization.rb', line 193

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.

Parameters:

  • _ns_class (Class, nil) (defaults to: nil)

    Namespace class (handled by format modules)

Returns:

  • (Class, nil)

    the namespace class



18
19
20
# File 'lib/lutaml/model/serialize/initialization.rb', line 18

def namespace(_ns_class = nil)
  @namespace_class
end

#namespace_prefixString?

Get the default namespace prefix for this Model

Returns:

  • (String, nil)

    the namespace prefix



32
33
34
# File 'lib/lutaml/model/serialize/initialization.rb', line 32

def namespace_prefix
  nil
end

#namespace_uriString?

Get the namespace URI for this Model

Returns:

  • (String, nil)

    the namespace URI



25
26
27
# File 'lib/lutaml/model/serialize/initialization.rb', line 25

def namespace_uri
  nil
end

#register(name) ⇒ Symbol?

Convert register parameter to symbol

Parameters:

  • name (Symbol, String, nil)

    The register name

Returns:

  • (Symbol, nil)

    The register name as a symbol



268
269
270
# File 'lib/lutaml/model/serialize/initialization.rb', line 268

def register(name)
  name&.to_sym
end

#register_record(register_id = nil) ⇒ Hash?

Get the register record for a specific register ID

Parameters:

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

    The register context

Returns:

  • (Hash, nil)

    The register record hash or nil



260
261
262
# File 'lib/lutaml/model/serialize/initialization.rb', line 260

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.

Parameters:

  • register_id (Symbol)

    The register ID



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