pubid 2.0.0.pre.alpha.3 → 2.0.0.pre.alpha.4

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.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pubid/amca/identifier.rb +4 -23
  3. data/lib/pubid/amca/identifiers/base.rb +67 -30
  4. data/lib/pubid/amca/identifiers/interpretation.rb +0 -4
  5. data/lib/pubid/amca/identifiers/publication.rb +0 -4
  6. data/lib/pubid/amca/identifiers/standard.rb +0 -4
  7. data/lib/pubid/amca/renderer.rb +1 -1
  8. data/lib/pubid/amca/urn_generator.rb +2 -1
  9. data/lib/pubid/api/builder.rb +4 -0
  10. data/lib/pubid/api/identifier.rb +5 -1
  11. data/lib/pubid/api/identifiers/base.rb +2 -12
  12. data/lib/pubid/api/identifiers/mpms.rb +0 -4
  13. data/lib/pubid/api/identifiers/typeless_standard.rb +0 -3
  14. data/lib/pubid/api/single_identifier.rb +5 -8
  15. data/lib/pubid/ashrae/identifier.rb +7 -22
  16. data/lib/pubid/ashrae/identifiers/base.rb +28 -17
  17. data/lib/pubid/ashrae/parser.rb +4 -0
  18. data/lib/pubid/ashrae.rb +4 -0
  19. data/lib/pubid/asme/single_identifier.rb +3 -1
  20. data/lib/pubid/astm/single_identifier.rb +3 -1
  21. data/lib/pubid/bsi/identifier.rb +5 -31
  22. data/lib/pubid/bsi/identifiers/addendum_document.rb +0 -4
  23. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +0 -4
  24. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +0 -4
  25. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +0 -3
  26. data/lib/pubid/bsi/identifiers/amendment.rb +0 -4
  27. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +0 -3
  28. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +2 -5
  29. data/lib/pubid/bsi/identifiers/committee_document.rb +0 -3
  30. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +2 -5
  31. data/lib/pubid/bsi/identifiers/corrigendum.rb +0 -4
  32. data/lib/pubid/bsi/identifiers/detailed_specification.rb +0 -3
  33. data/lib/pubid/bsi/identifiers/disc.rb +0 -3
  34. data/lib/pubid/bsi/identifiers/draft_document.rb +0 -3
  35. data/lib/pubid/bsi/identifiers/electronic_book.rb +0 -3
  36. data/lib/pubid/bsi/identifiers/expert_commentary.rb +0 -4
  37. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +0 -3
  38. data/lib/pubid/bsi/identifiers/flex.rb +0 -3
  39. data/lib/pubid/bsi/identifiers/handbook.rb +0 -3
  40. data/lib/pubid/bsi/identifiers/index.rb +0 -3
  41. data/lib/pubid/bsi/identifiers/method.rb +0 -3
  42. data/lib/pubid/bsi/identifiers/national_annex.rb +0 -3
  43. data/lib/pubid/bsi/identifiers/practice_guide.rb +0 -3
  44. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +0 -3
  45. data/lib/pubid/bsi/identifiers/published_document.rb +0 -3
  46. data/lib/pubid/bsi/identifiers/section.rb +0 -3
  47. data/lib/pubid/bsi/identifiers/set.rb +2 -5
  48. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +0 -3
  49. data/lib/pubid/bsi/identifiers/supplement_document.rb +0 -4
  50. data/lib/pubid/bsi/identifiers/supplementary_index.rb +0 -3
  51. data/lib/pubid/bsi/identifiers/technical_specification.rb +0 -3
  52. data/lib/pubid/bsi/identifiers/test_method.rb +0 -3
  53. data/lib/pubid/bsi/identifiers/value_added_publication.rb +0 -4
  54. data/lib/pubid/bsi/single_identifier.rb +32 -13
  55. data/lib/pubid/bsi.rb +8 -1
  56. data/lib/pubid/ccsds/identifier.rb +2 -14
  57. data/lib/pubid/cen_cenelec/identifier.rb +10 -8
  58. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +0 -4
  59. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +0 -4
  60. data/lib/pubid/cen_cenelec/identifiers/base.rb +2 -9
  61. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +0 -4
  62. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +0 -4
  63. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +0 -3
  64. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +0 -4
  65. data/lib/pubid/cen_cenelec/single_identifier.rb +4 -7
  66. data/lib/pubid/cen_cenelec.rb +4 -0
  67. data/lib/pubid/cie/identifier.rb +4 -0
  68. data/lib/pubid/cie/single_identifier.rb +4 -4
  69. data/lib/pubid/cie.rb +4 -0
  70. data/lib/pubid/csa/identifier.rb +10 -1
  71. data/lib/pubid/csa/identifiers/base.rb +0 -3
  72. data/lib/pubid/csa/identifiers/cec.rb +0 -4
  73. data/lib/pubid/csa/identifiers/series.rb +0 -4
  74. data/lib/pubid/csa/single_identifier.rb +1 -1
  75. data/lib/pubid/csa.rb +4 -0
  76. data/lib/pubid/etsi/components/code.rb +1 -7
  77. data/lib/pubid/etsi/components/version.rb +0 -5
  78. data/lib/pubid/etsi/identifier.rb +4 -12
  79. data/lib/pubid/etsi/identifiers/base.rb +31 -24
  80. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +0 -3
  81. data/lib/pubid/etsi.rb +3 -1
  82. data/lib/pubid/identifier.rb +90 -1
  83. data/lib/pubid/idf/identifier.rb +4 -0
  84. data/lib/pubid/idf.rb +4 -0
  85. data/lib/pubid/iec/identifier.rb +14 -14
  86. data/lib/pubid/iec/identifiers/base.rb +0 -4
  87. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +0 -4
  88. data/lib/pubid/iec/identifiers/fragment_identifier.rb +1 -5
  89. data/lib/pubid/iec/identifiers/sheet_identifier.rb +1 -5
  90. data/lib/pubid/iec/identifiers/test_report_form.rb +0 -3
  91. data/lib/pubid/iec/identifiers/vap_identifier.rb +1 -5
  92. data/lib/pubid/iec/identifiers/working_document.rb +0 -4
  93. data/lib/pubid/iec.rb +4 -0
  94. data/lib/pubid/ieee/identifier.rb +5 -17
  95. data/lib/pubid/ieee/identifiers/adopted_standard.rb +0 -4
  96. data/lib/pubid/ieee/identifiers/base.rb +223 -201
  97. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +0 -4
  98. data/lib/pubid/ieee/identifiers/corrigendum.rb +0 -4
  99. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +0 -4
  100. data/lib/pubid/ieee/identifiers/dual_identifier.rb +0 -4
  101. data/lib/pubid/ieee/identifiers/dual_published.rb +0 -4
  102. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +0 -4
  103. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +0 -4
  104. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +0 -4
  105. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +0 -4
  106. data/lib/pubid/ieee/identifiers/redlined_standard.rb +0 -4
  107. data/lib/pubid/ieee/identifiers/si_standard.rb +0 -4
  108. data/lib/pubid/ieee.rb +4 -0
  109. data/lib/pubid/iho/identifier.rb +7 -25
  110. data/lib/pubid/iho/identifiers/base.rb +62 -68
  111. data/lib/pubid/iho.rb +3 -1
  112. data/lib/pubid/iso/identifier.rb +15 -14
  113. data/lib/pubid/iso/single_identifier.rb +0 -4
  114. data/lib/pubid/iso.rb +4 -0
  115. data/lib/pubid/itu/components/code.rb +1 -7
  116. data/lib/pubid/itu/components/sector.rb +15 -4
  117. data/lib/pubid/itu/components/series.rb +0 -4
  118. data/lib/pubid/itu/identifier.rb +4 -18
  119. data/lib/pubid/itu/identifiers/base.rb +124 -122
  120. data/lib/pubid/itu.rb +3 -1
  121. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -4
  122. data/lib/pubid/jcgm/identifiers/gum_guide.rb +0 -4
  123. data/lib/pubid/jcgm/single_identifier.rb +0 -4
  124. data/lib/pubid/jis/identifier.rb +2 -14
  125. data/lib/pubid/nist/identifier.rb +8 -23
  126. data/lib/pubid/nist/identifiers/base.rb +553 -544
  127. data/lib/pubid/nist/preprocessor.rb +12 -0
  128. data/lib/pubid/nist.rb +4 -0
  129. data/lib/pubid/oiml/builder.rb +21 -3
  130. data/lib/pubid/oiml/components/code.rb +7 -0
  131. data/lib/pubid/oiml/identifier.rb +44 -0
  132. data/lib/pubid/oiml/identifiers/annex.rb +10 -1
  133. data/lib/pubid/oiml/identifiers/errata.rb +15 -0
  134. data/lib/pubid/oiml/identifiers.rb +1 -1
  135. data/lib/pubid/oiml/parser.rb +59 -12
  136. data/lib/pubid/oiml/renderer.rb +27 -17
  137. data/lib/pubid/oiml/single_identifier.rb +58 -0
  138. data/lib/pubid/oiml/supplement_identifier.rb +30 -1
  139. data/lib/pubid/plateau/identifier.rb +4 -21
  140. data/lib/pubid/plateau/identifiers/base.rb +45 -36
  141. data/lib/pubid/plateau/identifiers/handbook.rb +0 -4
  142. data/lib/pubid/plateau/identifiers/technical_report.rb +0 -4
  143. data/lib/pubid/plateau/supplement_identifier.rb +0 -4
  144. data/lib/pubid/sae/identifier.rb +4 -12
  145. data/lib/pubid/sae/identifiers/base.rb +26 -17
  146. data/lib/pubid/version.rb +1 -1
  147. data/lib/pubid.rb +18 -2
  148. data/lib/tasks/export.rake +6 -5
  149. metadata +3 -4
  150. data/lib/pubid/identifier_facade.rb +0 -114
  151. data/lib/pubid/oiml/identifiers/base.rb +0 -21
@@ -10,10 +10,6 @@ module Pubid
10
10
  def type_string
11
11
  "Technical Report"
12
12
  end
13
-
14
- def to_s
15
- render(format: :human)
16
- end
17
13
  end
18
14
  end
19
15
  end
@@ -19,10 +19,6 @@ module Pubid
19
19
  raise NotImplementedError, "Subclasses must implement supplement_string"
20
20
  end
21
21
 
22
- def to_s
23
- render(format: :human)
24
- end
25
-
26
22
  # Override base_hash to extract edition, type, and annex from base_identifier
27
23
  def base_hash
28
24
  hash = super
@@ -1,14 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Pubid
4
- module Sae
5
- class Identifier
6
- def self.parse(input)
7
- parsed = Parser.parse(input)
8
- Builder.build(parsed)
9
- rescue Parslet::ParseFailed => e
10
- raise "Failed to parse SAE identifier: #{input}\n#{e.message}"
11
- end
12
- end
13
- end
14
- end
3
+ # Pubid::Sae::Identifier is the SAE base class (a real Pubid::Identifier
4
+ # subclass); its body, `.parse`, and the Identifiers::Base back-compat alias
5
+ # live in identifiers/base.rb. This file just ensures it is loaded.
6
+ require_relative "identifiers/base"
@@ -2,27 +2,36 @@
2
2
 
3
3
  module Pubid
4
4
  module Sae
5
- module Identifiers
6
- # Base SAE Identifier
7
- # Handles all SAE document types (AMS, AIR, ARP, AS, MA)
8
- class Base < Pubid::Identifier
9
- # Generate URN for this identifier
10
- #
11
- # @return [String] URN representation
5
+ # Base SAE Identifier. Canonical name Pubid::Sae::Identifier (Identifiers::Base
6
+ # is a back-compat alias). SAE has a single identifier class that IS the
7
+ # document type, so this class is both the base and the only concrete type.
8
+ # Handles all SAE document types (AMS, AIR, ARP, AS, MA).
9
+ class Identifier < ::Pubid::Identifier
10
+ def self.parse(input)
11
+ parsed = Parser.parse(input)
12
+ Builder.build(parsed)
13
+ rescue Parslet::ParseFailed => e
14
+ raise "Failed to parse SAE identifier: #{input}\n#{e.message}"
15
+ end
12
16
 
13
- attribute :publisher, :string, default: -> { "SAE" }
14
- attribute :type, Sae::Components::Type
15
- attribute :number, Sae::Components::Code
16
- attribute :date, Sae::Components::Date
17
+ attribute :publisher, :string, default: -> { "SAE" }
18
+ attribute :type, Sae::Components::Type
19
+ attribute :number, Sae::Components::Code
20
+ attribute :date, Sae::Components::Date
17
21
 
18
- def self.type
19
- { key: :base, web: :standard, title: "Standard", short: "SAE" }
20
- end
22
+ def self.type
23
+ { key: :base, web: :standard, title: "Standard", short: "SAE" }
24
+ end
21
25
 
22
- def year
23
- date&.year
24
- end
26
+ def year
27
+ date&.year
25
28
  end
26
29
  end
30
+
31
+ module Identifiers
32
+ # Backward-compatible alias: SAE's base class used to be
33
+ # Pubid::Sae::Identifiers::Base. It is now Pubid::Sae::Identifier.
34
+ Base = Pubid::Sae::Identifier
35
+ end
27
36
  end
28
37
  end
data/lib/pubid/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pubid
4
- VERSION = "2.0.0.pre.alpha.3"
4
+ VERSION = "2.0.0.pre.alpha.4"
5
5
  end
data/lib/pubid.rb CHANGED
@@ -10,6 +10,21 @@ require "parslet"
10
10
  require "pubid/lutaml/no_store_registration"
11
11
 
12
12
  module Pubid
13
+ # Upper bound on the length of an identifier string accepted by any +parse+
14
+ # entry point. Real-world standards identifiers are well under 200 characters;
15
+ # this limit exists purely to keep pathological, attacker-controlled inputs
16
+ # away from the flavors' backtracking-capable normalization regexes
17
+ # (CodeQL rb/polynomial-redos). The inline `.length` checks in every public
18
+ # +parse+ method are recognized by CodeQL as a barrier that bounds the input
19
+ # before it can reach those regexes. Ruby 3.2+ already memoizes the flagged
20
+ # regexes to linear time, so this guard is defense-in-depth, not a fix for a
21
+ # live exploit; it must therefore never reject a legitimate identifier.
22
+ MAX_INPUT_LENGTH = 1000
23
+
24
+ # Raised (as an ArgumentError) when an input string exceeds MAX_INPUT_LENGTH.
25
+ INPUT_TOO_LONG_MESSAGE =
26
+ "identifier string exceeds maximum length of #{MAX_INPUT_LENGTH} characters"
27
+
13
28
  # Registry for tracking all loaded flavors
14
29
  class Registry
15
30
  @flavors = {}
@@ -50,7 +65,6 @@ module Pubid
50
65
  autoload :Components, "pubid/components"
51
66
  autoload :BundledIdentifier, "pubid/bundled_identifier"
52
67
  autoload :Identifier, "pubid/identifier"
53
- autoload :IdentifierFacade, "pubid/identifier_facade"
54
68
  autoload :IdentifierMetadata, "pubid/identifier_metadata"
55
69
  autoload :Rendering, "pubid/rendering"
56
70
  autoload :Renderers, "pubid/renderers"
@@ -111,6 +125,8 @@ module Pubid
111
125
  # @param format [Symbol] :auto, :human, :mr_string, or :urn
112
126
  # @return [Identifier] The parsed identifier
113
127
  def self.parse(string, format: :auto)
128
+ raise ArgumentError, INPUT_TOO_LONG_MESSAGE if string.length > MAX_INPUT_LENGTH
129
+
114
130
  format = FormatDetector.detect(string) if format == :auto
115
131
 
116
132
  case format
@@ -126,7 +142,7 @@ module Pubid
126
142
  end
127
143
 
128
144
  urn_parser = flavor_module.const_get(:UrnParser)
129
- urn_parser.parse(string) else
145
+ urn_parser.parse(string) else
130
146
  # Default to MR string parser for MR format, human-readable otherwise
131
147
  # The MR string parser converts to human-readable and delegates to flavor.parse
132
148
  raise ArgumentError,
@@ -19,17 +19,18 @@ namespace :export do
19
19
  desc "Audit library data against website publishers"
20
20
  task :audit do
21
21
  require "pubid/export"
22
- data = Pubid::Export::Exporter.export_all
23
22
 
24
- # Parse website publishers to extract doc type keys
25
- # For now, read the generated JSON and provide a summary
23
+ # Auditor compares string-keyed, JSON-shaped data (see Auditor.from_file and
24
+ # auditor_spec.rb), so roundtrip the export through JSON to convert the
25
+ # symbol keys (:identifier_types) into the string keys it expects.
26
+ data = JSON.parse(JSON.generate(Pubid::Export::Exporter.export_all))
26
27
  auditor = Pubid::Export::Auditor.new(data)
27
28
 
28
29
  # Build a minimal website representation from the generated data itself
29
30
  # (in production, this would parse the website's publishers.ts)
30
- {}
31
31
  summary = data.transform_values do |fd|
32
- { "doc_types" => fd[:identifier_types].map { |t| { "key" => t[:key] } } }
32
+ keys = fd["identifier_types"].map { |t| { "key" => t["key"] } }
33
+ { "doc_types" => keys }
33
34
  end
34
35
 
35
36
  results = auditor.audit(summary)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pubid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.alpha.3
4
+ version: 2.0.0.pre.alpha.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-06-26 00:00:00.000000000 Z
11
+ date: 2026-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -336,7 +336,6 @@ files:
336
336
  - lib/pubid/format_detector.rb
337
337
  - lib/pubid/format_registry.rb
338
338
  - lib/pubid/identifier.rb
339
- - lib/pubid/identifier_facade.rb
340
339
  - lib/pubid/identifier_metadata.rb
341
340
  - lib/pubid/idf.rb
342
341
  - lib/pubid/idf/builder.rb
@@ -609,9 +608,9 @@ files:
609
608
  - lib/pubid/oiml/identifiers.rb
610
609
  - lib/pubid/oiml/identifiers/amendment.rb
611
610
  - lib/pubid/oiml/identifiers/annex.rb
612
- - lib/pubid/oiml/identifiers/base.rb
613
611
  - lib/pubid/oiml/identifiers/basic_publication.rb
614
612
  - lib/pubid/oiml/identifiers/document.rb
613
+ - lib/pubid/oiml/identifiers/errata.rb
615
614
  - lib/pubid/oiml/identifiers/expert_report.rb
616
615
  - lib/pubid/oiml/identifiers/guide.rb
617
616
  - lib/pubid/oiml/identifiers/recommendation.rb
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pubid
4
- # Mixin for the per-flavor `Identifier` *module* facades (NIST, IHO, BSI,
5
- # CEN/CENELEC, ASHRAE). The class-pattern flavors (ISO, IEC, JIS, …) expose
6
- # their root identifier as a real class, so `id.is_a?(Pubid::Iso::Identifier)`
7
- # and `Pubid::Iso::Identifier.from_hash` already work natively. The
8
- # module-pattern flavors keep `Identifier` as a thin parse/factory module;
9
- # this mixin gives that module the same two capabilities a consumer relies on
10
- # when it is handed the module as its identifier class (e.g. relaton-index's
11
- # `pubid_class`):
12
- #
13
- # * `from_hash` — polymorphic deserialization that dispatches on the
14
- # `_type` discriminator to the correct concrete `Identifiers::*` class,
15
- # reusing the flavor's own `identifier_types` registry rather than a
16
- # hand-maintained map.
17
- # * identity — `extend`ing this mixin into the `Identifier` module is paired
18
- # with `include`-ing that module into the flavor's `Identifiers::Base`, so
19
- # every concrete identifier descends from it. That makes
20
- # `id.is_a?(Pubid::Nist::Identifier)` and `Pubid::Nist::Identifier === id`
21
- # both true (`Module#===` delegates to `is_a?`) — the test a consumer
22
- # holding the module needs to ask "is this one of my identifiers?".
23
- #
24
- # The flavor namespace, the `Identifiers` namespace, and the fallback `Base`
25
- # class are all derived from the extending module's own name by convention
26
- # (`Pubid::<Flavor>::Identifier`), so a flavor opts in with a single
27
- # `extend Pubid::IdentifierFacade`.
28
- #
29
- # Opt-in is deliberately GATED to flavors whose `to_hash`/`from_hash`
30
- # round-trips cleanly. Some module-pattern flavors (AMCA, ITU, PLATEAU, IEEE)
31
- # have a broken `to_hash` (publisher stored as a String) or a lossy
32
- # `from_hash`; for those the facade's identity check would route ids through a
33
- # consumer's `to_hash` and crash or silently corrupt them, so they
34
- # intentionally do not opt in (see the NOTE in each of their identifier.rb).
35
- module IdentifierFacade
36
- # Reconstruct a concrete identifier from its serialized key_value hash by
37
- # dispatching on the `_type` discriminator. Falls back to the flavor's
38
- # `Identifiers::Base` for an absent/unknown type, matching lutaml's own
39
- # non-polymorphic default.
40
- #
41
- # @param data [Hash] the serialized identifier hash (string or symbol keys)
42
- # @return [Pubid::Identifier] the concrete identifier instance
43
- def from_hash(data, options = {})
44
- type = data && (data["_type"] || data[:_type])
45
- klass = polymorphic_type_map[type] || identifier_base_class
46
- klass.from_hash(data, options)
47
- end
48
-
49
- # Map of polymorphic_name ("pubid:nist:interagency-report") => concrete
50
- # class, built once from the flavor's identifier-type registry so it tracks
51
- # newly registered types automatically.
52
- # @return [Hash{String => Class}]
53
- def polymorphic_type_map
54
- @polymorphic_type_map ||=
55
- (identifier_registry_classes + [identifier_base_class]).uniq
56
- .each_with_object({}) do |klass, map|
57
- poly_name = klass.polymorphic_name
58
- map[poly_name] = klass if poly_name
59
- end
60
- end
61
-
62
- private
63
-
64
- # The flavor module that namespaces this facade, e.g. Pubid::Nist for
65
- # Pubid::Nist::Identifier.
66
- def facade_flavor_module
67
- @facade_flavor_module ||=
68
- Object.const_get(name.split("::")[0...-1].join("::"))
69
- end
70
-
71
- def facade_identifiers_namespace
72
- @facade_identifiers_namespace ||=
73
- facade_flavor_module.const_get(:Identifiers)
74
- end
75
-
76
- # Fallback class for an absent/unknown `_type`. Most flavors expose a
77
- # concrete `Identifiers::Base`; flavors without one (e.g. BSI, whose common
78
- # ancestor is SingleIdentifier) fall back to the shared root, which is only
79
- # ever reached for an unrecognized `_type`.
80
- def identifier_base_class
81
- if facade_identifiers_namespace.const_defined?(:Base, false)
82
- facade_identifiers_namespace.const_get(:Base)
83
- else
84
- ::Pubid::Identifier
85
- end
86
- end
87
-
88
- # Every concrete identifier class whose `_type` may appear in a serialized
89
- # hash. Scans the `Identifiers` namespace for descendants of
90
- # Pubid::Identifier (the complete set, independent of whatever filtering the
91
- # flavor's `identifier_types` applies) and unions in `identifier_types`,
92
- # which may register classes living outside that namespace.
93
- def identifier_registry_classes
94
- (scanned_identifier_classes + registered_identifier_classes).uniq
95
- end
96
-
97
- # Concrete identifier classes found directly in the `Identifiers` namespace.
98
- def scanned_identifier_classes
99
- facade_identifiers_namespace.constants.filter_map do |const|
100
- klass = facade_identifiers_namespace.const_get(const)
101
- klass if klass.is_a?(Class) && klass < ::Pubid::Identifier
102
- rescue NameError
103
- nil
104
- end
105
- end
106
-
107
- # Classes the flavor explicitly registers via `identifier_types`, if any.
108
- def registered_identifier_classes
109
- return [] unless facade_flavor_module.respond_to?(:identifier_types)
110
-
111
- Array(facade_flavor_module.identifier_types)
112
- end
113
- end
114
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pubid
4
- module Oiml
5
- module Identifiers
6
- class Base < Pubid::Identifier
7
- attribute :publisher, :string
8
- attribute :type, :string
9
- attribute :code, Oiml::Components::Code
10
- attribute :date, Pubid::Components::Date
11
- attribute :stage, :string
12
- attribute :iteration, :string
13
- attribute :language, :string
14
-
15
- def to_s(**opts)
16
- render(format: :human, **opts)
17
- end
18
- end
19
- end
20
- end
21
- end