Class: Metaschema::ModelGenerator
- Inherits:
-
Object
- Object
- Metaschema::ModelGenerator
- Defined in:
- lib/metaschema/model_generator.rb,
lib/metaschema/model_generator/utils.rb,
lib/metaschema/model_generator/field_factory.rb,
lib/metaschema/model_generator/assembly_factory.rb,
lib/metaschema/model_generator/services/field_serializer.rb,
lib/metaschema/model_generator/services/field_deserializer.rb,
lib/metaschema/model_generator/services/collapsibles_collapser.rb
Overview
Generates Ruby classes (Lutaml::Model::Serializable subclasses) from NIST Metaschema definitions. The generated classes support XML and JSON round-tripping with full fidelity.
Delegates field class creation to FieldFactory and assembly class creation to AssemblyFactory. This class handles import resolution, augment application, and shared utilities.
Defined Under Namespace
Modules: Services, Utils Classes: AssemblyFactory, FieldFactory
Instance Attribute Summary collapse
-
#assembly_defs ⇒ Object
readonly
Shared state — accessed by FieldFactory and AssemblyFactory via @g.
-
#classes ⇒ Object
readonly
Shared state — accessed by FieldFactory and AssemblyFactory via @g.
-
#current_assembly_name ⇒ Object
Returns the value of attribute current_assembly_name.
-
#field_defs ⇒ Object
readonly
Shared state — accessed by FieldFactory and AssemblyFactory via @g.
-
#flag_defs ⇒ Object
readonly
Shared state — accessed by FieldFactory and AssemblyFactory via @g.
Class Method Summary collapse
- .generate_from_file(metaschema_path, base_path: nil) ⇒ Object
- .generate_from_metaschema(metaschema, base_path: nil) ⇒ Object
- .generate_from_xml(xml_string, base_path: nil) ⇒ Object
- .to_ruby_source(metaschema_path, module_name:, base_path: nil, split: false) ⇒ Object
Instance Method Summary collapse
- #add_flag_reference(klass, flag_ref) ⇒ Object
-
#add_inline_flag(klass, flag_def) ⇒ Object
── Shared Utilities (used by both factories) ──────────────────────.
-
#apply_constraint_validation(klass, constraint_def) ⇒ Object
── Constraint Validation Integration ──────────────────────────────.
-
#assembly_xml_element_name(assembly_ref) ⇒ Object
── XML Element Name Resolution ──────────────────────────────────.
- #create_placeholder_assembly(name) ⇒ Object
- #field_xml_element_name(field_ref) ⇒ Object
- #generate(metaschema, base_path: nil) ⇒ Object
- #scoped_field_name(field_name) ⇒ Object
Instance Attribute Details
#assembly_defs ⇒ Object (readonly)
Shared state — accessed by FieldFactory and AssemblyFactory via @g
43 44 45 |
# File 'lib/metaschema/model_generator.rb', line 43 def assembly_defs @assembly_defs end |
#classes ⇒ Object (readonly)
Shared state — accessed by FieldFactory and AssemblyFactory via @g
43 44 45 |
# File 'lib/metaschema/model_generator.rb', line 43 def classes @classes end |
#current_assembly_name ⇒ Object
Returns the value of attribute current_assembly_name.
44 45 46 |
# File 'lib/metaschema/model_generator.rb', line 44 def current_assembly_name @current_assembly_name end |
#field_defs ⇒ Object (readonly)
Shared state — accessed by FieldFactory and AssemblyFactory via @g
43 44 45 |
# File 'lib/metaschema/model_generator.rb', line 43 def field_defs @field_defs end |
#flag_defs ⇒ Object (readonly)
Shared state — accessed by FieldFactory and AssemblyFactory via @g
43 44 45 |
# File 'lib/metaschema/model_generator.rb', line 43 def flag_defs @flag_defs end |
Class Method Details
.generate_from_file(metaschema_path, base_path: nil) ⇒ Object
20 21 22 23 |
# File 'lib/metaschema/model_generator.rb', line 20 def generate_from_file(, base_path: nil) base_path ||= File.dirname(File.()) generate_from_xml(File.read(), base_path: base_path) end |
.generate_from_metaschema(metaschema, base_path: nil) ⇒ Object
30 31 32 |
# File 'lib/metaschema/model_generator.rb', line 30 def (, base_path: nil) new.generate(, base_path: base_path) end |
.generate_from_xml(xml_string, base_path: nil) ⇒ Object
25 26 27 28 |
# File 'lib/metaschema/model_generator.rb', line 25 def generate_from_xml(xml_string, base_path: nil) = Metaschema::Root.from_xml(xml_string) new.generate(, base_path: base_path) end |
.to_ruby_source(metaschema_path, module_name:, base_path: nil, split: false) ⇒ Object
34 35 36 37 38 39 |
# File 'lib/metaschema/model_generator.rb', line 34 def to_ruby_source(, module_name:, base_path: nil, split: false) classes = generate_from_file(, base_path: base_path) emitter = RubySourceEmitter.new(classes, module_name, self) split ? emitter.emit_split : emitter.emit end |
Instance Method Details
#add_flag_reference(klass, flag_ref) ⇒ Object
117 118 119 120 121 122 123 124 125 |
# File 'lib/metaschema/model_generator.rb', line 117 def add_flag_reference(klass, flag_ref) return unless flag_ref.ref flag_name = flag_ref.ref flag_def = @flag_defs[flag_name] attr_name = Utils.safe_attr(flag_name) type = flag_def ? TypeMapper.map(flag_def.as_type) : :string klass.attribute attr_name, type end |
#add_inline_flag(klass, flag_def) ⇒ Object
── Shared Utilities (used by both factories) ──────────────────────
109 110 111 112 113 114 115 |
# File 'lib/metaschema/model_generator.rb', line 109 def add_inline_flag(klass, flag_def) return unless flag_def.name attr_name = Utils.safe_attr(flag_def.name) type = TypeMapper.map(flag_def.as_type) klass.attribute attr_name, type end |
#apply_constraint_validation(klass, constraint_def) ⇒ Object
── Constraint Validation Integration ──────────────────────────────
139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/metaschema/model_generator.rb', line 139 def apply_constraint_validation(klass, constraint_def) return unless constraint_def klass.instance_variable_set(:@metaschema_constraints, constraint_def) klass.define_singleton_method(:metaschema_constraints) do @metaschema_constraints end klass.define_method(:validate_constraints) do validator = ConstraintValidator.new validator.validate(self, self.class.) end end |
#assembly_xml_element_name(assembly_ref) ⇒ Object
── XML Element Name Resolution ──────────────────────────────────
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/metaschema/model_generator.rb', line 83 def assembly_xml_element_name(assembly_ref) ref_name = assembly_ref.ref return ref_name unless ref_name return assembly_ref.use_name.content if assembly_ref.use_name&.content defn = @assembly_defs[ref_name] return defn.use_name.content if defn&.use_name&.content ref_name end |
#create_placeholder_assembly(name) ⇒ Object
132 133 134 135 |
# File 'lib/metaschema/model_generator.rb', line 132 def create_placeholder_assembly(name) key = "Assembly_#{name.gsub('-', '_')}" @classes[key] ||= Class.new(Lutaml::Model::Serializable) end |
#field_xml_element_name(field_ref) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/metaschema/model_generator.rb', line 95 def field_xml_element_name(field_ref) ref_name = field_ref.ref return ref_name unless ref_name return field_ref.use_name.content if field_ref.use_name&.content defn = @field_defs[ref_name] return defn.use_name.content if defn&.use_name&.content ref_name end |
#generate(metaschema, base_path: nil) ⇒ Object
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 |
# File 'lib/metaschema/model_generator.rb', line 46 def generate(, base_path: nil) @classes = {} @flag_defs = {} @assembly_defs = {} @field_defs = {} @namespace = .namespace @current_assembly_name = nil # Resolve imports — merge definitions from imported modules resolve_and_merge_imports(, base_path) collect_flag_definitions() collect_definition_registries() # Apply augments — add docs/flags to imported definitions apply_augments() # Phase 1: Create field classes for all definitions (top-level + imported) @field_defs.each_value do |fd| next if @classes.key?("Field_#{Utils.safe_attr(fd.name)}") FieldFactory.new(fd, self).create end # Phase 1: Create assembly placeholders for all definitions # Phase 2: Populate assembly classes for all definitions @assembly_defs.each_value do |ad| factory = AssemblyFactory.new(ad, self) factory.create_placeholder factory.populate end @classes end |
#scoped_field_name(field_name) ⇒ Object
127 128 129 130 |
# File 'lib/metaschema/model_generator.rb', line 127 def scoped_field_name(field_name) base = "Field_#{field_name.gsub('-', '_')}" @current_assembly_name ? "#{base}_in_#{@current_assembly_name}" : base end |