Class: GovCodes::Dafecd::RiSdi::IndexBuilder
- Inherits:
-
Object
- Object
- GovCodes::Dafecd::RiSdi::IndexBuilder
- Defined in:
- lib/gov_codes/dafecd/ri_sdi/index_builder.rb
Overview
Assembles the RI and SDI records of one publication into a single code-keyed index and surfaces the reconciliation data the CLI reports.
Every section named by the Config is sliced out and parsed by the format it uses: SDI sections by the SdiSectionSplitter + SdiCardParser (plus the one embedded CEM ladder record, parsed by the AFSC SpecialtyParser and keyed by its CEM code), RI sections by the RiListParser.
Verification gate: every emitted code must appear verbatim in the source, and every emitted acronym must appear as a "(ACRONYM)" parenthetical in its record's raw title (whitespace/dash/case tolerant). Titles are extracted verbatim (only sanitized) and then de-glued via human-verified overrides supplied by an injected TitleDegluer: each applied override is gated against the raw source title (spacing/case only), so drift lands in #unverified_titles and fails the build; a code with no override keeps its verbatim title and is reported in #codes_needing_deglue (not an error). #unverified? must be false before anything is written.
Acronyms are captured from a title's trailing parenthetical, EXCEPT for the per-publication Config#acronym_exclusions (organization/sub-phrase abbreviations). Every candidate — shipped or excluded — is reported via #acronym_candidates for review.
Constant Summary collapse
- ACRONYM_PATTERN =
A trailing parenthetical whose sole token is an uppercase abbreviation. Mirrors Dafecd::IndexBuilder::ACRONYM_PATTERN.
/\(([A-Z][A-Z0-9]{1,7})\)\s*\z/- UNICODE_DASHES =
Patterns::UNICODE_DASHES
Instance Attribute Summary collapse
-
#acronym_candidates ⇒ Object
readonly
Returns the value of attribute acronym_candidates.
-
#codes_needing_deglue ⇒ Object
readonly
Returns the value of attribute codes_needing_deglue.
-
#collisions ⇒ Object
readonly
Returns the value of attribute collisions.
-
#dropped_records ⇒ Object
readonly
Returns the value of attribute dropped_records.
-
#index ⇒ Object
readonly
Returns the value of attribute index.
-
#section_codes ⇒ Object
readonly
Returns the value of attribute section_codes.
-
#section_counts ⇒ Object
readonly
Returns the value of attribute section_counts.
-
#sequence_numbers ⇒ Object
readonly
Returns the value of attribute sequence_numbers.
-
#unverified_acronyms ⇒ Object
readonly
Returns the value of attribute unverified_acronyms.
-
#unverified_codes ⇒ Object
readonly
Returns the value of attribute unverified_codes.
-
#unverified_titles ⇒ Object
readonly
Returns the value of attribute unverified_titles.
Instance Method Summary collapse
- #build ⇒ Object
-
#initialize(full_text, config: Config.dafecd, degluer: TitleDegluer.empty) ⇒ IndexBuilder
constructor
A new instance of IndexBuilder.
-
#sequence_report ⇒ Hash{Symbol=>Hash}
Force => missing:, duplicates:.
-
#title_inventory ⇒ Array<Hash>
raw_title: in code order, for the governed de-glue pass (titles are NOT cleaned here).
-
#unverified? ⇒ Boolean
True if any emitted value failed verification; the CLI must not write.
Constructor Details
#initialize(full_text, config: Config.dafecd, degluer: TitleDegluer.empty) ⇒ IndexBuilder
Returns a new instance of IndexBuilder.
52 53 54 55 56 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 52 def initialize(full_text, config: Config.dafecd, degluer: TitleDegluer.empty) @full_text = full_text @config = config @degluer = degluer end |
Instance Attribute Details
#acronym_candidates ⇒ Object (readonly)
Returns the value of attribute acronym_candidates.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def acronym_candidates @acronym_candidates end |
#codes_needing_deglue ⇒ Object (readonly)
Returns the value of attribute codes_needing_deglue.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def codes_needing_deglue @codes_needing_deglue end |
#collisions ⇒ Object (readonly)
Returns the value of attribute collisions.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def collisions @collisions end |
#dropped_records ⇒ Object (readonly)
Returns the value of attribute dropped_records.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def dropped_records @dropped_records end |
#index ⇒ Object (readonly)
Returns the value of attribute index.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def index @index end |
#section_codes ⇒ Object (readonly)
Returns the value of attribute section_codes.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def section_codes @section_codes end |
#section_counts ⇒ Object (readonly)
Returns the value of attribute section_counts.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def section_counts @section_counts end |
#sequence_numbers ⇒ Object (readonly)
Returns the value of attribute sequence_numbers.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def sequence_numbers @sequence_numbers end |
#unverified_acronyms ⇒ Object (readonly)
Returns the value of attribute unverified_acronyms.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def unverified_acronyms @unverified_acronyms end |
#unverified_codes ⇒ Object (readonly)
Returns the value of attribute unverified_codes.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def unverified_codes @unverified_codes end |
#unverified_titles ⇒ Object (readonly)
Returns the value of attribute unverified_titles.
48 49 50 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 48 def unverified_titles @unverified_titles end |
Instance Method Details
#build ⇒ Object
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 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 58 def build @index = {} @dropped_records = [] @collisions = [] @acronym_candidates = [] @unverified_codes = [] @unverified_titles = [] @unverified_acronyms = [] @codes_needing_deglue = [] @section_counts = Hash.new(0) @section_codes = Hash.new { |h, k| h[k] = [] } @sequence_numbers = Hash.new { |h, k| h[k] = [] } SectionSlicer.new(@full_text, config: @config).sections.each do |section| case section.kind when :sdi then build_sdi(section) when :ri then build_ri(section) end end @index.each { |code, entry| apply_override(code, entry) } @index.each { |code, entry| capture_acronym(code, entry) } @index.each { |code, entry| verify(code, entry) } @index end |
#sequence_report ⇒ Hash{Symbol=>Hash}
Returns force => missing:, duplicates:.
90 91 92 93 94 95 96 97 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 90 def sequence_report @sequence_numbers.transform_values do |numbers| present = numbers.uniq.sort duplicates = numbers.group_by(&:itself).select { |_, v| v.size > 1 }.keys.sort missing = present.empty? ? [] : ((present.first..present.last).to_a - present) {present: present, missing: missing, duplicates: duplicates} end end |
#title_inventory ⇒ Array<Hash>
Returns raw_title: in code order, for the governed de-glue pass (titles are NOT cleaned here).
101 102 103 104 105 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 101 def title_inventory @index.sort_by { |code, _| code.to_s }.map do |code, entry| {code: code, name: entry[:name], raw_title: entry[:raw_title], glued: entry[:glued_title]} end end |
#unverified? ⇒ Boolean
True if any emitted value failed verification; the CLI must not write.
85 86 87 |
# File 'lib/gov_codes/dafecd/ri_sdi/index_builder.rb', line 85 def unverified? @unverified_codes.any? || @unverified_titles.any? || @unverified_acronyms.any? end |