Class: Pubid::Scheme

Inherits:
Object
  • Object
show all
Defined in:
lib/pubid/scheme.rb

Overview

Base Scheme class defining the standard interface for all flavor schemes.

The Scheme acts as a registry for identifier types and their associated typed stages. Each flavor (ISO, IEC, IEEE, etc.) should have a Scheme that implements this interface.

Standard Interface

All Scheme implementations must provide these methods:

  • locate_typed_stage_by_abbr(abbr) -> Find a TypedStage by abbreviation

  • locate_identifier_klass_by_type_code(type_code) -> Find an identifier class

  • typed_stages -> Get all typed stages for base identifiers

  • supplement_typed_stages -> Get typed stages for supplements

  • all_typed_stages -> Get all typed stages combined

  • identifiers -> Get all base identifier classes

  • supplement_identifiers -> Get all supplement identifier classes

  • all_identifier_classes -> Get all identifier classes combined

Implementation Patterns

There are several valid patterns for implementing a Scheme:

  1. Class-based (ISO, IEEE, JCGM, JIS, CCSDS, ASHRAE): Use class << self with class methods

  2. Instance-based with constants (BSI, CEN): Use TYPED_STAGES_REGISTRY and instance methods

  3. Transform-based (ITU): Use model_class and transform methods (no typed stages)

  4. Data class (ETSI, Plateau): Use Lutaml::Model::Serializable as a data model

  5. Inheritance-based (AMCA): Inherit from Pubid::Scheme base class

Performance

All registry lookups are memoized for performance. Callers can rely on repeated calls being O(1) after the first call.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(identifiers: [], stages: [], types: [], languages: [], publishers: [], supplement_identifiers: []) ⇒ Scheme

Returns a new instance of Scheme.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/pubid/scheme.rb', line 56

def initialize(
  identifiers: [], stages: [], types: [], languages: [], publishers: [],
  supplement_identifiers: []
)
  @identifiers = identifiers
  @supplement_identifiers = supplement_identifiers
  @stages = stages
  @types = types
  @languages = languages
  @publishers = publishers
end

Instance Attribute Details

#identifiersObject

Registry of identifiers for this scheme



49
50
51
# File 'lib/pubid/scheme.rb', line 49

def identifiers
  @identifiers
end

#languagesObject

Registry of identifiers for this scheme



49
50
51
# File 'lib/pubid/scheme.rb', line 49

def languages
  @languages
end

#publishersObject

Registry of identifiers for this scheme



49
50
51
# File 'lib/pubid/scheme.rb', line 49

def publishers
  @publishers
end

#stagesObject

Registry of identifiers for this scheme



49
50
51
# File 'lib/pubid/scheme.rb', line 49

def stages
  @stages
end

#supplement_identifiersObject

Registry of identifiers for this scheme



49
50
51
# File 'lib/pubid/scheme.rb', line 49

def supplement_identifiers
  @supplement_identifiers
end

#typesObject

Registry of identifiers for this scheme



49
50
51
# File 'lib/pubid/scheme.rb', line 49

def types
  @types
end

Instance Method Details

#all_identifier_classesArray<Class> Also known as: all_identifier_classes_by_type_code

Note:

Memoized for performance

Get all identifier classes sorted by type key

Returns:

  • (Array<Class>)

    All identifier classes sorted by type key



156
157
158
159
160
161
162
# File 'lib/pubid/scheme.rb', line 156

def all_identifier_classes
  return @all_identifier_classes if defined?(@all_identifier_classes)

  @all_identifier_classes = (@identifiers + @supplement_identifiers).sort_by do |klass|
    (klass.type&.dig(:key) || "").to_s
  end
end

#all_typed_stagesArray<TypedStage>

Note:

Memoized for performance

Get all typed stages (base + supplements), sorted by abbreviation

Returns:

  • (Array<TypedStage>)

    All typed stages sorted by abbreviation



97
98
99
100
101
102
103
# File 'lib/pubid/scheme.rb', line 97

def all_typed_stages
  return @all_typed_stages if defined?(@all_typed_stages)

  @all_typed_stages = (typed_stages + supplement_typed_stages).sort_by do |ts|
    (ts.abbr.first || "").to_s
  end.reverse
end

#configure {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:

  • _self (Pubid::Scheme)

    the object that the method was called on



68
69
70
# File 'lib/pubid/scheme.rb', line 68

def configure
  yield self if block_given?
end

#identifier_class_indexHash<String, Class>

Note:

Memoized for O(1) lookup performance

Hash-based index of identifier classes by type code

Returns:

  • (Hash<String, Class>)

    index mapping type codes to identifier classes



184
185
186
# File 'lib/pubid/scheme.rb', line 184

def identifier_class_index
  @identifier_class_index ||= build_identifier_class_index
end

#locate_identifier_klass_by_type_code(type_code) ⇒ Class?

Note:

Uses hash-based index for O(1) lookup, falls back to linear search

Locate an identifier class by type code

Parameters:

  • type_code (String, Symbol)

    The type code to find

Returns:

  • (Class, nil)

    The matching identifier class, or nil if not found



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/pubid/scheme.rb', line 169

def locate_identifier_klass_by_type_code(type_code)
  type_str = type_code.to_s

  # Try hash-based index first (O(1))
  identifier_klass = identifier_class_index[type_str]

  # Fall back to linear search if not found
  identifier_klass || all_identifier_classes.detect do |identifier_class|
    identifier_class.type&.dig(:key)&.to_s == type_str
  end
end

#locate_typed_stage_by_abbr(abbr) ⇒ TypedStage?

Note:

Uses hash-based index for O(1) lookup, falls back to linear search

Locate a TypedStage by abbreviation

Parameters:

  • abbr (String, Symbol)

    The abbreviation to find

Returns:

  • (TypedStage, nil)

    The matching TypedStage, or nil if not found



109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/pubid/scheme.rb', line 109

def locate_typed_stage_by_abbr(abbr)
  abbr = "" if abbr.nil? || abbr.to_s.strip.empty?

  # Try hash-based index first (O(1))
  typed_stage = typed_stage_index[abbr]

  # Fall back to linear search if not found (for abbreviations with
  # special formatting or edge cases)
  typed_stage || all_typed_stages.detect do |ts|
    ts.abbr.include?(abbr)
  end
end

#locate_typed_stage_by_harmonized_code(harmonized_code) ⇒ TypedStage?

Note:

Uses linear search to check harmonized_stages arrays

Locate a TypedStage by harmonized stage code

Parameters:

  • harmonized_code (String)

    The harmonized stage code to find (e.g., “00.00”, “10.00”)

Returns:

  • (TypedStage, nil)

    The matching TypedStage, or nil if not found



138
139
140
141
142
143
144
# File 'lib/pubid/scheme.rb', line 138

def locate_typed_stage_by_harmonized_code(harmonized_code)
  harmonized_str = harmonized_code.to_s

  all_typed_stages.detect do |ts|
    ts.harmonized_stages&.include?(harmonized_str)
  end
end

#locate_typed_stage_by_stage_code(stage_code) ⇒ TypedStage?

Note:

Uses linear search for stage code lookup

Locate a TypedStage by stage code

Parameters:

  • stage_code (String, Symbol)

    The stage code to find

Returns:

  • (TypedStage, nil)

    The matching TypedStage, or nil if not found



126
127
128
129
130
131
132
# File 'lib/pubid/scheme.rb', line 126

def locate_typed_stage_by_stage_code(stage_code)
  stage_code_sym = stage_code.to_sym

  all_typed_stages.detect do |ts|
    ts.stage_code.to_sym == stage_code_sym
  end
end

#supplement_typed_stagesArray<TypedStage>

Note:

Memoized for performance

Get all typed stages for supplement identifiers

Returns:

  • (Array<TypedStage>)

    All typed stages from supplement identifiers



86
87
88
89
90
91
92
# File 'lib/pubid/scheme.rb', line 86

def supplement_typed_stages
  return @supplement_typed_stages if defined?(@supplement_typed_stages)

  @supplement_typed_stages = @supplement_identifiers.filter_map do |identifier_class|
    identifier_class.const_defined?(:TYPED_STAGES) ? identifier_class.const_get(:TYPED_STAGES) : nil
  end.flatten
end

#typed_stage_indexHash<String, TypedStage>

Note:

Memoized for O(1) lookup performance

Hash-based index of typed stages by abbreviation

Returns:

  • (Hash<String, TypedStage>)

    index mapping abbreviations to typed stages



149
150
151
# File 'lib/pubid/scheme.rb', line 149

def typed_stage_index
  @typed_stage_index ||= build_typed_stage_index
end

#typed_stagesArray<TypedStage>

Note:

Memoized for performance

Get all typed stages for base identifiers

Returns:

  • (Array<TypedStage>)

    All typed stages from identifiers



75
76
77
78
79
80
81
# File 'lib/pubid/scheme.rb', line 75

def typed_stages
  return @typed_stages if defined?(@typed_stages)

  @typed_stages = @identifiers.filter_map do |identifier_class|
    identifier_class.const_defined?(:TYPED_STAGES) ? identifier_class.const_get(:TYPED_STAGES) : nil
  end.flatten
end