Module: Chemicalml::VersionedParser

Included in:
Cml::Schema24, Cml::Schema3
Defined in:
lib/chemicalml/versioned_parser.rb

Overview

Shared parse entrypoint for versioned schema modules. Each schema module (Cml::Schema3, Cml::Schema24) extends this.

Polymorphic: detects the XML root element and dispatches to the right wire class's from_xml. Supported roots include <cml> (Document), <module> (compchem Module), <dictionary>, <unitList>, <unitTypeList>, and the legacy standalone roots <molecule>, <reaction>, <reactionList>.


XML processing boundary (read me):

The gem uses lutaml-model for ALL XML parsing and serialization — 242 wire classes extend Lutaml::Model::Serializable, and no lib/ file defines to_xml/from_xml/to_h/from_h on a model class. Zero Nokogiri/REXML references in lib/.

This file has TWO pre-processing helpers — root_element_of and inject_namespace — that operate on the XML string before Lutaml::Model::Serializable.from_xml is called. They are NOT serialization: they don't construct XML nodes, don't traverse trees, don't map attributes to model fields. They are input normalization so callers can pass namespace-less XML or rely on the parser to dispatch by root element name. The actual parse happens on the const_get(class_name).from_xml(...) call below.

Constant Summary collapse

KNOWN_ROOTS =

Maps root element name → constant name on the schema module. Adding a new root type = adding one entry here. OCP — no existing code changes.

{
  "cml"          => :Document,
  "molecule"     => :Molecule,
  "reaction"     => :Reaction,
  "reactionList" => :ReactionList,
  "module"       => :Module,
  "dictionary"   => :Dictionary,
  "unitList"     => :UnitList,
  "unitTypeList" => :UnitTypeList,
}.freeze

Instance Method Summary collapse

Instance Method Details

#configurationObject



73
74
75
# File 'lib/chemicalml/versioned_parser.rb', line 73

def configuration
  const_get(:Configuration)
end

#document_classObject



69
70
71
# File 'lib/chemicalml/versioned_parser.rb', line 69

def document_class
  const_get(:Document)
end

#parse(xml, namespace_exist: true) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/chemicalml/versioned_parser.rb', line 45

def parse(xml, namespace_exist: true)
  configuration.ensure_registered!
  root = root_element_of(xml)

  # Resolve the wire class for this root element via O(1) hash
  # lookup. KNOWN_ROOTS provides explicit overrides; the reverse
  # index of Elements::ALL covers everything else.
  class_name = KNOWN_ROOTS[root] || Chemicalml::Cml::Elements::XML_TO_CLASS[root]
  unless class_name
    raise ArgumentError,
          "unsupported CML root element <#{root}>"
  end
  unless const_defined?(class_name, false)
    raise ArgumentError,
          "#{name} does not define #{class_name} " \
          "(not all root elements exist in every schema version)"
  end

  const_get(class_name).from_xml(
    xml_input(xml, namespace_exist, root),
    register: configuration.context_id
  )
end