Class: Pubid::Nist::Router

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

Overview

Router class for NIST series-to-class mapping Single Responsibility: Resolve parsed data to the correct identifier class

Delegates to Pubid::Nist.locate_stage / Pubid::Nist.locate_type for series-to-class resolution.

Constant Summary collapse

VALID_SERIES =

All valid series codes (comprehensive list)

[
  # Major series with dedicated classes
  "SP", "FIPS", "IR", "HB", "TN",
  # Specialized series with dedicated classes
  "CIRC", "CRPL", "CS", "CSM",
  # Other series (use Base class)
  "GCR", "AMS", "BSS", "BMS", "BH", "MONO", "MP",
  "NCSTAR", "NSRDS", "CSWP", "VTS", "AI", "OWMWP",
  "PC", "RPT", "SIBS", "TIBM", "TTB", "EAB",
  "JPCRD", "JRES", "CIS", "HR", "IRPL", "IP",
  "LC", "PS", "LCIRC",
  # Compound series
  "BRPD-CRPL-D", "CRPL-F-A", "CRPL-F-B", "CS-E",
  "CSRC Building Block", "CSRC Use Case", "CSRC Book",
  "ITL Bulletin", "NIST LC", "NIST PS", "NIST DCI",
  "NIST Other", "NSRDS-NBS",
].freeze

Instance Method Summary collapse

Instance Method Details

#has_supplement?(parsed_hash) ⇒ Boolean

Check if parsed hash has supplement indicators

Parameters:

  • parsed_hash (Hash)

    the parsed identifier data

Returns:

  • (Boolean)

    true if supplement indicators are present



139
140
141
142
143
144
145
# File 'lib/pubid/nist/router.rb', line 139

def has_supplement?(parsed_hash)
  parsed_hash[:supplement] ||
    parsed_hash[:supplement_date_range] ||
    parsed_hash[:supplement_date] ||
    parsed_hash[:supplement_slash_year] ||
    parsed_hash[:supplement_with_rev]
end

#locate_identifier_klass(parsed_hash) ⇒ Class

Locate identifier class by series and pattern

Parameters:

  • parsed_hash (Hash)

    the parsed identifier data

Returns:

  • (Class)

    the identifier class



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/pubid/nist/router.rb', line 40

def locate_identifier_klass(parsed_hash)
  # Date-style identifier (no series) dispatches here, not via series lookup.
  if parsed_hash[:dated_date] && parsed_hash[:dated_seq]
    return Identifiers::DatedDocument
  end

  series = parsed_hash[:series]&.to_s

  # Handle compound series that include publisher (both space and dot separated)
  if series&.start_with?("NBS ")
    simple_series = series.sub("NBS ", "")

    # Check for CIRC supplement
    if simple_series == "CIRC"
      if has_supplement?(parsed_hash)
        return Identifiers::CircularSupplement
      else
        return Identifiers::Circular
      end
    end

    # Use simple series for lookup (TYPED_STAGES abbr handles compound forms)
    series = simple_series
  elsif series&.start_with?("NBS.")
    # Handle dot-separated patterns (e.g., "NBS.LCIRC" after preprocessing)
    simple_series = series.sub("NBS.", "")

    # Check for LCIRC supplement (dot-separated variant)
    if simple_series == "LCIRC"
      if has_supplement?(parsed_hash)
        return Identifiers::CircularSupplement
      else
        return Identifiers::LetterCircular
      end
    end

    # Check for CIRC supplement (dot-separated variant)
    if simple_series == "CIRC"
      if has_supplement?(parsed_hash)
        return Identifiers::CircularSupplement
      else
        return Identifiers::Circular
      end
    end

    # Use simple series for lookup
    series = simple_series
  elsif series&.start_with?("NIST.")
    # Handle dot-separated NIST patterns
    simple_series = series.sub("NIST.", "")

    # Check for LCIRC supplement (dot-separated variant)
    if simple_series == "LCIRC"
      if has_supplement?(parsed_hash)
        return Identifiers::CircularSupplement
      else
        return Identifiers::LetterCircular
      end
    end

    # Use simple series for lookup
    series = simple_series
  end

  # Check for CS variants (works for both compound "NBS CS" and simple "CS")
  if series == "CS"
    first_num = parsed_hash[:first_number]

    # Check for CSM (monthly) - v#n# pattern inside first_number hash
    if first_num.is_a?(Hash) && first_num[:volume_number] && first_num[:issue_number]
      return Identifiers::CommercialStandardsMonthly
    end

    # Check for CS-E (emergency) - e-prefix with 3+ digits
    # Handle Parslet::Slice by converting to string
    first_num_str = first_num.is_a?(String) ? first_num.to_str : first_num.to_s

    # Match e104 or e104 (when "e104-43" is split into first+second)
    if /^e\d{3,}/.match?(first_num_str)
      return Identifiers::CommercialStandardEmergency
    end
  end

  # Look up using TYPED_STAGES registry (replaces series_to_class_map)
  # This handles simple series, compound series (via abbr array), and all variants
  # Delegates to Pubid::Nist.locate_stage / Pubid::Nist.locate_type
  # instead of an injected dependency.
  typed_stage = Pubid::Nist.locate_stage(series)
  if typed_stage
    Pubid::Nist.locate_type(typed_stage.type_code) || Identifiers::Base
  else
    # Fallback to Base for unmapped series (e.g., "AMS", "VTS")
    Identifiers::Base
  end
end

#valid_series?(series_code) ⇒ Boolean

Check if series is valid

Parameters:

  • series_code (String)

    the series code

Returns:

  • (Boolean)

    true if series is valid



33
34
35
# File 'lib/pubid/nist/router.rb', line 33

def valid_series?(series_code)
  VALID_SERIES.include?(series_code)
end