opencdd 0.3.2 → 0.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 907feca38dccee34a74c306983cdbe506bf3b18843640000501e7482cea75414
4
- data.tar.gz: 2581c9dfac24e7bb1b8fcb973ef311854d8096947daf9a6d01ca726e672d2612
3
+ metadata.gz: c3b245ffe7055b867a634912373305b044261c4fab4af420029ad62be539321f
4
+ data.tar.gz: c26921adb3a18950743b39274420522d3b41ff68e1b478ee1c27fb1e0c19d374
5
5
  SHA512:
6
- metadata.gz: eb42bba181fa6e5802a6c3ed1ea46dce2d7ee9197dea2f929bd8b2e9565826cdd19dc503ba58a231b5555208244e5d8e084b92199944d8b7d30aa1e2e6879c2f
7
- data.tar.gz: 74ab77f45f8365a433a638414c982d092140b07f9084fbb97ea94d846cc60a0c3787a29a2180d729a424715896514008c6ec0b2d5e9060ca8b3c60197d09f2fb
6
+ metadata.gz: 96952a531d921778810b8c6f929589d933d536dbbac9ceed1c3f5b41006f710b4b649262420241a05554cba496d8ff45ab6b9b54e8caa58883fb865180fac96f
7
+ data.tar.gz: 625fd243c5ca85e9cca57b2c2c4eae0c1f9024b9444255ba0df60773175c2029ec76ca4e3acb070e527bd9190066c38682130c1be046fca22c00f60b17b0f8be
@@ -110,6 +110,7 @@ module Opencdd
110
110
  def relations ; @entities_by_type[:relation] || [] ; end
111
111
  def view_controls ; @entities_by_type[:view_control] || [] ; end
112
112
  def list_of_units ; @entities_by_type[:list_of_unit] || [] ; end
113
+ def det_classifications ; @entities_by_type[:det_classification] || [] ; end
113
114
 
114
115
  def entities_of_type(type)
115
116
  @entities_by_type[type.to_sym] || []
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Opencdd
4
+ class DetClassification < Opencdd::Entity
5
+ # The cdd.iec.ch search-export DET classification .xls stores the
6
+ # entity code as a short string (e.g. "A11") in column 1. We
7
+ # need to synthesize the full IRDI by prepending the meta-class's
8
+ # supplier prefix (IECCDD_001) — the standard from_row would
9
+ # IRDI.parse("A11") which fails (no namespace).
10
+ DET_CLASSIFICATION_SUPPLIER = "0112/2///IECCDD_001".freeze
11
+
12
+ def self.from_row(row, schema:, meta_class_irdi:, code_property_id: nil)
13
+ row = row.dup
14
+ if meta_class_irdi&.code == "MDC_C0101"
15
+ # Promote the short code to a full IRDI before parent handles it.
16
+ # code_property_id for MDC_C0101 is the MDC code ID (MDC_P001_5).
17
+ cid = code_property_id || Opencdd::MetaClasses.code_property_id_for("MDC_C0101")
18
+ short = cid && row[cid]
19
+ if short && !short.to_s.include?("#")
20
+ row[cid] = "#{DET_CLASSIFICATION_SUPPLIER}##{short}"
21
+ end
22
+ end
23
+ super
24
+ end
25
+ end
26
+ end
@@ -70,14 +70,15 @@ module Opencdd
70
70
  # omitted (payload still has all the entity's own fields).
71
71
  # ─────────────────────────────────────────────────────────────
72
72
  PAYLOAD_BUILDERS = {
73
- Opencdd::Klass => :class_node,
74
- Opencdd::Property => :property_node,
75
- Opencdd::Unit => :unit_node,
76
- Opencdd::ValueList => :value_list_node,
77
- Opencdd::ValueTerm => :value_term_node,
78
- Opencdd::Relation => :relation_node,
79
- Opencdd::ViewControl => :view_control_node,
80
- Opencdd::ListUnit => :list_of_unit_node,
73
+ Opencdd::Klass => :class_node,
74
+ Opencdd::Property => :property_node,
75
+ Opencdd::Unit => :unit_node,
76
+ Opencdd::ValueList => :value_list_node,
77
+ Opencdd::ValueTerm => :value_term_node,
78
+ Opencdd::Relation => :relation_node,
79
+ Opencdd::ViewControl => :view_control_node,
80
+ Opencdd::ListUnit => :list_of_unit_node,
81
+ Opencdd::DetClassification => :det_classification_node,
81
82
  }.freeze
82
83
 
83
84
  def payload_for(entity, database: nil)
@@ -134,6 +135,10 @@ module Opencdd
134
135
  entity_payload(lou).merge(type: "list_of_unit").compact
135
136
  end
136
137
 
138
+ def det_classification_node(det)
139
+ entity_payload(det).merge(type: "det_classification").compact
140
+ end
141
+
137
142
  private
138
143
 
139
144
  # Iterates every declared field on the entity's class (walking
@@ -80,6 +80,7 @@ module Opencdd
80
80
  "MDC_C009" => "MDC_P001_10",
81
81
  "MDC_C010" => "MDC_P001_11",
82
82
  "MDC_C0100" => "C0101",
83
+ "MDC_C0101" => "MDC_P001_5",
83
84
  "EXT_C001" => "EXT_P001",
84
85
  }.freeze
85
86
 
@@ -91,6 +92,8 @@ module Opencdd
91
92
  "MDC_C009" => :unit,
92
93
  "MDC_C010" => :value_term,
93
94
  "MDC_C0100" => :list_of_unit,
95
+ "MDC_C0101" => :det_classification,
96
+ "IECCDD_001" => :det_classification,
94
97
  "EXT_C001" => :view_control,
95
98
  }.freeze
96
99
 
@@ -261,6 +264,17 @@ module Opencdd
261
264
  type: :list_of_unit,
262
265
  allowed_property_ids: common,
263
266
  )
267
+ # cdd.iec.ch's search-export uses CLASS_ID:=IECCDD_001 (an
268
+ # IEC-internal supplier scheme) — not a Parcel meta-class IRDI.
269
+ # We register MDC_C0101 as the canonical meta-class IRDI; the
270
+ # file's CLASS_ID is documentation, not the parsing gate.
271
+ det_classification = MetaClass.new(
272
+ irdi: "MDC_C0101",
273
+ name: "DetClassification",
274
+ entity_class: Opencdd::DetClassification,
275
+ type: :det_classification,
276
+ allowed_property_ids: common,
277
+ )
264
278
  {
265
279
  klass_class.irdi => klass_class,
266
280
  property_class.irdi => property_class,
@@ -270,6 +284,7 @@ module Opencdd
270
284
  value_term.irdi => value_term,
271
285
  view_control.irdi => view_control,
272
286
  list_of_unit.irdi => list_of_unit,
287
+ det_classification.irdi => det_classification,
273
288
  }
274
289
  end
275
290
  end
@@ -24,6 +24,7 @@ module Opencdd
24
24
  "VALUELIST" => :value_list,
25
25
  "VALUETERMS" => :value_term,
26
26
  "LISTOFUNITS" => :list_of_unit,
27
+ "DETCLASSIFICATION" => :det_classification,
27
28
  }.freeze
28
29
 
29
30
  attr_reader :path
@@ -32,7 +32,7 @@ module Opencdd
32
32
 
33
33
  # Per-type export filename produced by cdd.iec.ch's download
34
34
  # endpoint.
35
- FILE_PATTERN = /\Aexport_(CLASS|PROPERTY|RELATION|UNIT|VALUELIST|VALUETERMS|LISTOFUNITS)_[^\.]+\.(xls|xlsx)\z/i.freeze
35
+ FILE_PATTERN = /\Aexport_(CLASS|PROPERTY|RELATION|UNIT|VALUELIST|VALUETERMS|LISTOFUNITS|DETCLASSIFICATION)_[^\.]+\.(xls|xlsx)\z/i.freeze
36
36
 
37
37
  module_function
38
38
 
@@ -4,7 +4,7 @@ module Opencdd
4
4
  module Parcel
5
5
  # Verifies that scrape output produced populated .xls files, not
6
6
  # just schema stubs. Catches the silent failure mode discovered
7
- # on 2026-07-08: iec61360/iec63213/iec61360-7 scrapes appeared
7
+ # on 2026-07-08: iec61360/iec-63213/iec-61360-7 scrapes appeared
8
8
  # complete (10,338 PROPERTY .xls files for iec61360) but every
9
9
  # file had 0 data rows. The build pipeline exported 574 classes
10
10
  # + 0 properties, and the browser showed "No declared properties"
@@ -26,7 +26,7 @@ module Opencdd
26
26
  # +.xls+ files into a Workbook.
27
27
  #
28
28
  # Example:
29
- # reader = Opencdd::Parcel::ShardedDirReader.new("downloads/iec63213")
29
+ # reader = Opencdd::Parcel::ShardedDirReader.new("downloads/iec-63213")
30
30
  # db = Opencdd::Database.new
31
31
  # reader.load_into(db)
32
32
  #
@@ -3,11 +3,15 @@
3
3
  module Opencdd
4
4
  module Parcel
5
5
  class SheetSchema
6
- # Parcel-specific column-ID canonicalization. Maps the
7
- # ParcelMaker variant headers (MDC_P004_1, MDC_P005, ...)
8
- # to the canonical IEC 61360 IDs (MDC_P004, MDC_P006, ...).
6
+ # Parcel-specific column-ID canonicalization. Maps:
9
7
  #
10
- # Owned by SheetSchema because this mapping only exists for
8
+ # - ParcelMaker language-variant headers (MDC_P004_1, MDC_P005, ...)
9
+ # to the canonical IEC 61360 IDs (MDC_P004, MDC_P006, ...).
10
+ # - cdd.iec.ch search-export's project-specific IDs for DET
11
+ # classification (IECCDD_001_C0001, IECCDD_001_C0002.<lang>, ...)
12
+ # to the canonical IEC 61360 IDs (MDC_P001_5, MDC_P004_1.<lang>, ...).
13
+ #
14
+ # Owned by SheetSchema because these mappings only exist for
11
15
  # the Parcel sheet layout — the PropertyIds registry is
12
16
  # ontology-only and shouldn't carry format-specific details.
13
17
  VARIANT_TO_CANONICAL = {
@@ -17,6 +21,22 @@ module Opencdd
17
21
  "MDC_P005" => "MDC_P006",
18
22
  "MDC_P007_1" => "MDC_P008",
19
23
  "MDC_P007_2" => "MDC_P009",
24
+
25
+ # cdd.iec.ch search-export DET classification aliases.
26
+ # The file uses IEC-internal supplier scheme (IECCDD_001) and
27
+ # project-specific column IDs (C0001 = code, C0002.<lang> = name)
28
+ # rather than the standard MDC codes. Without these mappings,
29
+ # every DET classification entity would have nil code + name.
30
+ #
31
+ # C0002 maps to MDC_P004 (preferred_name), not MDC_P004_1
32
+ # (preferred_name_localized), because canonical_id splits the
33
+ # language suffix off and reapplies it after the base lookup —
34
+ # so the per-language entries (C0002.en, C0002.fr, etc.) below
35
+ # would be dead code. The base entry alone produces
36
+ # MDC_P004.<lang>, which is what the preferred_name field DSL
37
+ # reads via FieldRegistry.
38
+ "IECCDD_001_C0001" => "MDC_P001_5",
39
+ "IECCDD_001_C0002" => "MDC_P004",
20
40
  }.freeze
21
41
 
22
42
  # Canonicalize a Parcel column ID. Splits language tags
@@ -17,7 +17,7 @@ module Opencdd
17
17
  # version's subfolder.
18
18
  #
19
19
  # Example:
20
- # reader = Opencdd::Parcel::VersionedReader.new("downloads/iec63213")
20
+ # reader = Opencdd::Parcel::VersionedReader.new("downloads/iec-63213")
21
21
  # reader.versions_for("KEA012") # => 3 VersionHistory::Entry
22
22
  # reader.load_version("KEA012", "ABC123...") # => Database with v002 content
23
23
  class VersionedReader
@@ -18,6 +18,8 @@ module Opencdd
18
18
  "UNIT" => :unit,
19
19
  "VALUELIST" => :value_list,
20
20
  "VALUETERMS" => :value_term,
21
+ "LISTOFUNITS" => :list_of_unit,
22
+ "DETCLASSIFICATION" => :det_classification,
21
23
  }.freeze
22
24
 
23
25
  LEGACY_TYPE_TO_PARCEL_NAME = {
@@ -27,6 +29,8 @@ module Opencdd
27
29
  value_term: "TERMINOLOGY",
28
30
  unit: "UoM",
29
31
  relation: "RELATION",
32
+ list_of_unit: "LISTOFUNITS",
33
+ det_classification: "DETCLASSIFICATION",
30
34
  }.freeze
31
35
 
32
36
  META_CLASS_BY_LEGACY_TYPE = Opencdd::MetaClasses::TYPE_BY_META_CLASS.invert.freeze
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Opencdd
4
- VERSION = "0.3.2"
4
+ VERSION = "0.3.3"
5
5
  end
data/lib/opencdd.rb CHANGED
@@ -29,6 +29,7 @@ module Opencdd
29
29
  autoload :Relation, "opencdd/relation"
30
30
  autoload :ViewControl, "opencdd/view_control"
31
31
  autoload :ListUnit, "opencdd/list_unit"
32
+ autoload :DetClassification, "opencdd/det_classification"
32
33
 
33
34
  autoload :Database, "opencdd/database"
34
35
  autoload :EffectiveProperties, "opencdd/effective_properties"
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.3.2
4
+ version: 0.3.3
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-08-07 00:00:00.000000000 Z
11
+ date: 2026-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: roo
@@ -236,6 +236,7 @@ files:
236
236
  - lib/opencdd/database/parcel_integration.rb
237
237
  - lib/opencdd/database/persistence.rb
238
238
  - lib/opencdd/database/queries.rb
239
+ - lib/opencdd/det_classification.rb
239
240
  - lib/opencdd/effective_properties.rb
240
241
  - lib/opencdd/entity.rb
241
242
  - lib/opencdd/entity/field_reader.rb