class SimpleConfigObject

Constants

ConfigBugOrBrokenError
Path
ResolveResult

value is allowed to be null

ResolveStatus
SimpleConfigOrigin

Attributes

value[R]

Public Class Methods

empty(origin = nil) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 567
def self.empty(origin = nil)
  if origin.nil?
    empty(Hocon::Impl::SimpleConfigOrigin.new_simple("empty config"))
  else
    self.new(origin, {})
  end
end
empty_missing(base_origin) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 575
def self.empty_missing(base_origin)
  self.new(
      Hocon::Impl::SimpleConfigOrigin.new_simple("#{base_origin.description} (not found)"),
      {})
end
map_equals(a, b) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 498
def self.map_equals(a, b)
  if a.equal?(b)
    return true
  end

  # Hashes aren't ordered in ruby, so sort first
  if not a.keys.sort == b.keys.sort
    return false
  end

  a.keys.each do |key|
    if a[key] != b[key]
      return false
    end
  end

  true
end
map_hash(m) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 521
def self.map_hash(m)
  # the keys have to be sorted, otherwise we could be equal
  # to another map but have a different hashcode.
  keys = m.keys.sort

  value_hash = 0

  keys.each do |key|
    value_hash += m[key].hash
  end

  41 * (41 + keys.hash) + value_hash
end
new(origin, value, status = Hocon::Impl::ResolveStatus.from_values(value.values), ignores_fallbacks = false) click to toggle source
Calls superclass method Hocon::Impl::AbstractConfigObject::new
# File lib/hocon/impl/simple_config_object.rb, line 25
def initialize(origin,
               value,
               status = Hocon::Impl::ResolveStatus.from_values(value.values),
               ignores_fallbacks = false)
  super(origin)
  if value.nil?
    raise ConfigBugOrBrokenError, "creating config object with null map"
  end
  @value = value
  @resolved = (status == Hocon::Impl::ResolveStatus::RESOLVED)
  @ignores_fallbacks = ignores_fallbacks

  # Kind of an expensive debug check. Comment out?
  if status != Hocon::Impl::ResolveStatus.from_values(value.values)
    raise ConfigBugOrBrokenError, "Wrong resolved status on #{self}"
  end
end

Public Instance Methods

==(other) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 539
def ==(other)
  # note that "origin" is deliberately NOT part of equality.
  # neither are other "extras" like ignoresFallbacks or resolve status.
  if other.is_a? Hocon::ConfigObject
    # optimization to avoid unwrapped() for two ConfigObject,
    # which is what AbstractConfigValue does.
    can_equal(other) && self.class.map_equals(self, other)
  else
    false
  end
end
attempt_peek_with_partial_resolve(key) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 152
def attempt_peek_with_partial_resolve(key)
  @value[key]
end
can_equal(other) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 535
def can_equal(other)
  other.is_a? Hocon::ConfigObject
end
contains_key?(key) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 555
def contains_key?(key)
  @value.has_key?(key)
end
contains_value?(v) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 563
def contains_value?(v)
  @value.has_value?(v)
end
get(key) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 517
def get(key)
  @value[key]
end
has_descendant?(descendant) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 189
def has_descendant?(descendant)
  value.values.each do |child|
    if child.equal?(descendant)
      return true
    end
  end
  # now do the expensive search
  value.values.each do |child|
    if child.is_a?(Hocon::Impl::Container) && child.has_descendant?(descendant)
      return true
    end
  end

  false
end
hash() click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 551
def hash
  self.class.map_hash(@value)
end
ignores_fallbacks?() click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 205
def ignores_fallbacks?
  @ignores_fallbacks
end
key_set() click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 559
def key_set
  Set.new(@value.keys)
end
merged_with_object(abstract_fallback) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 217
def merged_with_object(abstract_fallback)
  require_not_ignoring_fallbacks

  unless abstract_fallback.is_a?(Hocon::Impl::SimpleConfigObject)
    raise ConfigBugOrBrokenError, "should not be reached (merging non-SimpleConfigObject)"
  end

  fallback = abstract_fallback
  changed = false
  all_resolved = true
  merged = {}
  all_keys = key_set.union(fallback.key_set)
  all_keys.each do |key|
    first = @value[key]
    second = fallback.value[key]
    kept =
        if first.nil?
          second
        elsif second.nil?
          first
        else
          first.with_fallback(second)
        end
    merged[key] = kept

    if first != kept
      changed = true
    end

    if kept.resolve_status == Hocon::Impl::ResolveStatus::UNRESOLVED
      all_resolved = false
    end
  end

  new_resolve_status = Hocon::Impl::ResolveStatus.from_boolean(all_resolved)
  new_ignores_fallbacks = fallback.ignores_fallbacks?

  if changed
    Hocon::Impl::SimpleConfigObject.new(Hocon::Impl::AbstractConfigObject.merge_origins([self, fallback]),
                                        merged, new_resolve_status,
                                        new_ignores_fallbacks)
  elsif (new_resolve_status != resolve_status) || (new_ignores_fallbacks != ignores_fallbacks?)
    new_copy_with_status(new_resolve_status, origin, new_ignores_fallbacks)
  else
    self
  end
end
modify(modifier) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 265
def modify(modifier)
  begin
    modify_may_throw(modifier)
  rescue Hocon::ConfigError => e
    raise e
  end
end
modify_may_throw(modifier) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 273
def modify_may_throw(modifier)
  changes = nil
  keys.each do |k|
    v = value[k]
    # "modified" may be null, which means remove the child;
    # to do that we put null in the "changes" map.
    modified = modifier.modify_child_may_throw(k, v)
    if ! modified.equal?(v)
      if changes.nil?
        changes = {}
      end
      changes[k] = modified
    end
  end
  if changes.nil?
    self
  else
    modified = {}
    saw_unresolved = false
    keys.each do |k|
      if changes.has_key?(k)
        new_value = changes[k]
        if ! new_value.nil?
          modified[k] = new_value
          if new_value.resolve_status == ResolveStatus::UNRESOLVED
            saw_unresolved = true
          end
        else
          # remove this child; don't put it in the new map
        end
      else
        new_value = value[k]
        modified[k] = new_value
        if new_value.resolve_status == ResolveStatus::UNRESOLVED
          saw_unresolved = true
        end
      end
    end
    self.class.new(origin, modified,
                   saw_unresolved ? ResolveStatus::UNRESOLVED : ResolveStatus::RESOLVED,
                   @ignores_fallbacks)
  end
end
new_copy_with_status(new_status, new_origin, new_ignores_fallbacks = nil) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 156
def new_copy_with_status(new_status, new_origin, new_ignores_fallbacks = nil)
  self.class.new(new_origin, @value, new_status, new_ignores_fallbacks)
end
relativized(prefix) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 374
def relativized(prefix)

  modifier = Class.new do
    include Hocon::Impl::AbstractConfigValue::NoExceptionsModifier

    # prefix isn't in scope inside of a def, but it is in scope inside of Class.new
    # so manually define a method that has access to prefix
    # I feel dirty
    define_method(:modify_child) do |key, v|
      v.relativized(prefix)
    end
  end

  modify(modifier.new)
end
render_value_to_sb(sb, indent, at_root, options) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 416
def render_value_to_sb(sb, indent, at_root, options)
  if empty?
    sb << "{}"
  else
    outer_braces = options.json? || !at_root

    if outer_braces
      inner_indent = indent + 1
      sb << "{"

      if options.formatted?
        sb << "\n"
      end
    else
      inner_indent = indent
    end

    separator_count = 0
    sorted_keys = RenderComparator.sort(keys)
    sorted_keys.each do |k|
      v = @value[k]

      if options.origin_comments?
        lines = v.origin.description.split("\n")
        lines.each { |l|
          Hocon::Impl::AbstractConfigValue.indent(sb, indent + 1, options)
          sb << '#'
          unless l.empty?
            sb << ' '
          end
          sb << l
          sb << "\n"
        }
      end
      if options.comments?
        v.origin.comments.each do |comment|
          Hocon::Impl::AbstractConfigValue.indent(sb, inner_indent, options)
          sb << "#"
          if !comment.start_with?(" ")
            sb << " "
          end
          sb << comment
          sb << "\n"
        end
      end
      Hocon::Impl::AbstractConfigValue.indent(sb, inner_indent, options)
      v.render_to_sb(sb, inner_indent, false, k.to_s, options)

      if options.formatted?
        if options.json?
          sb << ","
          separator_count = 2
        else
          separator_count = 1
        end
        sb << "\n"
      else
        sb << ","
        separator_count = 1
      end
    end
    # chop last commas/newlines
    # couldn't figure out a better way to chop characters off of the end of
    # the StringIO.  This relies on making sure that, prior to returning the
    # final string, we take a substring that ends at sb.pos.
    sb.pos = sb.pos - separator_count

    if outer_braces
      if options.formatted?
        sb << "\n" # put a newline back
        if outer_braces
          Hocon::Impl::AbstractConfigValue.indent(sb, indent, options)
        end
      end
      sb << "}"
    end
  end
  if at_root && options.formatted?
    sb << "\n"
  end
end
replace_child(child, replacement) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 172
def replace_child(child, replacement)
  new_children = @value.clone
  new_children.each do |old, old_value|
    if old_value.equal?(child)
      if replacement != nil
        new_children[old] = replacement
      else
        new_children.delete(old)
      end

      return self.class.new(origin, new_children, ResolveStatus.from_values(new_children.values),
                     @ignores_fallbacks)
    end
  end
  raise ConfigBugOrBrokenError, "SimpleConfigObject.replaceChild did not find #{child} in #{self}"
end
resolve_status() click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 168
def resolve_status
  ResolveStatus.from_boolean(@resolved)
end
resolve_substitutions(context, source) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 354
def resolve_substitutions(context, source)
  if resolve_status == ResolveStatus::RESOLVED
    return ResolveResult.make(context, self)
  end

  source_with_parent = source.push_parent(self)

  begin
    modifier = ResolveModifier.new(context, source_with_parent)

    value = modify_may_throw(modifier)
    ResolveResult.make(modifier.context, value)

  rescue NotPossibleToResolve => e
    raise e
  rescue Hocon::ConfigError => e
    raise e
  end
end
unwrapped() click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 209
def unwrapped
  m = {}
  @value.each do |k,v|
    m[k] = v.unwrapped
  end
  m
end
with_fallbacks_ignored() click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 160
def with_fallbacks_ignored()
  if @ignores_fallbacks
    self
  else
    new_copy_with_status(resolve_status, origin, true)
  end
end
with_key_value(key, v) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 137
def with_key_value(key, v)
  if v.nil?
    raise ConfigBugOrBrokenError.new("Trying to store null ConfigValue in a ConfigObject")
  end

  new_map = Hash.new
  if @value.empty?
    new_map[key] = v
  else
    new_map = @value.clone
    new_map[key] = v
  end
  self.class.new(origin, new_map, ResolveStatus.from_values(new_map.values), @ignores_fallbacks)
end
with_only_key(key) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 48
def with_only_key(key)
  with_only_path(Path.new_key(key))
end
with_only_path(path) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 83
def with_only_path(path)
  o = with_only_path_or_nil(path)
  if o.nil?
    self.class.new(origin, {}, ResolveStatus::RESOLVED, @ignores_fallbacks)
  else
    o
  end
end
with_only_path_or_nil(path) click to toggle source

gets the object with only the path if the path exists, otherwise null if it doesn't. this ensures that if we have { a : { b : 42 } } and do withOnlyPath(ā€œa.b.cā€) that we don't keep an empty ā€œaā€ object.

# File lib/hocon/impl/simple_config_object.rb, line 61
def with_only_path_or_nil(path)
  key = path.first
  path_next = path.remainder
  v = value[key]

  if ! path_next.nil?
    if (!v.nil?) && (v.is_a?(Hocon::Impl::AbstractConfigObject))
      v = v.with_only_path_or_nil(path_next)
    else
      # if the path has more elements but we don't have an object,
      # then the rest of the path does not exist.
      v = nil
    end
  end

  if v.nil?
    nil
  else
    self.class.new(origin, {key => v}, v.resolve_status, @ignores_fallbacks)
  end
end
with_value(path, v) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 119
def with_value(path, v)
  key = path.first
  remainder = path.remainder

  if remainder.nil?
    with_key_value(key, v)
  else
    child = @value[key]
    if (not child.nil?) && child.is_a?(Hocon::Impl::AbstractConfigObject)
      return with_key_value(key, child.with_value(remainder, v))
    else
      subtree = v.at_path_with_origin(
          SimpleConfigOrigin.new_simple("with_value(#{remainder.render})"), remainder)
      with_key_value(key, subtree.root)
    end
  end
end
without_key(key) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 52
def without_key(key)
  without_path(Path.new_key(key))
end
without_path(path) click to toggle source
# File lib/hocon/impl/simple_config_object.rb, line 92
def without_path(path)
  key = path.first
  remainder = path.remainder
  v = @value[key]

  if (not v.nil?) && (not remainder.nil?) && v.is_a?(Hocon::Impl::AbstractConfigObject)
    v = v.without_path(remainder)
    updated = @value.clone
    updated[key] = v
    self.class.new(origin,
                   updated,
                   ResolveStatus.from_values(updated.values), @ignores_fallbacks)
  elsif (not remainder.nil?) || v.nil?
    return self
  else
    smaller = Hash.new
    @value.each do |old_key, old_value|
      unless old_key == key
        smaller[old_key] = old_value
      end
    end
    self.class.new(origin,
                   smaller,
                   ResolveStatus.from_values(smaller.values), @ignores_fallbacks)
  end
end