Class: Hocon::Impl::ConfigConcatenation

Inherits:
AbstractConfigValue show all
Includes:
Unmergeable
Defined in:
lib/hocon/impl/config_concatenation.rb

Constant Summary collapse

SimpleConfigList =
Hocon::Impl::SimpleConfigList
ConfigObject =
Hocon::ConfigObject
Unmergeable =
Hocon::Impl::Unmergeable
SimpleConfigOrigin =
Hocon::Impl::SimpleConfigOrigin

Constants inherited from AbstractConfigValue

AbstractConfigValue::ConfigImplUtil

Instance Attribute Summary

Attributes inherited from AbstractConfigValue

#origin

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AbstractConfigValue

#at_key, #at_path, #indent, #render, #render_to_sb, #render_value_to_sb, #require_not_ignoring_fallbacks, #resolve_status, #to_s, #with_fallback, #with_origin

Constructor Details

#initialize(origin, pieces) ⇒ ConfigConcatenation

Returns a new instance of ConfigConcatenation.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/hocon/impl/config_concatenation.rb', line 107

def initialize(origin, pieces)
  super(origin)
  @pieces = pieces

  if pieces.size < 2
    raise ConfigBugError, "Created concatenation with less than 2 items: #{self}"
  end

  had_unmergeable = false
  pieces.each do |p|
    if p.is_a?(Hocon::Impl::ConfigConcatenation)
      raise ConfigBugError, "ConfigConcatenation should never be nested: #{self}"
    end
    if p.is_a?(Unmergeable)
      had_unmergeable = true
    end
  end

  unless had_unmergeable
    raise ConfigBugError, "Created concatenation without an unmergeable in it: #{self}"
  end
end

Class Method Details

.concatenate(pieces) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/hocon/impl/config_concatenation.rb', line 94

def self.concatenate(pieces)
  consolidated = consolidate(pieces)
  if consolidated.empty?
    nil
  elsif consolidated.length == 1
    consolidated[0]
  else
    merged_origin = SimpleConfigOrigin.merge_origins(consolidated)
    Hocon::Impl::ConfigConcatenation.new(merged_origin, consolidated)
  end
end

.consolidate(pieces) ⇒ Object



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
# File 'lib/hocon/impl/config_concatenation.rb', line 68

def self.consolidate(pieces)
  if pieces.length < 2
    pieces
  else
    flattened = []
    pieces.each do |v|
      if v.is_a?(Hocon::Impl::ConfigConcatenation)
        flattened.concat(v.pieces)
      else
        flattened.push(v)
      end
    end

    consolidated = []
    flattened.each do |v|
      if consolidated.empty?
        consolidated.push(v)
      else
        join(consolidated, v)
      end
    end

    consolidated
  end
end

.join(builder, orig_right) ⇒ Object

Add left and right, or their merger, to builder



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
# File 'lib/hocon/impl/config_concatenation.rb', line 21

def self.join(builder, orig_right)
  left = builder[builder.size - 1]
  right = orig_right

  # check for an object which can be converted to a list
  # (this will be an object with numeric keys, like foo.0, foo.1)
  if (left.is_a?(ConfigObject)) && (right.is_a?(SimpleConfigList))
    left = DefaultTransformer.transform(left, ConfigValueType::LIST)
  elsif (left.is_a?(SimpleConfigList)) && (right.is_a?(ConfigObject))
    right = DefaultTransformer.transform(right, ConfigValueType::LIST)
  end

  # Since this depends on the type of two instances, I couldn't think
  # of much alternative to an instanceof chain. Visitors are sometimes
  # used for multiple dispatch but seems like overkill.
  joined = nil
  if (left.is_a?(ConfigObject)) && (right.is_a?(ConfigObject))
    joined = right.with_fallback(left)
  elsif (left.is_a?(SimpleConfigList)) && (right.is_a?(SimpleConfigList))
    joined = left.concatenate(right)
  elsif (left.is_a?(Hocon::Impl::ConfigConcatenation)) ||
      (right.is_a?(Hocon::Impl::ConfigConcatenation))
    raise ConfigBugError, "unflattened ConfigConcatenation"
  elsif (left.is_a?(Unmergeable)) || (right.is_a?(Unmergeable))
    # leave joined=null, cannot join
  else
    # handle primitive type or primitive type mixed with object or list
    s1 = left.transform_to_string
    s2 = right.transform_to_string
    if s1.nil? || s2.nil?
      raise ConfigWrongTypeError.new(left.origin,
              "Cannot concatenate object or list with a non-object-or-list, #{left} " +
                  "and #{right} are not compatible")
    else
      joined_origin = SimpleConfigOrigin.merge_origins([left.origin, right.origin])
      joined = Hocon::Impl::ConfigString.new(joined_origin, s1 + s2)
    end
  end

  if joined.nil?
    builder.push(right)
  else
    builder.pop
    builder.push(joined)
  end
end

Instance Method Details

#ignores_fallbacks?Boolean

Returns:

  • (Boolean)


130
131
132
133
134
135
# File 'lib/hocon/impl/config_concatenation.rb', line 130

def ignores_fallbacks?
  # we can never ignore fallbacks because if a child ConfigReference
  # is self-referential we have to look lower in the merge stack
  # for its value.
  false
end