Module: Lutaml::Model::Serialize::TransformationBuilder
- Included in:
- ClassMethods
- Defined in:
- lib/lutaml/model/serialize/transformation_builder.rb
Overview
Handles transformation building for Serialize::ClassMethods
Extracted from serialize.rb to improve code organization. Provides methods for building transformations and processing types.
Instance Method Summary collapse
-
#build_transformation(format, register_id) ⇒ Transformation
Build a new transformation instance for the format.
-
#process_reference_type(type, options) ⇒ Array
Process a reference type specification.
-
#process_type_hash(type, options) ⇒ Array
Process a type hash (for reference types).
-
#reference_type?(type) ⇒ Boolean
Check if a type hash specifies a reference type.
-
#transformation_for(format, register = nil) ⇒ Transformation?
Get or build a pre-compiled transformation for the specified format.
-
#validate_reference_spec!(ref_spec) ⇒ Object
Validate a reference specification.
Instance Method Details
#build_transformation(format, register_id) ⇒ Transformation
Build a new transformation instance for the format
This method creates a pre-compiled transformation by:
-
Ensuring all mappings are imported
-
Getting the mapping DSL for the format
-
Creating format-specific transformation class
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/lutaml/model/serialize/transformation_builder.rb', line 49 def build_transformation(format, register_id) # Get the mapping DSL for this format mapping_dsl = mappings_for(format, register_id) # Pass register_id directly (Attribute#type handles Symbol) # Create format-specific transformation using registered builders # XML builder is registered by Lutaml::Xml at load time via # TransformationRegistry.register_builder(:xml, ...) case format when :json, :yaml, :toml, :hash # Key-value formats use KeyValue::Transformation (symmetric OOP architecture) Lutaml::KeyValue::Transformation.new(self, mapping_dsl, format, register_id) else # For other formats (including :xml), use registered builder or return mapping_dsl builder = TransformationRegistry.builder_for(format) if builder builder.build(self, mapping_dsl, format, register_id) else mapping_dsl end end end |
#process_reference_type(type, options) ⇒ Array
Process a reference type specification
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/lutaml/model/serialize/transformation_builder.rb', line 102 def process_reference_type(type, ) ref_spec = type[:ref] || type["ref"] validate_reference_spec!(ref_spec) model_class, key_attr = ref_spec [:ref_model_class] = model_class [:ref_key_attribute] = key_attr type = Lutaml::Model::Type::Reference [type, ] end |
#process_type_hash(type, options) ⇒ Array
Process a type hash (for reference types)
79 80 81 82 83 84 85 86 87 |
# File 'lib/lutaml/model/serialize/transformation_builder.rb', line 79 def process_type_hash(type, ) if reference_type?(type) type, = process_reference_type(type, ) else type = nil end [type, ] end |
#reference_type?(type) ⇒ Boolean
Check if a type hash specifies a reference type
93 94 95 |
# File 'lib/lutaml/model/serialize/transformation_builder.rb', line 93 def reference_type?(type) type.key?(:ref) || type.key?("ref") end |
#transformation_for(format, register = nil) ⇒ Transformation?
Get or build a pre-compiled transformation for the specified format
Transformations are cached centrally in TransformationRegistry singleton to ensure compilation happens only once per model class and format.
CRITICAL: Uses TransformationRegistry for cycle detection to prevent infinite recursion on self-referential models (e.g., Address.address: Address)
Architecture (Phase 5.1 refactoring):
-
Model classes define mappings (declarative DSL) - stateless
-
TransformationRegistry manages ALL transformation caches - single source of truth
-
Transformation objects execute serialization - runtime instances
Register resolution: If the caller passes a parent register (e.g., :default) but this class declares its own ‘lutaml_default_register` (e.g., :mml_v2), the child’s register takes precedence. This ensures cross-register embedding works transparently — the parent doesn’t need to know the child’s register.
32 33 34 35 36 37 |
# File 'lib/lutaml/model/serialize/transformation_builder.rb', line 32 def transformation_for(format, register = nil) resolved_register = Lutaml::Model::Register.resolve_for_child(self, register) TransformationRegistry.instance.get_or_build_transformation(self, format, resolved_register) end |
#validate_reference_spec!(ref_spec) ⇒ Object
Validate a reference specification
118 119 120 121 122 123 |
# File 'lib/lutaml/model/serialize/transformation_builder.rb', line 118 def validate_reference_spec!(ref_spec) return if ref_spec.is_a?(Array) && ref_spec.length == 2 raise ArgumentError, "ref: syntax requires an array [model_class, key_attribute]" end |