class Metacrunch::Marcxml::Document

Public Class Methods

new() click to toggle source
# File lib/metacrunch/marcxml/document.rb, line 11
def initialize
  @controlfields_map = {}
  @datafields_map    = {}
end

Public Instance Methods

[](query_string) click to toggle source

Returns a control field value or data field/sub field values matching the given query string.

@param query_string [String] a query string.

@return [Array<String>] The sub field values matching the query. Is empty if no match

is found.
# File lib/metacrunch/marcxml/document.rb, line 100
def [](query_string)
  # Control field query
  if query_string.starts_with?("00")
    # Example: "005"
    # [0..2] => Control field tag
    tag = query_string[0..2].presence
    controlfield(tag)&.value

  # Data field / sub field query
  else
    # Example: "100**a,e"
    # [0..2] => Data field tag (required).
    # [3]    => Ind1, defaults to `*`, which matches any indicator 1 (optional). ` `, `-` or `_` will be interpreted as `blank`.
    # [4]    => Ind2, defaults to `*`, which matches any indicator 2 (optional). ` `, `-` or `_` will be interpreted as `blank`.
    # [5]    => Sub field code(s) (optional).
    tag      = query_string[0..2].presence

    ind1     = query_string[3].presence
    ind1     = nil    if ind1 == "*"
    ind1     = :blank if ind1 == "-" || ind1 == "_" || ind1 == " "

    ind2     = query_string[4].presence
    ind2     = nil    if ind2 == "*"
    ind2     = :blank if ind2 == "-" || ind2 == "_" || ind2 == " "

    subfield_codes = query_string[5..-1]&.split(",")&.map(&:strip).compact.presence

    datafields(tag, ind1: ind1, ind2: ind2).subfields(subfield_codes).values
  end
end
add_controlfield(controlfield) click to toggle source

@!visibility private

# File lib/metacrunch/marcxml/document.rb, line 40
def add_controlfield(controlfield)
  @controlfields_map[controlfield.tag] = controlfield
end
add_datafield(datafield) click to toggle source

@!visibility private

# File lib/metacrunch/marcxml/document.rb, line 82
def add_datafield(datafield)
  (@datafields_map[datafield.tag] ||= []) << datafield
  datafield
end
controlfield(tag) click to toggle source

Returns the control field matching the given tag or nil if a control field with the given tag does not exist.

@param tag [String, Integer] the tag of the control field. The tag can be

a string or an integer.

@return [Metacrunch::Marcxml::Document::Controlfield, nil] the control field with the matching tag or nil

if a control field with a matching tag does not exist.
# File lib/metacrunch/marcxml/document.rb, line 33
def controlfield(tag)
  @controlfields_map[normalize_tag(tag)]
end
datafields(tag = nil, ind1: nil, ind2: nil) click to toggle source

Returns the data fields matching the given tag(s) and/or ind1/ind2.

@param tag [String, Integer, each, nil] filter by tag(s). Can be `nil`

to match all data fields. The tag can be a string or an integer. To filter for
more than a single tag, `tag` also accepts any object that responds to `#each` like
`Array` and `Range`.

@param ind1 [nil, String, Array<String>] filter by indicator 1. Can be nil to match

any indicator.

@param ind2 [nil, String, Array<String>] filter by indicator 2. Can be nil to match

any indicator.

@return [Metacrunch::Marcxml::Document::DatafieldSet] Set of data fields matching the

given tag(s) and ind1/ind2. The set is empty if a matching field doesn't exist.
# File lib/metacrunch/marcxml/document.rb, line 63
def datafields(tag = nil, ind1: nil, ind2: nil)
  matched_datafields = if tag.nil?
    @datafields_map.values.flatten(1)
  elsif tag.is_a?(Enumerable)
    tag.map{ |_tag| @datafields_map[normalize_tag(_tag)] }.compact.flatten(1)
  else
    @datafields_map[normalize_tag(tag)]
  end

  matched_datafields = (matched_datafields || []).select do |datafield|
    match_indicator(ind1, datafield.ind1) && match_indicator(ind2, datafield.ind2)
  end

  DatafieldSet.new(matched_datafields)
end
empty?() click to toggle source
# File lib/metacrunch/marcxml/document.rb, line 16
def empty?
  @controlfields_map.blank? && @datafields_map.blank?
end

Private Instance Methods

match_indicator(requested_ind, datafield_ind) click to toggle source
# File lib/metacrunch/marcxml/document.rb, line 133
def match_indicator(requested_ind, datafield_ind)
  [*[requested_ind]].flatten.map do |_requested_ind|
    if !_requested_ind
      true
    elsif _requested_ind == :blank && (datafield_ind == " " || datafield_ind == "-" || datafield_ind == "_" || datafield_ind.nil?)
      true
    elsif _requested_ind == datafield_ind
      true
    else
      false
    end
  end.any?
end
normalize_tag(tag) click to toggle source
# File lib/metacrunch/marcxml/document.rb, line 147
def normalize_tag(tag)
  case tag
  when Integer then tag.to_s.rjust(3, "0")
  when String  then tag[0..2]
  else tag.to_s[0..2]
  end
end