Class: MARCSpec::MultiValueMap

Inherits:
Map
  • Object
show all
Defined in:
lib/marcspec/multivaluemap.rb

Overview

A MultiValueMap (in this conectex) is an array of duples of the form

thingToMatch, ‘Value’

(or [thingToMatch, [array,of,values]])

along with an associated name.

Accessing via [] will give you an array of non-nil values that match (via ===) the corresponding keys.

Keys can be either strings or regular expressions (e.g., /^Bil/).

IF the key is a regexp, the value may then be a Proc object that takes a single argument: the MatchData object produced by calling key.match(passed_in_value)

Again, note that if several keys are === to the passed argument, all the values will be returned.

Instance Attribute Summary

Attributes inherited from Map

#map, #mapname

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Map

#==, fromFile, fromHash, fromPPString, #pretty_print

Constructor Details

#initialize(*args) ⇒ MultiValueMap

Override initialize and map= so we can do some optimization



25
26
27
28
# File 'lib/marcspec/multivaluemap.rb', line 25

def initialize *args
  super(*args)
  self.optimize if @map and @mapname
end

Class Method Details

.from_solrmarc_file(filename) ⇒ MARCSpec::MultiValueMap

Try to produce a valid MVMap from a solrmarc file

Parameters:

  • filename (String)

    The file to read

Returns:



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/marcspec/multivaluemap.rb', line 85

def self.from_solrmarc_file filename
  mapname = File.basename(filename).sub(/\..+?$/, '')
  kvlist = []
  File.open(filename) do |f|
    prop = Java::java.util.Properties.new
    prop.load(f.to_inputstream)
    prop.each do |patstring,kv|
      unless patstring =~ /^pattern/ and kv =~ /.+=>.+/
        log.warn "MultiValueMap import skipping weird line in #{filename}\n  #{l}"
        next
      end
      match = /^\s*(.+?)\s*=>\s*(.+?)\s*$/.match(kv)
      kvlist << [Regexp.new(match[1]), match[2]]
    end
  end        
  rv = self.new(nil,nil) # empty; avoid the optimize
  rv.mapname = mapname
  rv.map = kvlist
  return rv
end

Instance Method Details

#[](key, default = nil) ⇒ Object

Given a passed_in_key (and optional default) return the set of values that match, as described above.



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
# File 'lib/marcspec/multivaluemap.rb', line 54

def [] key, default=nil
  rv = []
  
  if @super_regexp.match key # do *any* of them match?
    @map.each do |pv|
      if pv[1].is_a? Proc
        match = pv[0].match key
        rv << pv[1].call(match) if match
      else
        rv << pv[1] if pv[0] === key
      end
    end
    rv.flatten!
    rv.compact!
    rv.uniq!
  end

  if rv.size > 0
    return rv
  else
    if default == :passthrough
      return key
    else
      return default
    end
  end
end

#asPPStringObject

Produce a string suitable for pretty-printing. Unfortunately, we need to just plain delete the procs before doing so



109
110
111
112
113
114
115
116
117
118
# File 'lib/marcspec/multivaluemap.rb', line 109

def asPPString
  map = @map.reject {|kv| kv[1].is_a? Proc}
  s = StringIO.new
  s.print "{\n :maptype=>:multi,\n :mapname=>"
  PP.singleline_pp(@mapname, s)
  s.print ",\n :map => "
  PP.pp(map, s)
  s.puts "\n}"
  return s.string
end

#map=(map) ⇒ Object



30
31
32
# File 'lib/marcspec/multivaluemap.rb', line 30

def map= map
  @map = map
end

#optimizeObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/marcspec/multivaluemap.rb', line 35

def optimize
  @super_regexp = Regexp.union @map.map{|pv| pv[0]}
  inverted = {}
  @map.each do |pv|
    inverted[pv[1]] ||= []
    inverted[pv[1]] << pv[0]
  end
  inverted.each_pair do |vals, patterns|
    next unless patterns.size > 1
    newpat = Regexp.union patterns
    patterns.each do |p|
      @map.delete_if{|pv| p == pv[0]}
    end
    @map << [newpat, vals]
  end
end