class Hocon::Impl::ConfigConcatenation
Constants
- ConfigBugOrBrokenError
- ConfigNotResolvedError
- ConfigObject
-
Subtype of {@link ConfigValue} representing an object (AKA dictionary or map) value, as in JSON’s curly brace
{ "a" : 42 }
syntax.<p> An object may also be viewed as a {@link Config} by calling {@link ConfigObject#toConfig()}.
<p> {@code ConfigObject} implements {@code java.util.Map<String, ConfigValue>} so you can use it like a regular Java map. Or call {@link
unwrapped()
} to unwrap the map to a map with plain Java values rather than {@code ConfigValue}.<p> Like all {@link ConfigValue} subtypes, {@code ConfigObject} is immutable. This makes it threadsafe and you never have to create “defensive copies.” The mutator methods from {@link java.util.Map} all throw {@link java.lang.UnsupportedOperationException}.
<p> The {@link ConfigValue#valueType} method on an object returns {@link ConfigValueType#OBJECT}.
<p> In most cases you want to use the {@link Config} interface rather than this one. Call {@link toConfig()} to convert a {@code ConfigObject} to a {@code Config}.
<p> The API for a {@code ConfigObject} is in terms of keys, while the API for a {@link Config} is in terms of path expressions. Conceptually, {@code ConfigObject} is a tree of maps from keys to values, while a {@code Config} is a one-level map from paths to values.
<p> Use {@link ConfigUtil#joinPath} and {@link ConfigUtil#splitPath} to convert between path expressions and individual path elements (keys).
<p> A {@code ConfigObject} may contain null values, which will have {@link ConfigValue#valueType()} equal to {@link ConfigValueType#NULL}. If {@link
ConfigObject#get(Object)
} returns Java’s null then the key was not present in the parsed file (or wherever this value tree came from). If {@code get(“key”)} returns a {@link ConfigValue} with type {@code ConfigValueType#NULL} then the key was set to null explicitly in the config file.<p> Do not implement interface {@code ConfigObject}; it should only be implemented by the config library. Arbitrary implementations will not work because the library internals assume a specific concrete implementation. Also, this interface is likely to grow new methods over time, so third-party implementations will break.
- ConfigString
- ConfigWrongTypeError
- ResolveStatus
- SimpleConfigList
- SimpleConfigOrigin
- Unmergeable
Attributes
Public Class Methods
Source
# File lib/hocon/impl/config_concatenation.rb, line 156 def self.concatenate(pieces) consolidated = consolidate(pieces) if consolidated.empty? nil elsif consolidated.length == 1 consolidated[0] else merged_origin = SimpleConfigOrigin.merge_value_origins(consolidated) Hocon::Impl::ConfigConcatenation.new(merged_origin, consolidated) end end
Source
# File lib/hocon/impl/config_concatenation.rb, line 130 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
Source
# File lib/hocon/impl/config_concatenation.rb, line 282 def self.is_ignored_whitespace(value) return value.is_a?(ConfigString) && !value.was_quoted? end
Source
# File lib/hocon/impl/config_concatenation.rb, line 79 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 = Hocon::Impl::DefaultTransformer.transform(left, Hocon::ConfigValueType::LIST) elsif (left.is_a?(SimpleConfigList)) && (right.is_a?(ConfigObject)) right = Hocon::Impl::DefaultTransformer.transform(right, Hocon::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?(SimpleConfigList) || left.is_a?(ConfigObject)) && is_ignored_whitespace(right) joined = left # it should be impossible that left is whitespace and right is a list or object elsif (left.is_a?(Hocon::Impl::ConfigConcatenation)) || (right.is_a?(Hocon::Impl::ConfigConcatenation)) raise ConfigBugOrBrokenError, "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", nil) else joined_origin = SimpleConfigOrigin.merge_origins([left.origin, right.origin]) joined = Hocon::Impl::ConfigString::Quoted.new(joined_origin, s1 + s2) end end if joined.nil? builder.push(right) else builder.pop builder.push(joined) end end
Add left and right, or their merger, to builder
Source
# File lib/hocon/impl/config_concatenation.rb, line 30 def initialize(origin, pieces) super(origin) @pieces = pieces if pieces.size < 2 raise ConfigBugOrBrokenError, "Created concatenation with less than 2 items: #{self}" end had_unmergeable = false pieces.each do |p| if p.is_a?(Hocon::Impl::ConfigConcatenation) raise ConfigBugOrBrokenError, "ConfigConcatenation should never be nested: #{self}" end if p.is_a?(Unmergeable) had_unmergeable = true end end unless had_unmergeable raise ConfigBugOrBrokenError, "Created concatenation without an unmergeable in it: #{self}" end end
Hocon::Impl::AbstractConfigValue::new
Public Instance Methods
Source
# File lib/hocon/impl/config_concatenation.rb, line 257 def ==(other) if other.is_a? Hocon::Impl::ConfigConcatenation can_equal(other) && @pieces == other.pieces else false end end
Source
# File lib/hocon/impl/config_concatenation.rb, line 253 def can_equal(other) other.is_a? Hocon::Impl::ConfigConcatenation end
Source
# File lib/hocon/impl/config_concatenation.rb, line 236 def has_descendant?(descendant) has_descendant_in_list?(@pieces, descendant) end
Source
# File lib/hocon/impl/config_concatenation.rb, line 265 def hash # note that "origin" is deliberately NOT part of equality @pieces.hash end
Source
# File lib/hocon/impl/config_concatenation.rb, line 65 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
Source
# File lib/hocon/impl/config_concatenation.rb, line 61 def new_copy(new_origin) self.class.new(new_origin, @pieces) end
Source
# File lib/hocon/impl/config_concatenation.rb, line 245 def relativized(prefix) new_pieces = [] @pieces.each { |p| new_pieces << p.relativized(prefix) } self.class.new(origin, new_pieces) end
when you graft a substitution into another object, you have to prefix it with the location in that object where you grafted it; but save prefixLength so system property and env variable lookups don ‘t get broken.
Source
# File lib/hocon/impl/config_concatenation.rb, line 270 def render_value_to_sb(sb, indent, at_root, options) @pieces.each do |piece| piece.render_value_to_sb(sb, indent, at_root, options) end end
Source
# File lib/hocon/impl/config_concatenation.rb, line 227 def replace_child(child, replacement) new_pieces = replace_child_in_list(@pieces, child, replacement) if new_pieces == nil nil else self.class.new(origin, new_pieces) end end
Source
# File lib/hocon/impl/config_concatenation.rb, line 223 def resolve_status ResolveStatus::UNRESOLVED end
Source
# File lib/hocon/impl/config_concatenation.rb, line 168 def resolve_substitutions(context, source) if Hocon::Impl::ConfigImpl.trace_substitution_enabled indent = context.depth + 2 Hocon::Impl::ConfigImpl.trace("concatenation has #{@pieces.size} pieces", indent - 1) count = 0 @pieces.each { |v| Hocon::Impl::ConfigImpl.trace("#{count}: #{v}", count) count += 1 } end # Right now there's no reason to pushParent here because the # content of ConfigConcatenation should not need to replaceChild, # but if it did we'd have to do this. source_with_parent = source new_context = context resolved = [] @pieces.each { |p| # to concat into a string we have to do a full resolve, # so unrestrict the context, then put restriction back afterward restriction = new_context.restrict_to_child result = new_context.unrestricted .resolve(p, source_with_parent) r = result.value new_context = result.context.restrict(restriction) if Hocon::Impl::ConfigImpl.trace_substitution_enabled Hocon::Impl::ConfigImpl.trace("resolved concat piece to #{r}", context.depth) end if r resolved << r end # otherwise, it was optional ... omit } # now need to concat everything joined = self.class.consolidate(resolved) # if unresolved is allowed we can just become another # ConfigConcatenation if joined.size > 1 and context.options.allow_unresolved Hocon::Impl::ResolveResult.make(new_context, Hocon::Impl::ConfigConcatenation.new(origin, joined)) elsif joined.empty? # we had just a list of optional references using ${?} Hocon::Impl::ResolveResult.make(new_context, nil) elsif joined.size == 1 Hocon::Impl::ResolveResult.make(new_context, joined[0]) else raise ConfigBugOrBrokenError.new( "Bug in the library; resolved list was joined to too many values: #{joined}") end end
Source
# File lib/hocon/impl/config_concatenation.rb, line 72 def unmerged_values [self] end
Source
# File lib/hocon/impl/config_concatenation.rb, line 57 def unwrapped raise not_resolved end
Source
# File lib/hocon/impl/config_concatenation.rb, line 53 def value_type raise not_resolved end
Private Instance Methods
Source
# File lib/hocon/impl/config_concatenation.rb, line 278 def not_resolved ConfigNotResolvedError.new("need to Config#resolve(), see the API docs for Config#resolve(); substitution not resolved: #{self}") end