1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
require "librarian/error"
module Librarian
module Config
class Source
RAW_KEY_SUFFIX_VALIDITY_PATTERN =
/\A[A-Z0-9_]+\z/
CONFIG_KEY_VALIDITY_PATTERN =
/\A[a-z][a-z0-9\-]+(?:\.[a-z0-9\-]+)*\z/
class << self
def raw_key_suffix_validity_pattern
RAW_KEY_SUFFIX_VALIDITY_PATTERN
end
def config_key_validity_pattern
CONFIG_KEY_VALIDITY_PATTERN
end
end
attr_accessor :adapter_name
private :adapter_name=
def initialize(adapter_name, options = { })
self.adapter_name = adapter_name
self.forbidden_keys = options.delete(:forbidden_keys) || []
end
def [](key)
load!
data[key]
end
def []=(key, value)
key_permitted?(key) or raise Error, "key not permitted: #{key.inspect}"
value_permitted?(key, value) or raise Error, "value for key #{key.inspect} not permitted: #{value.inspect}"
load!
if value.nil?
data.delete(key)
else
data[key] = value
end
save(data)
end
def keys
load!
data.keys
end
private
attr_accessor :data, :forbidden_keys
def load!
self.data = load unless data
end
def key_permitted?(key)
String === key &&
config_key_validity_pattern === key &&
!forbidden_keys.any?{|k| k === key}
end
def value_permitted?(key, value)
return true if value.nil?
String === value
end
def raw_key_valid?(key)
return false unless key.start_with?(raw_key_prefix)
suffix = key[raw_key_prefix.size..-1]
raw_key_suffix_validity_pattern =~ suffix
end
def raw_key_suffix_validity_pattern
self.class.raw_key_suffix_validity_pattern
end
def config_key_valid?(key)
config_key_validity_pattern === key
end
def config_key_validity_pattern
self.class.config_key_validity_pattern
end
def raw_key_prefix
@key_prefix ||= "LIBRARIAN_#{adapter_name.upcase}_"
end
def assert_raw_keys_valid!(raw)
bad_keys = raw.keys.reject{|k| raw_key_valid?(k)}
unless bad_keys.empty?
config_path_s = config_path.to_s.inspect
bad_keys_s = bad_keys.map(&:inspect).join(", ")
raise Error, "config #{to_s} has bad keys: #{bad_keys_s}"
end
end
def assert_config_keys_valid!(config)
bad_keys = config.keys.reject{|k| config_key_valid?(k)}
unless bad_keys.empty?
bad_keys_s = bad_keys.map(&:inspect).join(", ")
raise Error, "config has bad keys: #{bad_keys_s}"
end
end
def assert_values_valid!(data)
bad_data = data.reject{|k, v| String === v}
bad_keys = bad_data.keys
unless bad_keys.empty?
bad_keys_s = bad_keys.map(&:inspect).join(", ")
raise Error, "config has bad values for keys: #{bad_keys_s}"
end
end
def translate_raw_to_config(raw)
assert_raw_keys_valid!(raw)
assert_values_valid!(raw)
Hash[raw.map do |key, value|
key = key[raw_key_prefix.size .. -1]
key = key.downcase.gsub(/__/, ".").gsub(/_/, "-")
[key, value]
end]
end
def translate_config_to_raw(config)
assert_config_keys_valid!(config)
assert_values_valid!(config)
Hash[config.map do |key, value|
key = key.gsub(/\./, "__").gsub(/\-/, "_").upcase
key = "#{raw_key_prefix}#{key}"
[key, value]
end]
end
end
end
end
|