class NistPubid::Document

Attributes

addendum[RW]
appendix[RW]
code[RW]
edition[RW]
errata[RW]
index[RW]
insert[RW]
part[RW]
publisher[RW]
revision[RW]
section[RW]
serie[RW]
stage[RW]
supplement[RW]
translation[RW]
update_number[RW]
update_year[RW]
version[RW]
volume[RW]

Public Class Methods

match(regex, code) click to toggle source
# File lib/nist_pubid/document.rb, line 222
def self.match(regex, code)
  regex.match(code)&.to_s
end
new(publisher:, serie:, docnumber:, **opts) click to toggle source
# File lib/nist_pubid/document.rb, line 88
def initialize(publisher:, serie:, docnumber:, **opts)
  @publisher = Publisher.new(publisher: publisher)
  @serie = Serie.new(serie: serie)
  @code = docnumber
  opts.each { |key, value| send("#{key}=", value) }
end
parse(code) click to toggle source
# File lib/nist_pubid/document.rb, line 129
def self.parse(code)
  code = update_old_code(code)
  matches = {
    publisher: match(Publisher.regexp, code) || "NIST",
    serie: match(Serie.regexp, code),
    stage: Stage.parse(code),
    part: /(?<=(\.))?(?<![a-z])+(?:pt|Pt|p)(?(1)-)([A-Z\d]+)/.match(code)
            &.[](2),
    version:
      /(?<=\.)?(?:(?:ver)((?(1)[-\d]|[.\d])+|\d+)|(?:v)(\d+\.[.\d]+))/
        .match(code).to_a[1..-1]&.compact&.first&.gsub(/-/, "."),
    revision: /[\da](?:r|Rev\.\s|([0-9]+[A-Za-z]*-[0-9]+[A-Za-z]*-))([\da]+)/
      .match(code)&.[](2),
    addendum: match(/(?<=(\.))?(add(?:-\d+)?|Addendum)/, code),
    edition: /(?<=[^a-z])(?<=\.)?(?:e(?(1)-)|Ed\.\s)(\d+)|
              NBS\sFIPS\sPUB\s[0-9]+[A-Za-z]*-[0-9]+[A-Za-z]*-([A-Za-z\d]+)
      /x.match(code)&.captures&.join,
    section: /(?<=sec)\d+/.match(code)&.to_s,
    appendix: /\d+app/.match(code)&.to_s,
    errata: /-errata|\d+err(?:ata)?/.match(code)&.to_s,
    index: /\d+index|\d+indx/.match(code)&.to_s,
    insert: /\d+ins(?:ert)?/.match(code)&.to_s
  }
  supplement = /(?:(?:supp?)-?(\d*)|Supplement|Suppl.)/
    .match(code)
  unless supplement.nil?
    matches[:supplement] = supplement[1].nil? ? "" : supplement[1]
  end

  update = code.scan(/((?<=Upd)\s?[\d:]+|-upd)-?(\d*)/).first

  (matches[:update_number], matches[:update_year]) = update if update

  unless matches[:serie]
    raise Errors::ParseError.new("failed to parse serie for #{code}")
  end

  unless matches[:stage].nil?
    code = code.gsub(matches[:stage].original_code, "")
  end

  unless ["NBS CSM", "NBS CS"].include?(matches[:serie])
    matches[:volume] = /(?<=(\.))?v(?(1)-)(\d+)(?!\.\d+)/.match(code)&.[](2)
  end

  matches[:revision] = nil if matches[:addendum]

  matches[:docnumber] = parse_docnumber(matches[:serie], code)

  matches[:serie] = SERIES["mr"].invert[matches[:serie]] || matches[:serie]
  # matches[:serie].gsub!(/\./, " ")
  matches[:translation] = match(/(?<=\()\w{3}(?=\))/, code)

  new(**matches)
end
parse_docnumber(serie, code) click to toggle source
# File lib/nist_pubid/document.rb, line 185
def self.parse_docnumber(serie, code)
  localities = "[Pp]t\\d+|r(?:\\d+|[A-Za-z]?)|e\\d+|p|v|sec\\d+|inde?x|err(?:ata)?|ins(?:ert)?"
  excluded_parts = "(?!#{localities}|supp?)"

  if ["NBS CSM", "NBS CS"].include?(serie)
    docnumber = /v(\d+)n(\d+)/.match(code).to_a[1..-1]&.join("-")
  else
    # match docnumbers with localities in the first part, like NBS CIRC 11e2-1915
    docnumber =
      /(?:#{serie.gsub(" ", "\s|\.")})(?:\s|\.)?([0-9]+)(?:#{localities})(-[0-9]+)?/
        .match(code)&.captures&.join

    docnumber ||=
      /(?:#{serie.gsub(" ", "\s|\.")})(?:\s|\.)? # match serie
       ([0-9]+ # first part of report number
         (?:#{excluded_parts}[A-Za-z]+)? # with letter but without localities
         (?:-m)? # for NBS CRPL 4-m-5
         (?:-[A-Za]+)? # for NIST SP 1075-NCNR, NIST SP 1113-BFRL, NIST IR 6529-a
         (?:-[0-9.]+)? # second part
         (?:
           (?: # only big letter
             (#{excluded_parts}[A-Z]|(?![a-z]))+|#{excluded_parts}[a-z]?|#{excluded_parts}[a-z]+
           )? # or small letter but without localities
         )
       )/x
        .match(code)&.[](1)&.upcase
  end

  unless docnumber
    raise Errors::ParseError.new(
      "failed to parse document identifier for #{code}",
    )
  end

  docnumber
end
update_old_code(code) click to toggle source
# File lib/nist_pubid/document.rb, line 111
def self.update_old_code(code)
  code = code.gsub("FIPS", "FIPS PUB") unless code.include?("FIPS PUB")
  code.gsub("NBS MONO", "NBS MN").gsub("NIST MONO", "NIST MN")
    .gsub("NIST MP", "NBS MP")
    .gsub("NIST SP 304a-2017", "NIST SP 304A-2017")
    .gsub("NIST SP 260-162 2006ed.", "NIST SP 260-162e2006")
    .gsub("NBS CIRC 154suprev", "NBS CIRC 154r1sup")
    .gsub("NIST SP 260-126 rev 2013", "NIST SP 260-126r2013")
    .gsub("NIST CSWP", "NIST CSRC White Paper")
    .gsub("NIST.CSWP.01162020pt", "NIST.CSWP.01162020(por)")
    .gsub(/(?<=NBS MP )(\d+)\((\d+)\)/, '\1e\2')
    .gsub(/(?<=\d)es/, "(spa)")
    .gsub(/(?<=\d)chi/, "(zho)")
    .gsub(/(?<=\d)viet/, "(vie)")
    .gsub(/(?<=\d)port/, "(por)")
    # .gsub(/^LCIRC/, "NBS LC")
end

Public Instance Methods

merge(document) click to toggle source
# File lib/nist_pubid/document.rb, line 102
def merge(document)
  instance_variables.each do |var|
    val = document.instance_variable_get(var)
    instance_variable_set(var, val) unless val.nil?
  end

  self
end
render_addendum(input, format) click to toggle source
# File lib/nist_pubid/document.rb, line 326
def render_addendum(input, format)
  return input unless addendum

  case format
  when :long
    "Addendum to #{input}"
  when :abbrev
    "Add. to #{input}"
  when :short
    "#{input} Addendum"
  when :mr
    "#{input}.add-1"
  end
end
render_edition(format) click to toggle source
# File lib/nist_pubid/document.rb, line 272
def render_edition(format)
  result = ""

  result += "#{REVISION_DESC[format]}#{revision.to_s.upcase}" if revision
  result += "#{VERSION_DESC[format]}#{version}" unless version.nil?
  result += "#{EDITION_DESC[format]}#{edition}" unless edition.nil?
  result
end
render_localities(format) click to toggle source
# File lib/nist_pubid/document.rb, line 281
def render_localities(format)
  result = ""
  result += "#{SUPPLEMENT_DESC[format]}#{supplement}" unless supplement.nil?
  result += "#{SECTION_DESC[format]}#{section}" unless section.nil?
  result += "#{APPENDIX_DESC[format]}" unless appendix.nil?
  result += "#{ERRATA_DESC[format]}" unless errata.nil?
  result += INDEX_DESC[format] unless index.nil?
  result += INSERT_DESC[format] unless insert.nil?

  result
end
render_part(format) click to toggle source
# File lib/nist_pubid/document.rb, line 265
def render_part(format)
  result = ""
  result += "#{VOLUME_DESC[format]}#{volume}" unless volume.nil?
  result += "#{PART_DESC[format]}#{part}" unless part.nil?
  result
end
render_serie(format) click to toggle source
# File lib/nist_pubid/document.rb, line 257
def render_serie(format)
  if serie.to_s(format).include?(publisher.to_s(format))
    return serie.to_s(format)
  end

  "#{publisher.to_s(format)} #{serie.to_s(format)}"
end
render_translation(format) click to toggle source
# File lib/nist_pubid/document.rb, line 315
def render_translation(format)
  return "" if translation.nil?

  case format
  when :long, :abbrev
    " (#{translation.upcase})"
  else
    "(#{translation})"
  end
end
render_update(format) click to toggle source
# File lib/nist_pubid/document.rb, line 293
def render_update(format)
  return "" if update_year.nil?

  if update_number.match?(/\d+/)
    update_text = update_number
    update_text += "-#{update_year}" if update_year
  else
    update_text = "1"
  end

  case format
  when :long
    " Update #{update_text}"
  when :abbrev
    " Upd. #{update_text}"
  when :short
    "/Upd#{update_text}"
  when :mr
    ".u#{update_text}"
  end
end
to_json(*args) click to toggle source
# File lib/nist_pubid/document.rb, line 240
def to_json(*args)
  result = {
    styles: {
      short: to_s(:short),
      abbrev: to_s(:abbrev),
      long: to_s(:long),
      mr: to_s(:mr),
    }
  }

  instance_variables.each do |var|
    val = instance_variable_get(var)
    result[var.to_s.gsub('@', '')] = val unless val.nil?
  end
  result.to_json(*args)
end
to_s(format = :short) click to toggle source
# File lib/nist_pubid/document.rb, line 226
def to_s(format = :short)
  result = render_serie(format)
  result += " " unless format == :short || stage.nil?
  result += "#{stage&.to_s(format)}"\
            " #{code}#{render_part(format)}#{render_edition(format)}"\
            "#{render_localities(format)}"\
            "#{render_update(format)}#{render_translation(format)}"
  result = render_addendum(result, format)

  return result.gsub(" ", ".") if format == :mr

  result
end
weight() click to toggle source

returns weight based on amount of defined attributes

# File lib/nist_pubid/document.rb, line 96
def weight
  instance_variables.inject(0) do |sum, var|
    sum + (instance_variable_get(var).nil? ? 0 : 1)
  end
end