<commit_before>
module Coral
class Config
  
  #-----------------------------------------------------------------------------
  # Global interface

  extend Mixin::ConfigOptions
  extend Mixin::ConfigCollection
  extend Mixin::Lookup
  extend Mixin::ConfigOps
  
  #-----------------------------------------------------------------------------
  # Instance generators
  
  def self.ensure(config)
    case config
    when Coral::Config
      return config
    when Hash
      return new(config) 
    end
    return new
  end
  
  #---
  
  def self.init(options, contexts = [], hierarchy = [], defaults = {})
    contexts = contexts(contexts, hierarchy)
    config   = new(get_options(contexts), defaults)
    config.import(options) unless Util::Data.empty?(options)
    return config
  end
  
  #---
  
  def self.init_flat(options, contexts = [], defaults = {})
    return init(options, contexts, [], defaults)
  end
   
  #-----------------------------------------------------------------------------
  # Constructor / Destructor
   
  def initialize(data = {}, defaults = {}, force = true)
    @force      = force
    @properties = {}
    
    if defaults.is_a?(Hash) && ! defaults.empty?
      defaults = symbol_map(defaults)
    end
    
    case data
    when Coral::Config
      @properties = Util::Data.merge([ defaults, data.export ], force)
    when Hash
      @properties = {}
      if data.is_a?(Hash)
        @properties = Util::Data.merge([ defaults, symbol_map(data) ], force)
      end  
    end
  end
  
  #---
  
  def inspect
    "#<#{self.class}: #{@properties.to_s}>"
  end
      
  #-----------------------------------------------------------------------------
  # Property accessors / modifiers
    
  def fetch(data, keys, default = nil, format = false)    
    if keys.is_a?(String) || keys.is_a?(Symbol)
      keys = [ keys ]
    end    
    key = keys.shift.to_sym
    
    if data.has_key?(key)
      value = data[key]
      
      if keys.empty?
        return filter(value, format)
      else
        return fetch(data[key], keys, default, format)  
      end
    end
    return filter(default, format)
  end
  protected :fetch
  
  #---
  
  def modify(data, keys, value = nil) 
    if keys.is_a?(String) || keys.is_a?(Symbol)
      keys = [ keys ]
    end
        
    key      = keys.shift.to_sym
    has_key  = data.has_key?(key)
    existing = { 
      :key   => key, 
      :value => ( has_key ? data[key] : nil ) 
    }
    
    if keys.empty?      
      existing[:value] = data[key] if has_key
      
      if value.nil?
        data.delete(key) if has_key
      else
        data[key] = value
      end
    else      
      data[key] = {} unless has_key
      existing  = modify(data[key], keys, value)  
    end
    
    return existing
  end
  protected :modify
  
  #---
  
  def get(keys, default = nil, format = false)
    return fetch(@properties, array(keys).flatten, default, format)
  end

  #---
 
  def [](name, default = nil, format = false)
    get(name, default, format)
  end
  
  #---
  
  def get_array(keys, default = [])
    return get(keys, default, :array)
  end
  
  #---
  
  def get_hash(keys, default = {})
    return get(keys, default, :hash)
  end
  
  #---
  
  def init(keys, default = nil)
    return set(keys, get(keys, default))
  end

  #---
  
  def set(keys, value)
    modify(@properties, array(keys).flatten, value)
    return self
  end
  
  #---
  
  def []=(name, value)
    set(name, value)
  end
   
  #---
  
  def delete(keys, default = nil)
    existing = modify(@properties, array(keys).flatten, nil)
    return existing[:value] if existing[:value]
    return default
  end
  
  #---
  
  def clear
    @properties = {}
    return self
  end

  #-----------------------------------------------------------------------------
  # Import / Export
 
  def import_base(properties, options = {})
    config      = Config.new(options, { :force => @force }).set(:context, :hash)    
    import_type = config.get(:import_type, :override)
    
    case properties
    when Hash
      data = [ @properties, symbol_map(properties) ]
      data = data.reverse if import_type != :override<commit_msg>Updating an import parameter translation in the base config class.<commit_after>
module Coral
class Config
  
  #-----------------------------------------------------------------------------
  # Global interface

  extend Mixin::ConfigOptions
  extend Mixin::ConfigCollection
  extend Mixin::Lookup
  extend Mixin::ConfigOps
  
  #-----------------------------------------------------------------------------
  # Instance generators
  
  def self.ensure(config)
    case config
    when Coral::Config
      return config
    when Hash
      return new(config) 
    end
    return new
  end
  
  #---
  
  def self.init(options, contexts = [], hierarchy = [], defaults = {})
    contexts = contexts(contexts, hierarchy)
    config   = new(get_options(contexts), defaults)
    config.import(options) unless Util::Data.empty?(options)
    return config
  end
  
  #---
  
  def self.init_flat(options, contexts = [], defaults = {})
    return init(options, contexts, [], defaults)
  end
   
  #-----------------------------------------------------------------------------
  # Constructor / Destructor
   
  def initialize(data = {}, defaults = {}, force = true)
    @force      = force
    @properties = {}
    
    if defaults.is_a?(Hash) && ! defaults.empty?
      defaults = symbol_map(defaults)
    end
    
    case data
    when Coral::Config
      @properties = Util::Data.merge([ defaults, data.export ], force)
    when Hash
      @properties = {}
      if data.is_a?(Hash)
        @properties = Util::Data.merge([ defaults, symbol_map(data) ], force)
      end  
    end
  end
  
  #---
  
  def inspect
    "#<#{self.class}: #{@properties.to_s}>"
  end
      
  #-----------------------------------------------------------------------------
  # Property accessors / modifiers
    
  def fetch(data, keys, default = nil, format = false)    
    if keys.is_a?(String) || keys.is_a?(Symbol)
      keys = [ keys ]
    end    
    key = keys.shift.to_sym
    
    if data.has_key?(key)
      value = data[key]
      
      if keys.empty?
        return filter(value, format)
      else
        return fetch(data[key], keys, default, format)  
      end
    end
    return filter(default, format)
  end
  protected :fetch
  
  #---
  
  def modify(data, keys, value = nil) 
    if keys.is_a?(String) || keys.is_a?(Symbol)
      keys = [ keys ]
    end
        
    key      = keys.shift.to_sym
    has_key  = data.has_key?(key)
    existing = { 
      :key   => key, 
      :value => ( has_key ? data[key] : nil ) 
    }
    
    if keys.empty?      
      existing[:value] = data[key] if has_key
      
      if value.nil?
        data.delete(key) if has_key
      else
        data[key] = value
      end
    else      
      data[key] = {} unless has_key
      existing  = modify(data[key], keys, value)  
    end
    
    return existing
  end
  protected :modify
  
  #---
  
  def get(keys, default = nil, format = false)
    return fetch(@properties, array(keys).flatten, default, format)
  end

  #---
 
  def [](name, default = nil, format = false)
    get(name, default, format)
  end
  
  #---
  
  def get_array(keys, default = [])
    return get(keys, default, :array)
  end
  
  #---
  
  def get_hash(keys, default = {})
    return get(keys, default, :hash)
  end
  
  #---
  
  def init(keys, default = nil)
    return set(keys, get(keys, default))
  end

  #---
  
  def set(keys, value)
    modify(@properties, array(keys).flatten, value)
    return self
  end
  
  #---
  
  def []=(name, value)
    set(name, value)
  end
   
  #---
  
  def delete(keys, default = nil)
    existing = modify(@properties, array(keys).flatten, nil)
    return existing[:value] if existing[:value]
    return default
  end
  
  #---
  
  def clear
    @properties = {}
    return self
  end

  #-----------------------------------------------------------------------------
  # Import / Export
 
  def import_base(properties, options = {})
    config      = Config.new(options, { :force => @force }).set(:context, :hash)    
    import_type = config.get(:import_type, :override)
    
    properties  = properties.export if properties.is_a?(Coral::Config)
    
    case properties
    when Hash
      data = [ @properties, symbol_map(properties) ]
      data = data.reverse if import_type != :override
{'fraction_non_alphanumeric': 0.2040117994100295, 'fraction_numerical': 0.0, 'mean_word_length': 1.6290322580645162, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2725779', 'n_tokens_mistral': 2551, 'n_tokens_neox': 2547, 'n_words': 618}