opencdd 0.2.3 → 0.3.1
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 +4 -4
- data/bin/lint-no-raw-mdc +1 -0
- data/lib/opencdd/cddal/builder.rb +10 -80
- data/lib/opencdd/cddal/import_pipeline.rb +97 -0
- data/lib/opencdd/cddal.rb +1 -0
- data/lib/opencdd/condition.rb +65 -0
- data/lib/opencdd/entity/name_synthesizer.rb +46 -0
- data/lib/opencdd/entity/yaml.rb +95 -44
- data/lib/opencdd/entity.rb +1 -0
- data/lib/opencdd/parcel/sheet_schema.rb +3 -64
- data/lib/opencdd/property.rb +6 -13
- data/lib/opencdd/property_ids.rb +52 -0
- data/lib/opencdd/relation.rb +2 -2
- data/lib/opencdd/unit.rb +4 -4
- data/lib/opencdd/validator/condition_rule.rb +3 -0
- data/lib/opencdd/version.rb +1 -1
- data/lib/opencdd/view_control.rb +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c582aa6a0bf79bedf583a586f97c1c308852b53d4efc9972b3bb883a2be425fc
|
|
4
|
+
data.tar.gz: 1195b6615ee045c3c1ac63f237ccdb930d80838db9dbe33677216e271748accc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1cbdf2e8832ccd86b95fcfc6789d8d9dfe4be656a27f7b4cac4cb854ea6f224153f5aa8cca521362f364954e123e0c50d3424da3daf031cd73f1974823794cb9
|
|
7
|
+
data.tar.gz: 072c326fba5a5807249b7ea79eda95c31fc42384c80de750dba20c741de0601c8c67afe61e9b58a27e594797c68b12cbb38b4166c0f56ce547130e610625c80c
|
data/bin/lint-no-raw-mdc
CHANGED
|
@@ -24,7 +24,7 @@ module Opencdd
|
|
|
24
24
|
:source_file, :loaded_modules
|
|
25
25
|
|
|
26
26
|
def initialize(database = nil, resolver: nil, source_file: nil,
|
|
27
|
-
loaded_modules: nil, loading_stack: nil)
|
|
27
|
+
loaded_modules: nil, loading_stack: nil, qualified_table: nil)
|
|
28
28
|
@database = database || Opencdd::Database.new
|
|
29
29
|
@resolver = resolver || Opencdd::Cddal.default_resolver
|
|
30
30
|
@source_file = source_file
|
|
@@ -32,7 +32,7 @@ module Opencdd
|
|
|
32
32
|
@loading_stack = loading_stack || []
|
|
33
33
|
@alias_table = Opencdd::AliasTable.new(defaults: true)
|
|
34
34
|
@symbol_table = {}
|
|
35
|
-
@qualified_table = {}
|
|
35
|
+
@qualified_table = qualified_table || {}
|
|
36
36
|
@instance_decls = []
|
|
37
37
|
@meta_class_overrides = {}
|
|
38
38
|
end
|
|
@@ -108,84 +108,14 @@ module Opencdd
|
|
|
108
108
|
# names are accessible without qualification.
|
|
109
109
|
|
|
110
110
|
def apply_import_declarations(document)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# graceful-degradation behavior CDDAL authors expect for
|
|
120
|
-
# cross-dictionary URLs.
|
|
121
|
-
return if canonical.nil?
|
|
122
|
-
return if @loaded_modules.key?(canonical)
|
|
123
|
-
check_cycle!(canonical, decl.specifier)
|
|
124
|
-
|
|
125
|
-
@loading_stack.push(canonical)
|
|
126
|
-
sub_doc = Opencdd::Cddal::Parser.parse(source)
|
|
127
|
-
Builder.new(@database, resolver: @resolver, source_file: canonical,
|
|
128
|
-
loaded_modules: @loaded_modules,
|
|
129
|
-
loading_stack: @loading_stack)
|
|
130
|
-
.build(sub_doc)
|
|
131
|
-
@loading_stack.pop
|
|
132
|
-
@loaded_modules[canonical] = true
|
|
133
|
-
|
|
134
|
-
# Symbol scoping is applied AFTER the sub-document is built,
|
|
135
|
-
# so the named entities exist in @database by the time we
|
|
136
|
-
# look them up.
|
|
137
|
-
apply_import_scope(decl, canonical)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def resolve_specifier(specifier)
|
|
141
|
-
@resolver.resolve(specifier, importing_file: @source_file)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def check_cycle!(canonical, specifier)
|
|
145
|
-
return unless @loading_stack.include?(canonical)
|
|
146
|
-
cycle = @loading_stack.dup
|
|
147
|
-
cycle << canonical
|
|
148
|
-
raise Opencdd::Cddal::ImportError,
|
|
149
|
-
"circular CDDAL import detected: #{cycle.join(' → ')} " \
|
|
150
|
-
"(originally imported as #{specifier.inspect})"
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def apply_import_scope(decl, _canonical)
|
|
154
|
-
case decl.kind
|
|
155
|
-
when :bare
|
|
156
|
-
# Nothing to do — bare imports leave the sub-document's
|
|
157
|
-
# names in the shared @database symbol table.
|
|
158
|
-
when :qualified
|
|
159
|
-
register_qualified_symbols(decl.qualifier)
|
|
160
|
-
when :selective
|
|
161
|
-
register_selective_symbols(decl.imported_names)
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def register_qualified_symbols(qualifier)
|
|
166
|
-
@database.entities.each do |entity|
|
|
167
|
-
name = entity_alias_name(entity)
|
|
168
|
-
next unless name
|
|
169
|
-
qualified = "#{qualifier}.#{name}"
|
|
170
|
-
@qualified_table[qualified] = entity
|
|
171
|
-
@database.register_symbol(qualified, entity)
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def register_selective_symbols(imported_names)
|
|
176
|
-
imported_names.each do |imported|
|
|
177
|
-
entity = @database.resolve_reference(imported.name)
|
|
178
|
-
next unless entity
|
|
179
|
-
# Register in the parent Database's symbol table so the
|
|
180
|
-
# renamed name resolves during link phase.
|
|
181
|
-
@database.register_symbol(imported.local_name, entity)
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def entity_alias_name(entity)
|
|
186
|
-
code = entity.code
|
|
187
|
-
return code if code && !code.empty?
|
|
188
|
-
entity.preferred_name.to_s
|
|
111
|
+
Opencdd::Cddal::ImportPipeline.new(
|
|
112
|
+
database: @database,
|
|
113
|
+
resolver: @resolver,
|
|
114
|
+
source_file: @source_file,
|
|
115
|
+
loaded_modules: @loaded_modules,
|
|
116
|
+
loading_stack: @loading_stack,
|
|
117
|
+
qualified_table: @qualified_table,
|
|
118
|
+
).process(document.import_declarations)
|
|
189
119
|
end
|
|
190
120
|
|
|
191
121
|
def register_instance_symbols(document)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Opencdd
|
|
4
|
+
module Cddal
|
|
5
|
+
# Handles CDDAL module imports: resolution, cycle detection,
|
|
6
|
+
# recursive sub-document building, and symbol scoping.
|
|
7
|
+
#
|
|
8
|
+
# Extracted from Builder so the import pipeline has its own
|
|
9
|
+
# testable interface. Builder creates an ImportPipeline and
|
|
10
|
+
# delegates +apply_import_declarations+ to it.
|
|
11
|
+
#
|
|
12
|
+
# The pipeline holds shared mutable state (loaded_modules,
|
|
13
|
+
# loading_stack) that persists across recursive sub-builds.
|
|
14
|
+
# This state is passed by reference from the parent Builder
|
|
15
|
+
# so all levels of the import tree share the same cycle
|
|
16
|
+
# tracking.
|
|
17
|
+
class ImportPipeline
|
|
18
|
+
def initialize(database:, resolver:, source_file:, loaded_modules:, loading_stack:, qualified_table:)
|
|
19
|
+
@database = database
|
|
20
|
+
@resolver = resolver
|
|
21
|
+
@source_file = source_file
|
|
22
|
+
@loaded_modules = loaded_modules
|
|
23
|
+
@loading_stack = loading_stack
|
|
24
|
+
@qualified_table = qualified_table
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def process(import_declarations)
|
|
28
|
+
import_declarations.each { |decl| process_import(decl) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def process_import(decl)
|
|
34
|
+
canonical, source = @resolver.resolve(decl.specifier, importing_file: @source_file)
|
|
35
|
+
return if canonical.nil?
|
|
36
|
+
return if @loaded_modules.key?(canonical)
|
|
37
|
+
check_cycle!(canonical, decl.specifier)
|
|
38
|
+
|
|
39
|
+
@loading_stack.push(canonical)
|
|
40
|
+
sub_doc = Opencdd::Cddal::Parser.parse(source)
|
|
41
|
+
Builder.new(@database, resolver: @resolver, source_file: canonical,
|
|
42
|
+
loaded_modules: @loaded_modules,
|
|
43
|
+
loading_stack: @loading_stack,
|
|
44
|
+
qualified_table: @qualified_table)
|
|
45
|
+
.build(sub_doc)
|
|
46
|
+
@loading_stack.pop
|
|
47
|
+
@loaded_modules[canonical] = true
|
|
48
|
+
|
|
49
|
+
apply_import_scope(decl)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def check_cycle!(canonical, specifier)
|
|
53
|
+
return unless @loading_stack.include?(canonical)
|
|
54
|
+
cycle = @loading_stack.dup
|
|
55
|
+
cycle << canonical
|
|
56
|
+
raise Opencdd::Cddal::ImportError,
|
|
57
|
+
"circular CDDAL import detected: #{cycle.join(' → ')} " \
|
|
58
|
+
"(originally imported as #{specifier.inspect})"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def apply_import_scope(decl)
|
|
62
|
+
case decl.kind
|
|
63
|
+
when :bare
|
|
64
|
+
# Bare imports leave names in the shared symbol table.
|
|
65
|
+
when :qualified
|
|
66
|
+
register_qualified_symbols(decl.qualifier)
|
|
67
|
+
when :selective
|
|
68
|
+
register_selective_symbols(decl.imported_names)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def register_qualified_symbols(qualifier)
|
|
73
|
+
@database.entities.each do |entity|
|
|
74
|
+
name = entity_alias_name(entity)
|
|
75
|
+
next unless name
|
|
76
|
+
qualified = "#{qualifier}.#{name}"
|
|
77
|
+
@qualified_table[qualified] = entity
|
|
78
|
+
@database.register_symbol(qualified, entity)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def register_selective_symbols(imported_names)
|
|
83
|
+
imported_names.each do |imported|
|
|
84
|
+
entity = @database.resolve_reference(imported.name)
|
|
85
|
+
next unless entity
|
|
86
|
+
@database.register_symbol(imported.local_name, entity)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def entity_alias_name(entity)
|
|
91
|
+
code = entity.code
|
|
92
|
+
return code if code && !code.empty?
|
|
93
|
+
entity.preferred_name.to_s
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/opencdd/cddal.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Opencdd
|
|
|
7
7
|
autoload :Parser, "opencdd/cddal/parser"
|
|
8
8
|
autoload :GeneratedParser, "opencdd/cddal/generated_parser"
|
|
9
9
|
autoload :Builder, "opencdd/cddal/builder"
|
|
10
|
+
autoload :ImportPipeline, "opencdd/cddal/import_pipeline"
|
|
10
11
|
autoload :Serializer, "opencdd/cddal/serializer"
|
|
11
12
|
autoload :Resolver, "opencdd/cddal/resolver"
|
|
12
13
|
autoload :Fetcher, "opencdd/cddal/fetcher"
|
data/lib/opencdd/condition.rb
CHANGED
|
@@ -13,6 +13,12 @@ module Opencdd
|
|
|
13
13
|
(?<right>.+)
|
|
14
14
|
\z/x.freeze
|
|
15
15
|
|
|
16
|
+
# A single bare token (IRDI or short code) without internal whitespace.
|
|
17
|
+
# Used to detect class-reference conditions of the form
|
|
18
|
+
# `0112/2///62683#ACE132` and distinguish them from malformed input
|
|
19
|
+
# like "no operator here" (which has internal whitespace).
|
|
20
|
+
SINGLE_TOKEN_PATTERN = /\A\S+\z/.freeze
|
|
21
|
+
|
|
16
22
|
attr_reader :left, :operator, :right
|
|
17
23
|
|
|
18
24
|
def initialize(left, operator, right)
|
|
@@ -24,6 +30,10 @@ module Opencdd
|
|
|
24
30
|
@right = right
|
|
25
31
|
end
|
|
26
32
|
|
|
33
|
+
def class_reference?
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
|
|
27
37
|
def set?
|
|
28
38
|
@right.is_a?(Set)
|
|
29
39
|
end
|
|
@@ -76,6 +86,12 @@ module Opencdd
|
|
|
76
86
|
op = Regexp.last_match(:op)
|
|
77
87
|
raw_right = Regexp.last_match(:right).strip
|
|
78
88
|
new(left, op, parse_rhs(raw_right))
|
|
89
|
+
elsif s =~ SET_PATTERN
|
|
90
|
+
body = Regexp.last_match(:body)
|
|
91
|
+
elements = body.split(/[,\s]+/).map(&:strip).reject(&:empty?)
|
|
92
|
+
ClassReference.new(irdis: elements)
|
|
93
|
+
elsif SINGLE_TOKEN_PATTERN.match?(s)
|
|
94
|
+
ClassReference.new(irdis: [s])
|
|
79
95
|
else
|
|
80
96
|
raise ArgumentError, "invalid condition expression: #{s.inspect}"
|
|
81
97
|
end
|
|
@@ -116,5 +132,54 @@ module Opencdd
|
|
|
116
132
|
def normalize_for_eq(value)
|
|
117
133
|
value.is_a?(Set) ? value.to_a.sort : value
|
|
118
134
|
end
|
|
135
|
+
|
|
136
|
+
# A condition of the form `{0112/2///62683#ACE132}` or a bare
|
|
137
|
+
# `0112/2///62683#ACE132` — meaning "this property applies when the
|
|
138
|
+
# host class is one of the listed IRDIs". IEC 62683 stores property
|
|
139
|
+
# conditions this way; the regular boolean-expression grammar in
|
|
140
|
+
# +Condition+ cannot represent it.
|
|
141
|
+
class ClassReference < Condition
|
|
142
|
+
attr_reader :irdis
|
|
143
|
+
|
|
144
|
+
# The binding key (string or symbol) consulted by +#satisfied_by?+
|
|
145
|
+
# to discover the host class IRDI. Callers that resolve the host
|
|
146
|
+
# class via a different key should override +satisfied_by?+.
|
|
147
|
+
HOST_CLASS_KEYS = [:class, :host_class, "class", "host_class"].freeze
|
|
148
|
+
|
|
149
|
+
def initialize(irdis:)
|
|
150
|
+
@irdis = Array(irdis).map(&:to_s)
|
|
151
|
+
@left = nil
|
|
152
|
+
@operator = nil
|
|
153
|
+
@right = nil
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def class_reference?
|
|
157
|
+
true
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def set?
|
|
161
|
+
@irdis.size > 1
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def satisfied_by?(bindings)
|
|
165
|
+
hash = bindings.is_a?(Hash) ? bindings : bindings.to_h
|
|
166
|
+
actual = HOST_CLASS_KEYS.map { |k| hash[k] }.compact.first
|
|
167
|
+
return true if actual.nil?
|
|
168
|
+
@irdis.any? { |irdi| actual.to_s == irdi }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def to_s
|
|
172
|
+
@irdis.size == 1 ? @irdis.first : "{#{@irdis.join(', ')}}"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def ==(other)
|
|
176
|
+
other.is_a?(ClassReference) && Set.new(@irdis) == Set.new(other.irdis)
|
|
177
|
+
end
|
|
178
|
+
alias_method :eql?, :==
|
|
179
|
+
|
|
180
|
+
def hash
|
|
181
|
+
Set.new(@irdis).hash
|
|
182
|
+
end
|
|
183
|
+
end
|
|
119
184
|
end
|
|
120
185
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Opencdd
|
|
4
|
+
class Entity
|
|
5
|
+
# Reverse name-to-ID resolution for Parcel sheets that omit the
|
|
6
|
+
# #PROPERTY_ID directive row. Some cdd.iec.ch export formats
|
|
7
|
+
# (notably RELATION exports) include only #PROPERTY_NAME.en,
|
|
8
|
+
# leaving the importer unable to map column positions to property
|
|
9
|
+
# IDs. NameSynthesizer bridges that gap using the IEC 62656-1
|
|
10
|
+
# defined column names.
|
|
11
|
+
#
|
|
12
|
+
# Extracted from SheetSchema so SheetSchema focuses on header
|
|
13
|
+
# parsing + Column construction. Name synthesis is a separate
|
|
14
|
+
# concern with its own test surface.
|
|
15
|
+
#
|
|
16
|
+
# The name→ID table itself lives in Opencdd::PropertyIds::IEC_COLUMN_NAMES
|
|
17
|
+
# (the lint-exempt SSOT). NAME_TO_PROPERTY_ID is kept here as a
|
|
18
|
+
# back-compat alias so existing callers see no public-API change.
|
|
19
|
+
module NameSynthesizer
|
|
20
|
+
NAME_TO_PROPERTY_ID = Opencdd::PropertyIds::IEC_COLUMN_NAMES
|
|
21
|
+
|
|
22
|
+
# Given a PROPERTY_NAME directive row (Array of name strings),
|
|
23
|
+
# returns a parallel Array of property IDs (or nil where the
|
|
24
|
+
# name is unrecognized). Language suffixes (.EN, .FR) are
|
|
25
|
+
# stripped for lookup and re-appended to the synthesized ID.
|
|
26
|
+
#
|
|
27
|
+
# synthesize(["Code", "PreferredName.EN", "Unknown"])
|
|
28
|
+
# => ["MDC_P001_5", "MDC_P004.en", nil]
|
|
29
|
+
def self.synthesize(name_values)
|
|
30
|
+
Array.new(name_values.size) do |idx|
|
|
31
|
+
val = name_values[idx]
|
|
32
|
+
next nil if val.nil? || val.to_s.strip.empty?
|
|
33
|
+
raw = val.to_s.strip
|
|
34
|
+
if raw =~ /\A(.+)\.([A-Za-z]{2})\z/
|
|
35
|
+
base = $1
|
|
36
|
+
lang = $2
|
|
37
|
+
pid = NAME_TO_PROPERTY_ID[base]
|
|
38
|
+
pid ? "#{pid}.#{lang.downcase}" : nil
|
|
39
|
+
else
|
|
40
|
+
NAME_TO_PROPERTY_ID[raw]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/opencdd/entity/yaml.rb
CHANGED
|
@@ -96,55 +96,52 @@ module Opencdd
|
|
|
96
96
|
# ── Catch-all for unknown properties (lossless) ────────
|
|
97
97
|
attribute :extra, :hash
|
|
98
98
|
|
|
99
|
+
# Fields that should NOT be driven from FieldRegistry in
|
|
100
|
+
# from_entity — they're either identity fields (irdi, code)
|
|
101
|
+
# or catch-all (extra, raw_properties, version_history, etc.)
|
|
102
|
+
# handled separately.
|
|
103
|
+
SKIP_FIELDS = %i[
|
|
104
|
+
raw_properties version_history dates
|
|
105
|
+
source_document_of_definition synonymous_names
|
|
106
|
+
simplified_drawing example time_stamp
|
|
107
|
+
status_level publisher published_in responsible_committee
|
|
108
|
+
change_request_id data_object_identifier
|
|
109
|
+
alternative_unit_irdis domain_of_function_irdis
|
|
110
|
+
formula_language external_solver trigger_event
|
|
111
|
+
domain_element_type codomain_element_type role segment
|
|
112
|
+
super_relation_irdi sgml_representation
|
|
113
|
+
unit_sgml class_value_assignment coded_name
|
|
114
|
+
symbol_in_text constraint type_classification
|
|
115
|
+
applicable_documents imported_documents
|
|
116
|
+
superclass_type_property
|
|
117
|
+
].freeze
|
|
118
|
+
|
|
99
119
|
# ── Conversion: Entity → Entity::Yaml ───────────────────
|
|
120
|
+
# Drives from FieldRegistry — the same SSOT that drives the
|
|
121
|
+
# JSON exporter. Each field's wire_name (from the `as:` DSL
|
|
122
|
+
# option) determines the YAML attribute to set. Adding a new
|
|
123
|
+
# field requires zero changes here if the wire_name matches
|
|
124
|
+
# a declared YAML attribute.
|
|
100
125
|
def self.from_entity(entity)
|
|
101
126
|
attrs = {
|
|
102
127
|
irdi: entity.irdi&.to_s,
|
|
103
128
|
type: entity.type&.to_s,
|
|
104
129
|
code: entity.code,
|
|
105
|
-
guid: entity[Opencdd::PropertyIds::MDC_P066],
|
|
106
|
-
version: entity[Opencdd::PropertyIds::MDC_P002_1],
|
|
107
|
-
revision: entity[Opencdd::PropertyIds::MDC_P002_2],
|
|
108
130
|
}
|
|
109
131
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
attrs[
|
|
123
|
-
attrs[:imported_properties] = entity.read_field(:imported_property_irdis)&.map(&:to_s) || []
|
|
124
|
-
attrs[:sub_class_selection] = entity.read_field(:sub_class_selection_irdis)&.map(&:to_s) || []
|
|
125
|
-
when :property
|
|
126
|
-
attrs[:data_type] = entity.read_field(:parsed_data_type)&.to_s
|
|
127
|
-
attrs[:value_format] = entity.read_field(:parsed_value_format)&.to_s
|
|
128
|
-
attrs[:definition_class] = entity.read_field(:definition_class_irdi)&.to_s
|
|
129
|
-
attrs[:unit] = entity.read_field(:unit_irdi)&.to_s
|
|
130
|
-
attrs[:condition] = entity.read_field(:condition)&.to_s
|
|
131
|
-
attrs[:property_data_element_type] = entity.read_field(:property_data_element_type)&.to_s
|
|
132
|
-
when :unit
|
|
133
|
-
attrs[:unit_structure] = entity.read_field(:structure)
|
|
134
|
-
attrs[:unit_text] = entity.read_field(:text_representation)
|
|
135
|
-
when :value_list
|
|
136
|
-
attrs[:list_type] = entity.read_field(:list_type)&.to_s
|
|
137
|
-
attrs[:code_list] = entity.read_field(:code_list) || []
|
|
138
|
-
attrs[:term_irdis] = entity.read_field(:term_irdis)&.map(&:to_s) || []
|
|
139
|
-
when :value_term
|
|
140
|
-
attrs[:enumeration_code] = entity.read_field(:enumeration_code)
|
|
141
|
-
when :relation
|
|
142
|
-
attrs[:relation_type] = entity.read_field(:relation_type)&.to_s
|
|
143
|
-
attrs[:codomain] = entity.read_field(:codomain_irdi)&.to_s
|
|
144
|
-
attrs[:formula] = entity.read_field(:formula)
|
|
145
|
-
when :view_control
|
|
146
|
-
attrs[:controlled_classes] = entity.read_field(:controlled_class_irdis)&.map(&:to_s) || []
|
|
147
|
-
attrs[:shown_properties] = entity.read_field(:shown_property_irdis)&.map(&:to_s) || []
|
|
132
|
+
declared_attrs = attribute_names
|
|
133
|
+
seen_property_ids = {}
|
|
134
|
+
|
|
135
|
+
Opencdd::Entity::FieldRegistry.fields_for(entity.class).each do |field|
|
|
136
|
+
next if SKIP_FIELDS.include?(field.name)
|
|
137
|
+
next unless declared_attrs.include?(field.wire_name)
|
|
138
|
+
next if field.property_id && seen_property_ids.key?(field.property_id)
|
|
139
|
+
seen_property_ids[field.property_id] = true if field.property_id
|
|
140
|
+
|
|
141
|
+
value = read_field_for_yaml(entity, field)
|
|
142
|
+
next if value.nil?
|
|
143
|
+
|
|
144
|
+
attrs[field.wire_name.to_sym] = value
|
|
148
145
|
end
|
|
149
146
|
|
|
150
147
|
extra = extract_extra(entity)
|
|
@@ -186,10 +183,17 @@ module Opencdd
|
|
|
186
183
|
props[Opencdd::PropertyIds::MDC_P023_1] = unit_text if unit_text
|
|
187
184
|
|
|
188
185
|
props[Opencdd::PropertyIds::MDC_P046] = list_type if list_type
|
|
189
|
-
props[Opencdd::PropertyIds::MDC_P044] = rejoin_set(code_list) if code_list&.any?
|
|
190
186
|
props[Opencdd::PropertyIds::MDC_P043] = rejoin_set(term_irdis) if term_irdis&.any?
|
|
191
187
|
|
|
192
|
-
|
|
188
|
+
# MDC_P044 is overloaded: code_list (value_list, collection)
|
|
189
|
+
# vs enumeration_code (value_term, scalar). Guard by type to
|
|
190
|
+
# prevent the value_term path from clobbering the value_list.
|
|
191
|
+
case type&.to_sym
|
|
192
|
+
when :value_list
|
|
193
|
+
props[Opencdd::PropertyIds::MDC_P044] = rejoin_set(code_list) if code_list&.any?
|
|
194
|
+
when :value_term
|
|
195
|
+
props[Opencdd::PropertyIds::MDC_P044] = enumeration_code if enumeration_code
|
|
196
|
+
end
|
|
193
197
|
|
|
194
198
|
props[Opencdd::PropertyIds::MDC_P200] = relation_type if relation_type
|
|
195
199
|
props[Opencdd::PropertyIds::MDC_P203] = codomain if codomain
|
|
@@ -229,7 +233,7 @@ module Opencdd
|
|
|
229
233
|
MDC_P011 MDC_P010 MDC_P010_1
|
|
230
234
|
MDC_P013 MDC_P014 MDC_P090 MDC_P016
|
|
231
235
|
MDC_P022 MDC_P024 MDC_P021 MDC_P041 MDC_P028 MDC_P020
|
|
232
|
-
MDC_P023 MDC_P023_1
|
|
236
|
+
MDC_P023 MDC_P023_1 MDC_P023_2
|
|
233
237
|
MDC_P046 MDC_P044 MDC_P043
|
|
234
238
|
MDC_P200 MDC_P203 MDC_P204
|
|
235
239
|
EXT_P002 EXT_P003
|
|
@@ -262,6 +266,53 @@ module Opencdd
|
|
|
262
266
|
def rejoin_set(list)
|
|
263
267
|
Opencdd::StructuredValues.rejoin(list)
|
|
264
268
|
end
|
|
269
|
+
|
|
270
|
+
# ── FieldRegistry-driven value conversion ───────────────
|
|
271
|
+
# For multilingual fields, returns the full Hash<lang,text>
|
|
272
|
+
# by scanning @properties for <property_id>.<lang> keys.
|
|
273
|
+
# For scalar/collection fields, reads through the field DSL
|
|
274
|
+
# and converts to YAML-compatible types.
|
|
275
|
+
def self.read_field_for_yaml(entity, field)
|
|
276
|
+
if field.multilingual? && field.property_id
|
|
277
|
+
extract_ml(entity, field.property_id)
|
|
278
|
+
else
|
|
279
|
+
value = entity.read_field(field.name)
|
|
280
|
+
return nil if value.nil?
|
|
281
|
+
field_to_yaml(value, field)
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def self.field_to_yaml(value, field)
|
|
286
|
+
case field.value_kind
|
|
287
|
+
when :synonym_pairs
|
|
288
|
+
return nil if value.nil?
|
|
289
|
+
value.transform_keys(&:to_s)
|
|
290
|
+
when :irdi, :identifier_ref, :class_ref
|
|
291
|
+
value&.to_s
|
|
292
|
+
when :set_of_refs, :string_list
|
|
293
|
+
return nil if value.nil? || value.empty?
|
|
294
|
+
value.map(&:to_s)
|
|
295
|
+
when :string, :date, :date_time, :condition
|
|
296
|
+
value&.to_s
|
|
297
|
+
when :integer
|
|
298
|
+
value
|
|
299
|
+
when :boolean
|
|
300
|
+
value
|
|
301
|
+
else
|
|
302
|
+
case value
|
|
303
|
+
when Array then value.empty? ? nil : value.map(&:to_s)
|
|
304
|
+
when Hash then value.empty? ? nil : value
|
|
305
|
+
else value.to_s
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Returns the list of declared lutaml-model attribute names.
|
|
311
|
+
# Used by from_entity to check if a field's wire_name matches
|
|
312
|
+
# a declared YAML attribute.
|
|
313
|
+
def self.attribute_names
|
|
314
|
+
attributes.map { |name, _| name.to_s }
|
|
315
|
+
end
|
|
265
316
|
end
|
|
266
317
|
end
|
|
267
318
|
end
|
data/lib/opencdd/entity.rb
CHANGED
|
@@ -15,6 +15,7 @@ module Opencdd
|
|
|
15
15
|
autoload :FieldReader, "opencdd/entity/field_reader"
|
|
16
16
|
autoload :VersionHistory, "opencdd/entity/version_history"
|
|
17
17
|
autoload :Yaml, "opencdd/entity/yaml"
|
|
18
|
+
autoload :NameSynthesizer, "opencdd/entity/name_synthesizer"
|
|
18
19
|
|
|
19
20
|
class << self
|
|
20
21
|
# Declare a typed field on this entity class. Defaults for
|
|
@@ -197,57 +197,8 @@ module Opencdd
|
|
|
197
197
|
freeze
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
#
|
|
201
|
-
# #
|
|
202
|
-
# This happens with some export formats (notably RELATION
|
|
203
|
-
# exports from cdd.iec.ch) that omit the PROPERTY_ID row.
|
|
204
|
-
NAME_TO_PROPERTY_ID = {
|
|
205
|
-
"Code" => "MDC_P001_5",
|
|
206
|
-
"Version" => "MDC_P002_1",
|
|
207
|
-
"Revision" => "MDC_P002_2",
|
|
208
|
-
"VersionInitiationDate" => "MDC_P003_1",
|
|
209
|
-
"VersionReleaseDate" => "MDC_P003_2",
|
|
210
|
-
"RevisionReleaseDate" => "MDC_P003_3",
|
|
211
|
-
"PreferredName" => "MDC_P004",
|
|
212
|
-
"SynonymousName" => "MDC_P007",
|
|
213
|
-
"ShortName" => "MDC_P005",
|
|
214
|
-
"Definition" => "MDC_P006",
|
|
215
|
-
"DefinitionSource" => "MDC_P006_1",
|
|
216
|
-
"Note" => "MDC_P008",
|
|
217
|
-
"Remark" => "MDC_P009",
|
|
218
|
-
"Drawing" => "MDC_P008_1",
|
|
219
|
-
"GUID" => "MDC_P066",
|
|
220
|
-
"TimeStamp" => "MDC_P067",
|
|
221
|
-
"ClassType" => "MDC_P011",
|
|
222
|
-
"Superclass" => "MDC_P010",
|
|
223
|
-
"IsCaseOf" => "MDC_P013",
|
|
224
|
-
"ApplicableProperties" => "MDC_P014",
|
|
225
|
-
"ImportedProperties" => "MDC_P090",
|
|
226
|
-
"SubClassSelection" => "MDC_P016",
|
|
227
|
-
"DataType" => "MDC_P022",
|
|
228
|
-
"ValueFormat" => "MDC_P024",
|
|
229
|
-
"DefinitionClass" => "MDC_P021",
|
|
230
|
-
"Unit" => "MDC_P041",
|
|
231
|
-
"Condition" => "MDC_P028",
|
|
232
|
-
"ListType" => "MDC_P046",
|
|
233
|
-
"CodeList" => "MDC_P044",
|
|
234
|
-
"TermList" => "MDC_P043",
|
|
235
|
-
"EnumerationCode" => "MDC_P044",
|
|
236
|
-
"RelationType" => "MDC_P200",
|
|
237
|
-
"RelationDomain" => "MDC_P201",
|
|
238
|
-
"FunctionDomain" => "MDC_P202",
|
|
239
|
-
"FunctionCodomain" => "MDC_P203",
|
|
240
|
-
"Formula" => "MDC_P204",
|
|
241
|
-
"FormulaLanguage" => "MDC_P205",
|
|
242
|
-
"FormulaExternalSolver" => "MDC_P206",
|
|
243
|
-
"TriggerEvent" => "MDC_P207",
|
|
244
|
-
"DomainElementType" => "MDC_P208",
|
|
245
|
-
"CodomainElementType" => "MDC_P209",
|
|
246
|
-
"Role" => "MDC_P210",
|
|
247
|
-
"Segment" => "MDC_P211",
|
|
248
|
-
"SuperRelation" => "MDC_P212",
|
|
249
|
-
}.freeze
|
|
250
|
-
|
|
200
|
+
# Delegates to Entity::NameSynthesizer when the sheet has no
|
|
201
|
+
# #PROPERTY_ID directive row. See name_synthesizer.rb.
|
|
251
202
|
def synthesize_ids_from_names
|
|
252
203
|
names = nil
|
|
253
204
|
@column_directives.each do |key, vals|
|
|
@@ -257,19 +208,7 @@ module Opencdd
|
|
|
257
208
|
break
|
|
258
209
|
end
|
|
259
210
|
return [] unless names
|
|
260
|
-
|
|
261
|
-
val = names[idx]
|
|
262
|
-
next nil if val.nil? || val.to_s.strip.empty?
|
|
263
|
-
raw = val.to_s.strip
|
|
264
|
-
if raw =~ /\A(.+)\.([A-Za-z]{2})\z/
|
|
265
|
-
base = $1
|
|
266
|
-
lang = $2
|
|
267
|
-
pid = NAME_TO_PROPERTY_ID[base]
|
|
268
|
-
pid ? "#{pid}.#{lang.downcase}" : nil
|
|
269
|
-
else
|
|
270
|
-
NAME_TO_PROPERTY_ID[raw]
|
|
271
|
-
end
|
|
272
|
-
end
|
|
211
|
+
Opencdd::Entity::NameSynthesizer.synthesize(names)
|
|
273
212
|
end
|
|
274
213
|
|
|
275
214
|
def [](property_id_or_name)
|
data/lib/opencdd/property.rb
CHANGED
|
@@ -37,10 +37,10 @@ module Opencdd
|
|
|
37
37
|
field :type_classification, "MDC_P033", :string
|
|
38
38
|
field :source_document, "MDC_P006_1", :string
|
|
39
39
|
field :coded_name, "MDC_P018", :string
|
|
40
|
-
field :definition_class_irdi, "MDC_P021"
|
|
40
|
+
field :definition_class_irdi, "MDC_P021", as: "definition_class"
|
|
41
41
|
field :class_value_assignment, "MDC_P017"
|
|
42
|
-
field :unit_irdi, "MDC_P041"
|
|
43
|
-
field :alternative_unit_irdis, "MDC_P042"
|
|
42
|
+
field :unit_irdi, "MDC_P041", as: "unit"
|
|
43
|
+
field :alternative_unit_irdis, "MDC_P042", as: "alternative_units"
|
|
44
44
|
|
|
45
45
|
# ── Computed fields with block-form readers (synthetic: true).
|
|
46
46
|
# Blocks are evaluated via instance_exec on the entity, so
|
|
@@ -57,11 +57,11 @@ module Opencdd
|
|
|
57
57
|
Opencdd::PropertyDataTypeElement.parse(properties[Opencdd::PropertyIds::MDC_P020])
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
field :parsed_data_type, synthetic: true, &PARSED_DATA_TYPE_BLOCK
|
|
60
|
+
field :parsed_data_type, synthetic: true, as: "data_type", &PARSED_DATA_TYPE_BLOCK
|
|
61
61
|
field :data_element_type, synthetic: true, as: "data_element_type", &DATA_ELEMENT_TYPE_BLOCK
|
|
62
62
|
field :property_data_element_type,
|
|
63
|
-
synthetic: true, &DATA_ELEMENT_TYPE_BLOCK
|
|
64
|
-
field :parsed_value_format, synthetic: true do
|
|
63
|
+
synthetic: true, as: "property_data_element_type", &DATA_ELEMENT_TYPE_BLOCK
|
|
64
|
+
field :parsed_value_format, synthetic: true, as: "value_format" do
|
|
65
65
|
Opencdd::ValueFormat.parse(properties[Opencdd::PropertyIds::MDC_P024])
|
|
66
66
|
end
|
|
67
67
|
field :condition_raw, "MDC_P028", synthetic: true do
|
|
@@ -69,13 +69,6 @@ module Opencdd
|
|
|
69
69
|
end
|
|
70
70
|
field :condition, synthetic: true do
|
|
71
71
|
@condition ||= Opencdd::Condition.parse(properties[Opencdd::PropertyIds::MDC_P028])
|
|
72
|
-
rescue ArgumentError
|
|
73
|
-
# IEC CDD occasionally stores a bare class-reference set in the
|
|
74
|
-
# condition column (e.g. "{0112/2///62683#ACE132}") instead of
|
|
75
|
-
# a `left OP right` boolean expression. Condition's grammar
|
|
76
|
-
# rejects that shape; treat it as nil rather than crashing the
|
|
77
|
-
# import. Tracked in TODO.full-cdd/17-condition-grammar-fix.md.
|
|
78
|
-
@condition = nil
|
|
79
72
|
end
|
|
80
73
|
field :formula, synthetic: true do
|
|
81
74
|
properties[Opencdd::PropertyIds::MDC_P027_1] ||
|
data/lib/opencdd/property_ids.rb
CHANGED
|
@@ -142,6 +142,58 @@ module Opencdd
|
|
|
142
142
|
# ontology registry). Kept here as an alias for back-compat.
|
|
143
143
|
PARCEL_VARIANT_TO_CANONICAL = Opencdd::Parcel::SheetSchema::VARIANT_TO_CANONICAL
|
|
144
144
|
|
|
145
|
+
# IEC 62656-1 defined PROPERTY_NAME directive column names mapped
|
|
146
|
+
# to canonical property IDs. Used by Opencdd::Entity::NameSynthesizer
|
|
147
|
+
# when a Parcel sheet omits the #PROPERTY_ID directive row and
|
|
148
|
+
# only carries #PROPERTY_NAME. Declared here so the raw IDs live
|
|
149
|
+
# in the lint-exempt SSOT instead of in the synthesis module.
|
|
150
|
+
IEC_COLUMN_NAMES = {
|
|
151
|
+
"Code" => "MDC_P001_5",
|
|
152
|
+
"Version" => "MDC_P002_1",
|
|
153
|
+
"Revision" => "MDC_P002_2",
|
|
154
|
+
"VersionInitiationDate" => "MDC_P003_1",
|
|
155
|
+
"VersionReleaseDate" => "MDC_P003_2",
|
|
156
|
+
"RevisionReleaseDate" => "MDC_P003_3",
|
|
157
|
+
"PreferredName" => "MDC_P004",
|
|
158
|
+
"SynonymousName" => "MDC_P007",
|
|
159
|
+
"ShortName" => "MDC_P005",
|
|
160
|
+
"Definition" => "MDC_P006",
|
|
161
|
+
"DefinitionSource" => "MDC_P006_1",
|
|
162
|
+
"Note" => "MDC_P008",
|
|
163
|
+
"Remark" => "MDC_P009",
|
|
164
|
+
"Drawing" => "MDC_P008_1",
|
|
165
|
+
"GUID" => "MDC_P066",
|
|
166
|
+
"TimeStamp" => "MDC_P067",
|
|
167
|
+
"ClassType" => "MDC_P011",
|
|
168
|
+
"Superclass" => "MDC_P010",
|
|
169
|
+
"IsCaseOf" => "MDC_P013",
|
|
170
|
+
"ApplicableProperties" => "MDC_P014",
|
|
171
|
+
"ImportedProperties" => "MDC_P090",
|
|
172
|
+
"SubClassSelection" => "MDC_P016",
|
|
173
|
+
"DataType" => "MDC_P022",
|
|
174
|
+
"ValueFormat" => "MDC_P024",
|
|
175
|
+
"DefinitionClass" => "MDC_P021",
|
|
176
|
+
"Unit" => "MDC_P041",
|
|
177
|
+
"Condition" => "MDC_P028",
|
|
178
|
+
"ListType" => "MDC_P046",
|
|
179
|
+
"CodeList" => "MDC_P044",
|
|
180
|
+
"TermList" => "MDC_P043",
|
|
181
|
+
"EnumerationCode" => "MDC_P044",
|
|
182
|
+
"RelationType" => "MDC_P200",
|
|
183
|
+
"RelationDomain" => "MDC_P201",
|
|
184
|
+
"FunctionDomain" => "MDC_P202",
|
|
185
|
+
"FunctionCodomain" => "MDC_P203",
|
|
186
|
+
"Formula" => "MDC_P204",
|
|
187
|
+
"FormulaLanguage" => "MDC_P205",
|
|
188
|
+
"FormulaExternalSolver" => "MDC_P206",
|
|
189
|
+
"TriggerEvent" => "MDC_P207",
|
|
190
|
+
"DomainElementType" => "MDC_P208",
|
|
191
|
+
"CodomainElementType" => "MDC_P209",
|
|
192
|
+
"Role" => "MDC_P210",
|
|
193
|
+
"Segment" => "MDC_P211",
|
|
194
|
+
"SuperRelation" => "MDC_P212",
|
|
195
|
+
}.freeze
|
|
196
|
+
|
|
145
197
|
REGISTRY.each_key do |id|
|
|
146
198
|
const_set(id, id.freeze) unless const_defined?(id, false)
|
|
147
199
|
end
|
data/lib/opencdd/relation.rb
CHANGED
|
@@ -8,8 +8,8 @@ module Opencdd
|
|
|
8
8
|
}.freeze
|
|
9
9
|
|
|
10
10
|
# ── Pure field reads ─────────────────────────────────────────
|
|
11
|
-
field :domain_of_function_irdis, "MDC_P202"
|
|
12
|
-
field :codomain_irdi, "MDC_P203"
|
|
11
|
+
field :domain_of_function_irdis, "MDC_P202", as: "domain_of_function"
|
|
12
|
+
field :codomain_irdi, "MDC_P203", as: "codomain"
|
|
13
13
|
field :formula, "MDC_P204", :string
|
|
14
14
|
field :formula_language, "MDC_P205", :string
|
|
15
15
|
field :external_solver, "MDC_P206", :string
|
data/lib/opencdd/unit.rb
CHANGED
|
@@ -6,10 +6,10 @@ module Opencdd
|
|
|
6
6
|
# MDC_P023/023_1/023_2 are :identifier_ref in REGISTRY but used
|
|
7
7
|
# as raw strings for unit symbols/representations. Explicit :string
|
|
8
8
|
# override preserves historical behavior.
|
|
9
|
-
field :structure, "MDC_P023", :string
|
|
10
|
-
field :text_representation, "MDC_P023_1", :string
|
|
11
|
-
field :sgml_representation, "MDC_P023_2", :string
|
|
12
|
-
field :definition_class_irdi, "MDC_P021"
|
|
9
|
+
field :structure, "MDC_P023", :string, as: "unit_structure"
|
|
10
|
+
field :text_representation, "MDC_P023_1", :string, as: "unit_text"
|
|
11
|
+
field :sgml_representation, "MDC_P023_2", :string, as: "unit_sgml"
|
|
12
|
+
field :definition_class_irdi, "MDC_P021", as: "definition_class"
|
|
13
13
|
|
|
14
14
|
alias_method :symbol, :text_representation
|
|
15
15
|
end
|
|
@@ -14,6 +14,9 @@ module Opencdd
|
|
|
14
14
|
|
|
15
15
|
def call(value, _context)
|
|
16
16
|
return true if value.nil? || value.to_s.strip.empty?
|
|
17
|
+
# parse returns a boolean Condition or a Condition::ClassReference
|
|
18
|
+
# for bare-IRDI / bare-set conditions (IEC 62683 shape). Both are
|
|
19
|
+
# valid; only malformed input raises ArgumentError.
|
|
17
20
|
!Opencdd::Condition.parse(value.to_s).nil?
|
|
18
21
|
rescue ArgumentError
|
|
19
22
|
false
|
data/lib/opencdd/version.rb
CHANGED
data/lib/opencdd/view_control.rb
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module Opencdd
|
|
4
4
|
class ViewControl < Opencdd::Entity
|
|
5
5
|
# ── Pure field reads ─────────────────────────────────────────
|
|
6
|
-
field :controlled_class_irdis, "EXT_P002"
|
|
7
|
-
field :shown_property_irdis, "EXT_P003"
|
|
6
|
+
field :controlled_class_irdis, "EXT_P002", as: "controlled_classes"
|
|
7
|
+
field :shown_property_irdis, "EXT_P003", as: "shown_properties"
|
|
8
8
|
# data_object_identifier and time_stamp inherited from Entity base.
|
|
9
9
|
end
|
|
10
10
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opencdd
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenCDD contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: roo
|
|
@@ -217,6 +217,7 @@ files:
|
|
|
217
217
|
- lib/opencdd/cddal/fetcher/in_memory.rb
|
|
218
218
|
- lib/opencdd/cddal/fetcher/net_http.rb
|
|
219
219
|
- lib/opencdd/cddal/generated_parser.rb
|
|
220
|
+
- lib/opencdd/cddal/import_pipeline.rb
|
|
220
221
|
- lib/opencdd/cddal/lexer.rb
|
|
221
222
|
- lib/opencdd/cddal/parser.rb
|
|
222
223
|
- lib/opencdd/cddal/resolver.rb
|
|
@@ -239,6 +240,7 @@ files:
|
|
|
239
240
|
- lib/opencdd/entity.rb
|
|
240
241
|
- lib/opencdd/entity/field_reader.rb
|
|
241
242
|
- lib/opencdd/entity/field_registry.rb
|
|
243
|
+
- lib/opencdd/entity/name_synthesizer.rb
|
|
242
244
|
- lib/opencdd/entity/version_history.rb
|
|
243
245
|
- lib/opencdd/entity/yaml.rb
|
|
244
246
|
- lib/opencdd/entity_diff.rb
|