module MasterView # Extends Hash to allow case insensitive access to data using any case string or symbol, # however it retains the original case when iterated on. When updating a value it first checks # for the existence of a case indendependent key and if found uses that for storage key, # thus the first form to store determines the case. class CaseInsensitiveHash < Hash def initialize super init_lcks_map end # uses a lowercased symbol to find original key which is then used to find value def [](key) original_key = @lcks_to_original_key[convert_to_lcs(key)] (original_key.nil?) ? nil : super(original_key) end # put value into map first checking if there is already an entry using lowercased # symbol, if so use it (it determines key case), otherwise add new entry def []=(key, value) lcks = convert_to_lcs(key) original_key = @lcks_to_original_key[lcks] if original_key.nil? # not found so create new original key in map @lcks_to_original_key[lcks] = key original_key = key end super(original_key, value) end alias :store :[]= # build hash from another hash def replace(hash) super(hash) init_lcks_map hash.each do |k,v| @lcks_to_original_key[convert_to_lcs(k)] = k end end # retrieves the lowercased string value for the key def get_lowercase_str_value(key) value = self[key] unless value.nil? if value.is_a? String value.downcase! elsif value.is_a? Symbol value = value.to_s.downcase else value = value.inspect.downcase end end value end private # reset lowercased symbol map def init_lcks_map @lcks_to_original_key = {} # lower case key symbol to original key map end # convert to lowercased symbol def convert_to_lcs(key) key.to_s.downcase.to_sym end end end