Class: ROF::Filters::Label

Inherits:
ROF::Filter show all
Defined in:
lib/rof/filters/label.rb

Overview

Class Label locates in-place labels of the form “$(label_name)” in the ROF file, assigns each label a pid, then replaces the label with that pid.

Defined Under Namespace

Classes: AccessMappingNotFound, MissingLabel, NoPool, NoidsPool, OutOfIdentifiers

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Label

Returns a new instance of Label.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :prefix (String, nil)
    • if truthy, prepend “<prefix>:” to each identifier

  • :id_list (Array, nil)
    • circumvent using the :noids configuration and instead use these for next_ids

  • :noids (Hash)
    • A Hash with keys :noid_server and :pool_name; Responsible for minting next_ids

Raises:

  • NoPool if we don’t have a means of determining the next_id



27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rof/filters/label.rb', line 27

def initialize(options = {})
  prefix = options.fetch(:prefix, nil)
  @id_list =  case
              when options[:id_list]
                options[:id_list]
              when options[:noids]
                NoidsPool.new(options[:noids].fetch(:noid_server), options[:noids].fetch(:pool_name))
              else
                raise NoPool
              end
  @prefix = "#{prefix}:" if prefix
  # The first match group in the RE provides the label name
  @label_re = /\$\(([^)]+)\)/
end

Instance Method Details

#assign_pid(obj, labels) ⇒ Object

assign pids, recording any labels we find. obj is mutated



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/rof/filters/label.rb', line 78

def assign_pid(obj, labels)
  return if obj['type'] != 'fobject'

  label = nil
  unless obj['pid'].nil?
    label = find_label(obj['pid'])
    # skip if the "pid" is not a label
    return if label.nil?
  end
  pid = "#{@prefix}#{next_id}"
  obj['pid'] = pid
  labels[label] = pid unless label.nil?
end

#find_label(s) ⇒ Object



130
131
132
# File 'lib/rof/filters/label.rb', line 130

def find_label(s)
  s[@label_re, 1]
end

#next_idObject

Raises:



134
135
136
137
# File 'lib/rof/filters/label.rb', line 134

def next_id
  raise OutOfIdentifiers if @id_list.empty?
  @id_list.shift
end

#process(obj_list) ⇒ Object

mutate obj_list by assigning labels and resolving labels where needed Every fobject will be assigned an pid and a bendo_item



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
# File 'lib/rof/filters/label.rb', line 44

def process(obj_list)
  labels = {}

  # Use two passes. First assign ids, and then resolve labels
  # Do this since labels can be referenced before being defined

  # Assign pids to each fobject. If we find any labels in the pid field, then
  # record a mapping of label => pid into the labels hash.
  obj_list.each do |obj|
    assign_pid(obj, labels)
  end

  # now replace any reference labels with the pids we've assigned them
  obj_list.each do |obj|
    replace_labels_in_obj(obj, labels)
  end

  # now assign bendo ids
  bendo_item = nil
  obj_list.each do |obj|
    # for now we just use the first item's pid stripped of any namespaces as the bendo item id
    if bendo_item.nil?
      bendo_item = obj['pid'].gsub(/^.*:/, '') unless obj['pid'].nil?
      next if bendo_item.nil?
    end
    # don't touch if a bendo item has already been assigned
    obj['bendo-item'] = bendo_item if obj['bendo-item'].nil? || obj['bendo-item'] == ''
  end

  obj_list
end

#replace_labels(obj, labels, force = false) ⇒ Object

recurse through obj replacing any labels in strings with the id in labels, which is a hash. The relacement is done in place. Hash keys are not touched (only hash values). if force is true, labels which don’t resolve will raise a MissingLabel error.



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/rof/filters/label.rb', line 108

def replace_labels(obj, labels, force = false)
  if obj.is_a?(Array)
    obj.map! { |x| replace_labels(x, labels, force) }
  elsif obj.is_a?(Hash)
    obj.each { |k, v| obj[k] = replace_labels(v, labels, force) }
    obj
  elsif obj.is_a?(String)
    replace_match(obj, labels, force)
  else
    obj
  end
end

#replace_labels_in_obj(obj, labels) ⇒ Object

replace any label references we find in obj. obj is mutated



94
95
96
97
98
99
100
# File 'lib/rof/filters/label.rb', line 94

def replace_labels_in_obj(obj, labels)
  return if obj['type'] != 'fobject'
  obj.each do |k, v|
    # only force labels to exist if we are looking in the rels-ext
    obj[k] = replace_labels(v, labels, k == 'rels-ext')
  end
end

#replace_match(obj, labels, force) ⇒ Object

small matching function- uses regular expression



122
123
124
125
126
127
128
# File 'lib/rof/filters/label.rb', line 122

def replace_match(obj, labels, force)
  obj.gsub(@label_re) do |match|
    pid = labels[Regexp.last_match(1)]
    raise MissingLabel if pid.nil? && force
    pid.nil? ? match : pid
  end
end