chemicalml 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +21 -0
- data/CLAUDE.md +198 -0
- data/Gemfile +14 -0
- data/LICENSE +24 -0
- data/NOTICES.adoc +115 -0
- data/README.adoc +87 -0
- data/Rakefile +8 -0
- data/TODO.align/01-cml-base-mixins.md +122 -0
- data/TODO.align/02-real-schema-hierarchies.md +88 -0
- data/TODO.align/03-configuration.md +50 -0
- data/TODO.align/04-parse-entry-points.md +59 -0
- data/TODO.align/05-schema-aware-translator.md +33 -0
- data/TODO.align/06-no-respond-to.md +44 -0
- data/TODO.align/07-canon-xml-comparison.md +43 -0
- data/TODO.align/08-expand-fixtures.md +37 -0
- data/TODO.align/09-final-spec-lint.md +29 -0
- data/TODO.align/10-role-marker-modules.md +54 -0
- data/TODO.align/11-dry-configuration.md +63 -0
- data/TODO.align/12-wire-class-macro.md +51 -0
- data/TODO.align/13-wire-namespace.md +44 -0
- data/TODO.align/14-schema24-correctness.md +37 -0
- data/TODO.align/15-canon-fixture-roundtrip.md +38 -0
- data/TODO.align/16-schema24-convention-coverage.md +33 -0
- data/TODO.align/17-final-spec-lint.md +28 -0
- data/TODO.align/README.md +27 -0
- data/TODO.align/README.round2.md +24 -0
- data/TODO.cml-full/01-reference-docs.md +43 -0
- data/TODO.cml-full/02-schema-versioned-model.md +70 -0
- data/TODO.cml-full/03-fixtures-scrape.md +52 -0
- data/TODO.cml-full/04-convention-framework.md +69 -0
- data/TODO.cml-full/05-dictionary-layer.md +77 -0
- data/TODO.cml-full/06-extend-canonical-translator.md +60 -0
- data/TODO.cml-full/07-attribution-notices.md +42 -0
- data/TODO.cml-full/08-autoload-only.md +48 -0
- data/TODO.cml-full/09-spec-coverage.md +38 -0
- data/TODO.cml-full/README.md +23 -0
- data/chemicalml.gemspec +35 -0
- data/data/dictionaries/_index.yaml +14 -0
- data/data/dictionaries/compchem.yaml +481 -0
- data/data/dictionaries/unit_non_si.yaml +53 -0
- data/data/dictionaries/unit_si.yaml +87 -0
- data/data/dictionaries/unit_type.yaml +113 -0
- data/lib/chemicalml/cml/array.rb +10 -0
- data/lib/chemicalml/cml/atom.rb +10 -0
- data/lib/chemicalml/cml/atom_array.rb +10 -0
- data/lib/chemicalml/cml/atom_parity.rb +10 -0
- data/lib/chemicalml/cml/base/array.rb +36 -0
- data/lib/chemicalml/cml/base/atom.rb +38 -0
- data/lib/chemicalml/cml/base/atom_array.rb +22 -0
- data/lib/chemicalml/cml/base/atom_parity.rb +24 -0
- data/lib/chemicalml/cml/base/bond.rb +28 -0
- data/lib/chemicalml/cml/base/bond_array.rb +22 -0
- data/lib/chemicalml/cml/base/bond_stereo.rb +28 -0
- data/lib/chemicalml/cml/base/cml_module.rb +40 -0
- data/lib/chemicalml/cml/base/dictionary.rb +32 -0
- data/lib/chemicalml/cml/base/dictionary_entry.rb +34 -0
- data/lib/chemicalml/cml/base/document.rb +26 -0
- data/lib/chemicalml/cml/base/formula.rb +38 -0
- data/lib/chemicalml/cml/base/identifier.rb +26 -0
- data/lib/chemicalml/cml/base/label.rb +28 -0
- data/lib/chemicalml/cml/base/list.rb +36 -0
- data/lib/chemicalml/cml/base/matrix.rb +38 -0
- data/lib/chemicalml/cml/base/metadata.rb +30 -0
- data/lib/chemicalml/cml/base/metadata_list.rb +28 -0
- data/lib/chemicalml/cml/base/molecule.rb +40 -0
- data/lib/chemicalml/cml/base/name.rb +26 -0
- data/lib/chemicalml/cml/base/parameter.rb +34 -0
- data/lib/chemicalml/cml/base/parameter_list.rb +28 -0
- data/lib/chemicalml/cml/base/product.rb +22 -0
- data/lib/chemicalml/cml/base/product_list.rb +22 -0
- data/lib/chemicalml/cml/base/property.rb +34 -0
- data/lib/chemicalml/cml/base/property_list.rb +28 -0
- data/lib/chemicalml/cml/base/reactant.rb +22 -0
- data/lib/chemicalml/cml/base/reactant_list.rb +22 -0
- data/lib/chemicalml/cml/base/reaction.rb +32 -0
- data/lib/chemicalml/cml/base/reaction_list.rb +22 -0
- data/lib/chemicalml/cml/base/scalar.rb +32 -0
- data/lib/chemicalml/cml/base/substance.rb +30 -0
- data/lib/chemicalml/cml/base/unit.rb +38 -0
- data/lib/chemicalml/cml/base/unit_list.rb +30 -0
- data/lib/chemicalml/cml/base/unit_type.rb +28 -0
- data/lib/chemicalml/cml/base/unit_type_list.rb +30 -0
- data/lib/chemicalml/cml/base.rb +51 -0
- data/lib/chemicalml/cml/bond.rb +10 -0
- data/lib/chemicalml/cml/bond_array.rb +10 -0
- data/lib/chemicalml/cml/bond_stereo.rb +10 -0
- data/lib/chemicalml/cml/cml_module.rb +10 -0
- data/lib/chemicalml/cml/dictionary.rb +10 -0
- data/lib/chemicalml/cml/dictionary_entry.rb +10 -0
- data/lib/chemicalml/cml/document.rb +10 -0
- data/lib/chemicalml/cml/elements.rb +58 -0
- data/lib/chemicalml/cml/formula.rb +10 -0
- data/lib/chemicalml/cml/identifier.rb +10 -0
- data/lib/chemicalml/cml/label.rb +10 -0
- data/lib/chemicalml/cml/list.rb +10 -0
- data/lib/chemicalml/cml/matrix.rb +10 -0
- data/lib/chemicalml/cml/metadata.rb +10 -0
- data/lib/chemicalml/cml/metadata_list.rb +10 -0
- data/lib/chemicalml/cml/molecule.rb +10 -0
- data/lib/chemicalml/cml/name.rb +10 -0
- data/lib/chemicalml/cml/namespace.rb +17 -0
- data/lib/chemicalml/cml/parameter.rb +10 -0
- data/lib/chemicalml/cml/parameter_list.rb +10 -0
- data/lib/chemicalml/cml/product.rb +10 -0
- data/lib/chemicalml/cml/product_list.rb +10 -0
- data/lib/chemicalml/cml/property.rb +10 -0
- data/lib/chemicalml/cml/property_list.rb +10 -0
- data/lib/chemicalml/cml/reactant.rb +10 -0
- data/lib/chemicalml/cml/reactant_list.rb +10 -0
- data/lib/chemicalml/cml/reaction.rb +10 -0
- data/lib/chemicalml/cml/reaction_list.rb +10 -0
- data/lib/chemicalml/cml/role/array.rb +13 -0
- data/lib/chemicalml/cml/role/atom.rb +13 -0
- data/lib/chemicalml/cml/role/atom_array.rb +13 -0
- data/lib/chemicalml/cml/role/atom_parity.rb +13 -0
- data/lib/chemicalml/cml/role/bond.rb +13 -0
- data/lib/chemicalml/cml/role/bond_array.rb +13 -0
- data/lib/chemicalml/cml/role/bond_stereo.rb +13 -0
- data/lib/chemicalml/cml/role/cml_module.rb +14 -0
- data/lib/chemicalml/cml/role/dictionary.rb +13 -0
- data/lib/chemicalml/cml/role/dictionary_entry.rb +13 -0
- data/lib/chemicalml/cml/role/document.rb +13 -0
- data/lib/chemicalml/cml/role/formula.rb +13 -0
- data/lib/chemicalml/cml/role/identifier.rb +13 -0
- data/lib/chemicalml/cml/role/label.rb +13 -0
- data/lib/chemicalml/cml/role/list.rb +13 -0
- data/lib/chemicalml/cml/role/matrix.rb +13 -0
- data/lib/chemicalml/cml/role/metadata.rb +13 -0
- data/lib/chemicalml/cml/role/metadata_list.rb +13 -0
- data/lib/chemicalml/cml/role/molecule.rb +13 -0
- data/lib/chemicalml/cml/role/name.rb +13 -0
- data/lib/chemicalml/cml/role/parameter.rb +13 -0
- data/lib/chemicalml/cml/role/parameter_list.rb +13 -0
- data/lib/chemicalml/cml/role/product.rb +13 -0
- data/lib/chemicalml/cml/role/product_list.rb +13 -0
- data/lib/chemicalml/cml/role/property.rb +13 -0
- data/lib/chemicalml/cml/role/property_list.rb +13 -0
- data/lib/chemicalml/cml/role/reactant.rb +13 -0
- data/lib/chemicalml/cml/role/reactant_list.rb +13 -0
- data/lib/chemicalml/cml/role/reaction.rb +13 -0
- data/lib/chemicalml/cml/role/reaction_list.rb +13 -0
- data/lib/chemicalml/cml/role/scalar.rb +13 -0
- data/lib/chemicalml/cml/role/substance.rb +13 -0
- data/lib/chemicalml/cml/role/unit.rb +13 -0
- data/lib/chemicalml/cml/role/unit_list.rb +13 -0
- data/lib/chemicalml/cml/role/unit_type.rb +13 -0
- data/lib/chemicalml/cml/role/unit_type_list.rb +13 -0
- data/lib/chemicalml/cml/role.rb +54 -0
- data/lib/chemicalml/cml/scalar.rb +10 -0
- data/lib/chemicalml/cml/schema24/configuration.rb +19 -0
- data/lib/chemicalml/cml/schema24.rb +40 -0
- data/lib/chemicalml/cml/schema3/configuration.rb +17 -0
- data/lib/chemicalml/cml/schema3.rb +40 -0
- data/lib/chemicalml/cml/substance.rb +10 -0
- data/lib/chemicalml/cml/translator/value_translations.rb +265 -0
- data/lib/chemicalml/cml/translator.rb +233 -0
- data/lib/chemicalml/cml/unit.rb +10 -0
- data/lib/chemicalml/cml/unit_list.rb +10 -0
- data/lib/chemicalml/cml/unit_type.rb +10 -0
- data/lib/chemicalml/cml/unit_type_list.rb +10 -0
- data/lib/chemicalml/cml/visitable.rb +65 -0
- data/lib/chemicalml/cml/wire_class_macro.rb +45 -0
- data/lib/chemicalml/cml.rb +55 -0
- data/lib/chemicalml/context_configuration.rb +127 -0
- data/lib/chemicalml/convention/base.rb +48 -0
- data/lib/chemicalml/convention/compchem/constraints/compchem_module_must_contain_job_list.rb +33 -0
- data/lib/chemicalml/convention/compchem/constraints/job_must_contain_initialization.rb +38 -0
- data/lib/chemicalml/convention/compchem/constraints.rb +14 -0
- data/lib/chemicalml/convention/compchem.rb +28 -0
- data/lib/chemicalml/convention/constraint.rb +79 -0
- data/lib/chemicalml/convention/dictionary/constraints/entry_ids_unique_within_dictionary.rb +33 -0
- data/lib/chemicalml/convention/dictionary/constraints/entry_must_have_id_and_term.rb +34 -0
- data/lib/chemicalml/convention/dictionary/constraints.rb +14 -0
- data/lib/chemicalml/convention/dictionary.rb +28 -0
- data/lib/chemicalml/convention/molecular/constraints/atom_array_must_contain_atoms.rb +30 -0
- data/lib/chemicalml/convention/molecular/constraints/atom_ids_unique_within_molecule.rb +42 -0
- data/lib/chemicalml/convention/molecular/constraints/bond_must_reference_atoms_in_same_molecule.rb +54 -0
- data/lib/chemicalml/convention/molecular/constraints.rb +19 -0
- data/lib/chemicalml/convention/molecular.rb +29 -0
- data/lib/chemicalml/convention/registry.rb +50 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints/unit_must_have_symbol_and_unit_type.rb +46 -0
- data/lib/chemicalml/convention/unit_dictionary/constraints.rb +12 -0
- data/lib/chemicalml/convention/unit_dictionary.rb +27 -0
- data/lib/chemicalml/convention/unit_type_dictionary/constraints/unit_type_must_have_id_and_name.rb +34 -0
- data/lib/chemicalml/convention/unit_type_dictionary/constraints.rb +12 -0
- data/lib/chemicalml/convention/unit_type_dictionary.rb +27 -0
- data/lib/chemicalml/convention/violation.rb +36 -0
- data/lib/chemicalml/convention.rb +39 -0
- data/lib/chemicalml/dictionary/entry.rb +59 -0
- data/lib/chemicalml/dictionary/enum.rb +51 -0
- data/lib/chemicalml/dictionary/link.rb +32 -0
- data/lib/chemicalml/dictionary/loader.rb +60 -0
- data/lib/chemicalml/dictionary/model.rb +64 -0
- data/lib/chemicalml/dictionary/registry.rb +75 -0
- data/lib/chemicalml/dictionary.rb +26 -0
- data/lib/chemicalml/errors.rb +7 -0
- data/lib/chemicalml/model/atom.rb +40 -0
- data/lib/chemicalml/model/bond.rb +33 -0
- data/lib/chemicalml/model/cml_array.rb +27 -0
- data/lib/chemicalml/model/cml_module.rb +45 -0
- data/lib/chemicalml/model/document.rb +29 -0
- data/lib/chemicalml/model/formula.rb +34 -0
- data/lib/chemicalml/model/identifier.rb +21 -0
- data/lib/chemicalml/model/label.rb +21 -0
- data/lib/chemicalml/model/matrix.rb +29 -0
- data/lib/chemicalml/model/metadata.rb +23 -0
- data/lib/chemicalml/model/metadata_list.rb +25 -0
- data/lib/chemicalml/model/molecule.rb +38 -0
- data/lib/chemicalml/model/name.rb +21 -0
- data/lib/chemicalml/model/node.rb +45 -0
- data/lib/chemicalml/model/parameter.rb +27 -0
- data/lib/chemicalml/model/parameter_list.rb +25 -0
- data/lib/chemicalml/model/product.rb +21 -0
- data/lib/chemicalml/model/product_list.rb +21 -0
- data/lib/chemicalml/model/property.rb +28 -0
- data/lib/chemicalml/model/property_list.rb +25 -0
- data/lib/chemicalml/model/reactant.rb +21 -0
- data/lib/chemicalml/model/reactant_list.rb +21 -0
- data/lib/chemicalml/model/reaction.rb +41 -0
- data/lib/chemicalml/model/reaction_list.rb +23 -0
- data/lib/chemicalml/model/scalar.rb +25 -0
- data/lib/chemicalml/model/substance.rb +25 -0
- data/lib/chemicalml/model.rb +38 -0
- data/lib/chemicalml/schema/definition.rb +41 -0
- data/lib/chemicalml/schema/registry.rb +30 -0
- data/lib/chemicalml/schema.rb +35 -0
- data/lib/chemicalml/version.rb +5 -0
- data/lib/chemicalml/versioned_parser.rb +43 -0
- data/lib/chemicalml.rb +47 -0
- data/lib/tasks/reference_fetch.rake +105 -0
- data/lib/tasks/scrape_fixtures.rake +133 -0
- data/reference-docs/conventions/compchem.md +141 -0
- data/reference-docs/conventions/dictionary.md +119 -0
- data/reference-docs/conventions/index.md +56 -0
- data/reference-docs/conventions/molecular.md +115 -0
- data/reference-docs/conventions/unit-dictionary.md +92 -0
- data/reference-docs/conventions/unitType-dictionary.md +51 -0
- data/reference-docs/dictionaries/compchem.md +335 -0
- data/reference-docs/dictionaries/index.md +52 -0
- data/reference-docs/examples/schema24-index.md +50 -0
- data/reference-docs/examples/schema3-compchem-index.md +14 -0
- data/reference-docs/examples/schema3-molecular-index.md +28 -0
- data/reference-docs/schemas/schema24/schema.xsd +10624 -0
- data/reference-docs/schemas/schema3/schema.xsd +11459 -0
- metadata +306 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chemicalml
|
|
4
|
+
module Cml
|
|
5
|
+
class Translator
|
|
6
|
+
# Canonical-form translations for the value-container and module
|
|
7
|
+
# elements introduced when the compchem / molecular conventions
|
|
8
|
+
# were added. Each method is symmetric with the existing
|
|
9
|
+
# molecule/atom/bond translators.
|
|
10
|
+
module ValueTranslations
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def scalar_to_canonical(cml_scalar)
|
|
13
|
+
return nil unless cml_scalar
|
|
14
|
+
|
|
15
|
+
Model::Scalar.new(
|
|
16
|
+
value: cml_scalar.content,
|
|
17
|
+
data_type: cml_scalar.data_type,
|
|
18
|
+
units: cml_scalar.units,
|
|
19
|
+
id: cml_scalar.id,
|
|
20
|
+
title: cml_scalar.title,
|
|
21
|
+
dict_ref: cml_scalar.dict_ref
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def scalar_from_canonical(scalar)
|
|
26
|
+
return nil unless scalar
|
|
27
|
+
|
|
28
|
+
Cml::Scalar.new(
|
|
29
|
+
content: scalar.value,
|
|
30
|
+
data_type: scalar.data_type,
|
|
31
|
+
units: scalar.units,
|
|
32
|
+
id: scalar.id,
|
|
33
|
+
title: scalar.title,
|
|
34
|
+
dict_ref: scalar.dict_ref
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def array_to_canonical(cml_array)
|
|
39
|
+
return nil unless cml_array
|
|
40
|
+
|
|
41
|
+
Model::Array.new(
|
|
42
|
+
values: cml_array.content.to_s.split,
|
|
43
|
+
data_type: cml_array.data_type,
|
|
44
|
+
units: cml_array.units,
|
|
45
|
+
size: cml_array.size,
|
|
46
|
+
id: cml_array.id,
|
|
47
|
+
title: cml_array.title,
|
|
48
|
+
dict_ref: cml_array.dict_ref
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def array_from_canonical(array)
|
|
53
|
+
return nil unless array
|
|
54
|
+
|
|
55
|
+
Cml::Array.new(
|
|
56
|
+
content: Array(array.values).join(" "),
|
|
57
|
+
data_type: array.data_type,
|
|
58
|
+
units: array.units,
|
|
59
|
+
size: array.size,
|
|
60
|
+
id: array.id,
|
|
61
|
+
title: array.title,
|
|
62
|
+
dict_ref: array.dict_ref
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def matrix_to_canonical(cml_matrix)
|
|
67
|
+
return nil unless cml_matrix
|
|
68
|
+
|
|
69
|
+
Model::Matrix.new(
|
|
70
|
+
values: cml_matrix.content.to_s.split,
|
|
71
|
+
rows: cml_matrix.rows,
|
|
72
|
+
columns: cml_matrix.columns,
|
|
73
|
+
data_type: cml_matrix.data_type,
|
|
74
|
+
units: cml_matrix.units,
|
|
75
|
+
id: cml_matrix.id,
|
|
76
|
+
title: cml_matrix.title,
|
|
77
|
+
dict_ref: cml_matrix.dict_ref
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def matrix_from_canonical(matrix)
|
|
82
|
+
return nil unless matrix
|
|
83
|
+
|
|
84
|
+
Cml::Matrix.new(
|
|
85
|
+
content: Array(matrix.values).join(" "),
|
|
86
|
+
rows: matrix.rows,
|
|
87
|
+
columns: matrix.columns,
|
|
88
|
+
data_type: matrix.data_type,
|
|
89
|
+
units: matrix.units,
|
|
90
|
+
id: matrix.id,
|
|
91
|
+
title: matrix.title,
|
|
92
|
+
dict_ref: matrix.dict_ref
|
|
93
|
+
)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def value_container_to_canonical(cml_value)
|
|
97
|
+
return nil unless cml_value
|
|
98
|
+
|
|
99
|
+
if cml_value.is_a?(Cml::Matrix)
|
|
100
|
+
matrix_to_canonical(cml_value)
|
|
101
|
+
elsif cml_value.is_a?(Cml::Array)
|
|
102
|
+
array_to_canonical(cml_value)
|
|
103
|
+
elsif cml_value.is_a?(Cml::Scalar)
|
|
104
|
+
scalar_to_canonical(cml_value)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def value_container_from_canonical(value)
|
|
109
|
+
case value
|
|
110
|
+
when Model::Matrix then matrix_from_canonical(value)
|
|
111
|
+
when Model::Array then array_from_canonical(value)
|
|
112
|
+
when Model::Scalar then scalar_from_canonical(value)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def property_to_canonical(cml_prop)
|
|
117
|
+
return nil unless cml_prop
|
|
118
|
+
|
|
119
|
+
Model::Property.new(
|
|
120
|
+
id: cml_prop.id,
|
|
121
|
+
title: cml_prop.title,
|
|
122
|
+
dict_ref: cml_prop.dict_ref,
|
|
123
|
+
convention: cml_prop.convention,
|
|
124
|
+
value: property_value_to_canonical(cml_prop)
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def property_from_canonical(prop)
|
|
129
|
+
return nil unless prop
|
|
130
|
+
|
|
131
|
+
value = value_container_from_canonical(prop.value)
|
|
132
|
+
Cml::Property.new(
|
|
133
|
+
id: prop.id,
|
|
134
|
+
title: prop.title,
|
|
135
|
+
dict_ref: prop.dict_ref,
|
|
136
|
+
convention: prop.convention,
|
|
137
|
+
scalar: value.is_a?(Cml::Scalar) ? value : nil,
|
|
138
|
+
array: value.is_a?(Cml::Array) ? value : nil,
|
|
139
|
+
matrix: value.is_a?(Cml::Matrix) ? value : nil
|
|
140
|
+
)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def parameter_to_canonical(cml_param)
|
|
144
|
+
return nil unless cml_param
|
|
145
|
+
|
|
146
|
+
Model::Parameter.new(
|
|
147
|
+
id: cml_param.id,
|
|
148
|
+
title: cml_param.title,
|
|
149
|
+
dict_ref: cml_param.dict_ref,
|
|
150
|
+
convention: cml_param.convention,
|
|
151
|
+
value: parameter_value_to_canonical(cml_param)
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def parameter_from_canonical(param)
|
|
156
|
+
return nil unless param
|
|
157
|
+
|
|
158
|
+
value = value_container_from_canonical(param.value)
|
|
159
|
+
Cml::Parameter.new(
|
|
160
|
+
id: param.id,
|
|
161
|
+
title: param.title,
|
|
162
|
+
dict_ref: param.dict_ref,
|
|
163
|
+
convention: param.convention,
|
|
164
|
+
scalar: value.is_a?(Cml::Scalar) ? value : nil,
|
|
165
|
+
array: value.is_a?(Cml::Array) ? value : nil,
|
|
166
|
+
matrix: value.is_a?(Cml::Matrix) ? value : nil
|
|
167
|
+
)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def label_to_canonical(cml_label)
|
|
171
|
+
return nil unless cml_label
|
|
172
|
+
|
|
173
|
+
Model::Label.new(
|
|
174
|
+
id: cml_label.id,
|
|
175
|
+
value: cml_label.value,
|
|
176
|
+
dict_ref: cml_label.dict_ref,
|
|
177
|
+
convention: cml_label.convention
|
|
178
|
+
)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def label_from_canonical(label)
|
|
182
|
+
return nil unless label
|
|
183
|
+
|
|
184
|
+
Cml::Label.new(
|
|
185
|
+
id: label.id,
|
|
186
|
+
value: label.value,
|
|
187
|
+
dict_ref: label.dict_ref,
|
|
188
|
+
convention: label.convention
|
|
189
|
+
)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def metadata_to_canonical(cml_md)
|
|
193
|
+
return nil unless cml_md
|
|
194
|
+
|
|
195
|
+
Model::Metadata.new(
|
|
196
|
+
id: cml_md.id,
|
|
197
|
+
name: cml_md.name,
|
|
198
|
+
content: cml_md.content,
|
|
199
|
+
convention: cml_md.convention,
|
|
200
|
+
title: cml_md.title
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def metadata_from_canonical(md)
|
|
205
|
+
return nil unless md
|
|
206
|
+
|
|
207
|
+
Cml::Metadata.new(
|
|
208
|
+
id: md.id,
|
|
209
|
+
name: md.name,
|
|
210
|
+
content: md.content,
|
|
211
|
+
convention: md.convention,
|
|
212
|
+
title: md.title
|
|
213
|
+
)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def formula_to_canonical(cml_formula)
|
|
217
|
+
return nil unless cml_formula
|
|
218
|
+
|
|
219
|
+
Model::Formula.new(
|
|
220
|
+
id: cml_formula.id,
|
|
221
|
+
concise: cml_formula.concise,
|
|
222
|
+
inline: cml_formula.inline,
|
|
223
|
+
formal_charge: cml_formula.formal_charge,
|
|
224
|
+
count: cml_formula.count,
|
|
225
|
+
title: cml_formula.title,
|
|
226
|
+
convention: cml_formula.convention,
|
|
227
|
+
dict_ref: cml_formula.dict_ref
|
|
228
|
+
)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def formula_from_canonical(formula)
|
|
232
|
+
return nil unless formula
|
|
233
|
+
|
|
234
|
+
Cml::Formula.new(
|
|
235
|
+
id: formula.id,
|
|
236
|
+
concise: formula.concise,
|
|
237
|
+
inline: formula.inline,
|
|
238
|
+
formal_charge: formula.formal_charge,
|
|
239
|
+
count: formula.count,
|
|
240
|
+
title: formula.title,
|
|
241
|
+
convention: formula.convention,
|
|
242
|
+
dict_ref: formula.dict_ref
|
|
243
|
+
)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
private
|
|
247
|
+
|
|
248
|
+
def property_value_to_canonical(cml_prop)
|
|
249
|
+
value_container_to_canonical(cml_prop.scalar) ||
|
|
250
|
+
value_container_to_canonical(cml_prop.array) ||
|
|
251
|
+
value_container_to_canonical(cml_prop.matrix)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def parameter_value_to_canonical(cml_param)
|
|
255
|
+
value_container_to_canonical(cml_param.scalar) ||
|
|
256
|
+
value_container_to_canonical(cml_param.array) ||
|
|
257
|
+
value_container_to_canonical(cml_param.matrix)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
extend ValueTranslations::ClassMethods
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chemicalml
|
|
4
|
+
module Cml
|
|
5
|
+
# Adapter between the canonical `Chemicalml::Model` and the CML XML
|
|
6
|
+
# wire-format layer (`Chemicalml::Cml::*` lutaml-model classes).
|
|
7
|
+
#
|
|
8
|
+
# Pure transformation. No I/O. Two class methods, one per
|
|
9
|
+
# direction. Adding a new CML element means updating the
|
|
10
|
+
# translator's mapping rules; the canonical classes and the CML
|
|
11
|
+
# wire classes stay independent.
|
|
12
|
+
class Translator
|
|
13
|
+
autoload :ValueTranslations, "chemicalml/cml/translator/value_translations"
|
|
14
|
+
|
|
15
|
+
# CML wire format -> canonical. Accepts either Schema3 or
|
|
16
|
+
# Schema24 wire documents; dispatches based on class.
|
|
17
|
+
def self.to_canonical(document)
|
|
18
|
+
Model::Document.new(
|
|
19
|
+
molecules: document.molecules.map { |m| molecule_to_canonical(m) },
|
|
20
|
+
reactions: document.reactions.map { |r| reaction_to_canonical(r) }
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Canonical -> CML wire format. `schema:` selects the target
|
|
25
|
+
# version (`:schema3` default, or `:schema24`).
|
|
26
|
+
def self.from_canonical(document, schema: :schema3)
|
|
27
|
+
wire_class = document_class_for(schema)
|
|
28
|
+
wire_class.new(
|
|
29
|
+
molecules: document.molecules.map { |m| molecule_from_canonical(m) },
|
|
30
|
+
reactions: document.reactions.map { |r| reaction_from_canonical(r) }
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.document_class_for(schema)
|
|
35
|
+
case schema.to_sym
|
|
36
|
+
when :schema3 then Chemicalml::Cml::Schema3::Document
|
|
37
|
+
when :schema24 then Chemicalml::Cml::Schema24::Document
|
|
38
|
+
else
|
|
39
|
+
raise ArgumentError, "unsupported schema: #{schema.inspect}"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
private_class_method :document_class_for
|
|
43
|
+
|
|
44
|
+
# -- CML -> canonical --------------------------------------------
|
|
45
|
+
|
|
46
|
+
def self.molecule_to_canonical(cml_mol)
|
|
47
|
+
Model::Molecule.new(
|
|
48
|
+
id: cml_mol.id,
|
|
49
|
+
atoms: cml_mol.atom_array&.atoms&.map { |a| atom_to_canonical(a) } || [],
|
|
50
|
+
bonds: cml_mol.bond_array&.bonds&.map { |b| bond_to_canonical(b) } || [],
|
|
51
|
+
names: cml_mol.names.map { |n| Model::Name.new(content: n.content, convention: n.convention, dict_ref: n.dict_ref) },
|
|
52
|
+
identifiers: cml_mol.identifiers.map { |i| Model::Identifier.new(value: i.value, convention: i.convention, dict_ref: i.dict_ref) },
|
|
53
|
+
count: cml_mol.count,
|
|
54
|
+
formal_charge: cml_mol.formal_charge,
|
|
55
|
+
title: cml_mol.title
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.atom_to_canonical(cml_atom)
|
|
60
|
+
Model::Atom.new(
|
|
61
|
+
id: cml_atom.id,
|
|
62
|
+
element: cml_atom.element_type,
|
|
63
|
+
formal_charge: cml_atom.formal_charge,
|
|
64
|
+
isotope: cml_atom.isotope,
|
|
65
|
+
count: cml_atom.count,
|
|
66
|
+
hydrogen_count: cml_atom.hydrogen_count,
|
|
67
|
+
spin_multiplicity: cml_atom.spin_multiplicity,
|
|
68
|
+
title: cml_atom.title
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.bond_to_canonical(cml_bond)
|
|
73
|
+
Model::Bond.new(
|
|
74
|
+
id: cml_bond.id,
|
|
75
|
+
atom_refs: cml_bond.atom_refs2&.split(" ") || [],
|
|
76
|
+
kind: cml_order_to_kind(cml_bond.order)
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.reaction_to_canonical(cml_rxn)
|
|
81
|
+
Model::Reaction.new(
|
|
82
|
+
id: cml_rxn.id,
|
|
83
|
+
reactant_list: reactant_list_to_canonical(cml_rxn.reactant_list),
|
|
84
|
+
product_list: product_list_to_canonical(cml_rxn.product_list),
|
|
85
|
+
arrow: type_to_arrow(cml_rxn.type || cml_rxn.title),
|
|
86
|
+
title: cml_rxn.title,
|
|
87
|
+
type: cml_rxn.type
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.reactant_list_to_canonical(cml_list)
|
|
92
|
+
return Model::ReactantList.new unless cml_list
|
|
93
|
+
|
|
94
|
+
Model::ReactantList.new(
|
|
95
|
+
reactants: cml_list.reactants.map do |r|
|
|
96
|
+
Model::Reactant.new(
|
|
97
|
+
substance: Model::Substance.new(
|
|
98
|
+
molecule: molecule_to_canonical(r.substance.molecule),
|
|
99
|
+
title: r.substance.title,
|
|
100
|
+
role: r.substance.role
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def self.product_list_to_canonical(cml_list)
|
|
108
|
+
return Model::ProductList.new unless cml_list
|
|
109
|
+
|
|
110
|
+
Model::ProductList.new(
|
|
111
|
+
products: cml_list.products.map do |p|
|
|
112
|
+
Model::Product.new(
|
|
113
|
+
substance: Model::Substance.new(
|
|
114
|
+
molecule: molecule_to_canonical(p.substance.molecule),
|
|
115
|
+
title: p.substance.title,
|
|
116
|
+
role: p.substance.role
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
end
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# -- Canonical -> CML --------------------------------------------
|
|
124
|
+
|
|
125
|
+
def self.molecule_from_canonical(mol)
|
|
126
|
+
Cml::Molecule.new(
|
|
127
|
+
id: mol.id,
|
|
128
|
+
atom_array: mol.atoms.empty? ? nil : Cml::AtomArray.new(
|
|
129
|
+
atoms: mol.atoms.map { |a| atom_from_canonical(a) }
|
|
130
|
+
),
|
|
131
|
+
bond_array: mol.bonds.empty? ? nil : Cml::BondArray.new(
|
|
132
|
+
bonds: mol.bonds.map { |b| bond_from_canonical(b) }
|
|
133
|
+
),
|
|
134
|
+
names: mol.names.map { |n| Cml::Name.new(content: n.content, convention: n.convention, dict_ref: n.dict_ref) },
|
|
135
|
+
identifiers: mol.identifiers.map { |i| Cml::Identifier.new(value: i.value, convention: i.convention, dict_ref: i.dict_ref) },
|
|
136
|
+
count: mol.count,
|
|
137
|
+
formal_charge: mol.formal_charge,
|
|
138
|
+
title: mol.title
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.atom_from_canonical(atom)
|
|
143
|
+
Cml::Atom.new(
|
|
144
|
+
id: atom.id,
|
|
145
|
+
element_type: atom.element,
|
|
146
|
+
formal_charge: atom.formal_charge,
|
|
147
|
+
isotope: atom.isotope,
|
|
148
|
+
count: atom.count,
|
|
149
|
+
hydrogen_count: atom.hydrogen_count,
|
|
150
|
+
spin_multiplicity: atom.spin_multiplicity,
|
|
151
|
+
title: atom.title
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def self.bond_from_canonical(bond)
|
|
156
|
+
Cml::Bond.new(
|
|
157
|
+
id: bond.id,
|
|
158
|
+
atom_refs2: bond.atom_refs.join(" "),
|
|
159
|
+
order: bond.cml_order
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def self.reaction_from_canonical(rxn)
|
|
164
|
+
Cml::Reaction.new(
|
|
165
|
+
id: rxn.id,
|
|
166
|
+
title: rxn.title || rxn.arrow.to_s,
|
|
167
|
+
type: rxn.type || rxn.arrow.to_s,
|
|
168
|
+
reactant_list: reactant_list_from_canonical(rxn.reactant_list),
|
|
169
|
+
product_list: product_list_from_canonical(rxn.product_list)
|
|
170
|
+
)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self.reactant_list_from_canonical(list)
|
|
174
|
+
Cml::ReactantList.new(
|
|
175
|
+
reactants: list.reactants.map do |r|
|
|
176
|
+
Cml::Reactant.new(
|
|
177
|
+
substance: Cml::Substance.new(
|
|
178
|
+
molecule: molecule_from_canonical(r.substance.molecule),
|
|
179
|
+
title: r.substance.title,
|
|
180
|
+
role: r.substance.role
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
end
|
|
184
|
+
)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def self.product_list_from_canonical(list)
|
|
188
|
+
Cml::ProductList.new(
|
|
189
|
+
products: list.products.map do |p|
|
|
190
|
+
Cml::Product.new(
|
|
191
|
+
substance: Cml::Substance.new(
|
|
192
|
+
molecule: molecule_from_canonical(p.substance.molecule),
|
|
193
|
+
title: p.substance.title,
|
|
194
|
+
role: p.substance.role
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
end
|
|
198
|
+
)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# -- Lookup tables -----------------------------------------------
|
|
202
|
+
|
|
203
|
+
ORDER_TO_KIND = {
|
|
204
|
+
"S" => :single, "D" => :double, "T" => :triple,
|
|
205
|
+
"Q" => :quadruple, "A" => :aromatic, "W" => :wedge,
|
|
206
|
+
"H" => :hash, "DG" => :dative, "V" => :wavy
|
|
207
|
+
}.freeze
|
|
208
|
+
|
|
209
|
+
TYPE_TO_ARROW = {
|
|
210
|
+
"forward" => :forward,
|
|
211
|
+
"reverse" => :reverse,
|
|
212
|
+
"equilibrium" => :equilibrium,
|
|
213
|
+
"resonance" => :resonance
|
|
214
|
+
}.freeze
|
|
215
|
+
|
|
216
|
+
def self.cml_order_to_kind(order)
|
|
217
|
+
return :single if order.nil?
|
|
218
|
+
|
|
219
|
+
ORDER_TO_KIND.fetch(order.upcase, :single)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def self.type_to_arrow(value)
|
|
223
|
+
return :forward if value.nil?
|
|
224
|
+
|
|
225
|
+
TYPE_TO_ARROW.fetch(value.to_s.downcase, :forward)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
private_class_method :cml_order_to_kind, :type_to_arrow
|
|
229
|
+
|
|
230
|
+
extend ValueTranslations::ClassMethods
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Backward-compatible alias. New code should reference the versioned
|
|
4
|
+
# class directly: Chemicalml::Cml::Schema3::Unit.
|
|
5
|
+
module Chemicalml
|
|
6
|
+
module Cml
|
|
7
|
+
remove_const(:Unit) if const_defined?(:Unit, false)
|
|
8
|
+
const_set(:Unit, Chemicalml::Cml::Schema3::Unit)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Backward-compatible alias. New code should reference the versioned
|
|
4
|
+
# class directly: Chemicalml::Cml::Schema3::UnitList.
|
|
5
|
+
module Chemicalml
|
|
6
|
+
module Cml
|
|
7
|
+
remove_const(:UnitList) if const_defined?(:UnitList, false)
|
|
8
|
+
const_set(:UnitList, Chemicalml::Cml::Schema3::UnitList)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Backward-compatible alias. New code should reference the versioned
|
|
4
|
+
# class directly: Chemicalml::Cml::Schema3::UnitType.
|
|
5
|
+
module Chemicalml
|
|
6
|
+
module Cml
|
|
7
|
+
remove_const(:UnitType) if const_defined?(:UnitType, false)
|
|
8
|
+
const_set(:UnitType, Chemicalml::Cml::Schema3::UnitType)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Backward-compatible alias. New code should reference the versioned
|
|
4
|
+
# class directly: Chemicalml::Cml::Schema3::UnitTypeList.
|
|
5
|
+
module Chemicalml
|
|
6
|
+
module Cml
|
|
7
|
+
remove_const(:UnitTypeList) if const_defined?(:UnitTypeList, false)
|
|
8
|
+
const_set(:UnitTypeList, Chemicalml::Cml::Schema3::UnitTypeList)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chemicalml
|
|
4
|
+
module Cml
|
|
5
|
+
# Marker mixin included by every wire class. Provides a uniform
|
|
6
|
+
# interface the convention-constraint walker relies on:
|
|
7
|
+
#
|
|
8
|
+
# - `wire_children` returns the child wire nodes
|
|
9
|
+
# - `node_id` returns the id attribute or `nil`
|
|
10
|
+
# - `element_name` returns the XML tag name
|
|
11
|
+
#
|
|
12
|
+
# All three use lutaml-model's attribute registry — no duck typing.
|
|
13
|
+
# A wire class that doesn't declare an `:id` attribute simply has
|
|
14
|
+
# `node_id` return `nil`.
|
|
15
|
+
module Visitable
|
|
16
|
+
def wire_children
|
|
17
|
+
declared_attribute_names.flat_map do |name|
|
|
18
|
+
collect_wire_nodes(public_send(name))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def node_id
|
|
23
|
+
return id if declared_attribute?(:id)
|
|
24
|
+
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def element_name
|
|
29
|
+
xml_mapping = self.class.mappings[:xml]
|
|
30
|
+
root = xml_mapping && xml_mapping.root
|
|
31
|
+
root && root.name || self.class.name.split("::").last
|
|
32
|
+
rescue StandardError
|
|
33
|
+
self.class.name.split("::").last
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def collect_wire_nodes(value)
|
|
37
|
+
return [] if value.nil?
|
|
38
|
+
|
|
39
|
+
if value.is_a?(::Array)
|
|
40
|
+
value.select { |v| wire_node?(v) }
|
|
41
|
+
elsif wire_node?(value)
|
|
42
|
+
[value]
|
|
43
|
+
else
|
|
44
|
+
[]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def wire_node?(value)
|
|
49
|
+
value.is_a?(Lutaml::Model::Serializable)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def declared_attribute_names
|
|
53
|
+
self.class.model.attributes.keys
|
|
54
|
+
rescue StandardError
|
|
55
|
+
[]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def declared_attribute?(name)
|
|
59
|
+
self.class.model.attributes.key?(name)
|
|
60
|
+
rescue StandardError
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chemicalml
|
|
4
|
+
module Cml
|
|
5
|
+
# Macro for defining a schema version's wire classes without
|
|
6
|
+
# writing 35+ boilerplate files. Each generated class:
|
|
7
|
+
#
|
|
8
|
+
# - subclasses `Lutaml::Model::Serializable`
|
|
9
|
+
# - includes the corresponding `Base::*` mixin (shared attribute
|
|
10
|
+
# declarations and xml mapping)
|
|
11
|
+
# - includes `Cml::Visitable` (uniform interface for the
|
|
12
|
+
# constraint walker)
|
|
13
|
+
# - defines `self.lutaml_default_register` returning the
|
|
14
|
+
# provided context_id
|
|
15
|
+
#
|
|
16
|
+
# Usage:
|
|
17
|
+
#
|
|
18
|
+
# Chemicalml::Cml.define_wire_classes(
|
|
19
|
+
# namespace: Chemicalml::Cml::Schema3,
|
|
20
|
+
# context_id: :chemicalml_schema3
|
|
21
|
+
# )
|
|
22
|
+
#
|
|
23
|
+
# Pass `except:` to skip elements (e.g. Schema 2.4 lacks <module>):
|
|
24
|
+
#
|
|
25
|
+
# Chemicalml::Cml.define_wire_classes(
|
|
26
|
+
# namespace: Chemicalml::Cml::Schema24,
|
|
27
|
+
# context_id: :chemicalml_schema24,
|
|
28
|
+
# except: Chemicalml::Cml::Elements::SCHEMA3_ONLY
|
|
29
|
+
# )
|
|
30
|
+
def self.define_wire_classes(namespace:, context_id:, except: [])
|
|
31
|
+
skip = except.to_set
|
|
32
|
+
Elements::ALL.each_key do |class_name|
|
|
33
|
+
next if skip.include?(class_name)
|
|
34
|
+
|
|
35
|
+
base_module = Base.const_get(class_name)
|
|
36
|
+
klass = Class.new(Lutaml::Model::Serializable) do
|
|
37
|
+
include base_module
|
|
38
|
+
include Chemicalml::Cml::Visitable
|
|
39
|
+
end
|
|
40
|
+
klass.define_singleton_method(:lutaml_default_register) { context_id }
|
|
41
|
+
namespace.const_set(class_name, klass)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|