Class: Hocon::Impl::ResolveSource

Inherits:
Object
  • Object
show all
Defined in:
lib/hocon/impl/resolve_source.rb

Defined Under Namespace

Classes: Node, ResultWithPath, ValueWithPath

Constant Summary collapse

ConfigBugOrBrokenError =
Hocon::ConfigError::ConfigBugOrBrokenError
ConfigNotResolvedError =
Hocon::ConfigError::ConfigNotResolvedError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root, path_from_root = nil) ⇒ ResolveSource

Returns a new instance of ResolveSource.



20
21
22
23
# File 'lib/hocon/impl/resolve_source.rb', line 20

def initialize(root, path_from_root = nil)
  @root = root
  @path_from_root = path_from_root
end

Instance Attribute Details

#path_from_rootObject

‘path_from_root’ is used for knowing the chain of parents we used to get here. null if we should assume we are not a descendant of the root. the root itself should be a node in this if non-null.



18
19
20
# File 'lib/hocon/impl/resolve_source.rb', line 18

def path_from_root
  @path_from_root
end

#rootObject

‘path_from_root’ is used for knowing the chain of parents we used to get here. null if we should assume we are not a descendant of the root. the root itself should be a node in this if non-null.



18
19
20
# File 'lib/hocon/impl/resolve_source.rb', line 18

def root
  @root
end

Instance Method Details

#find_in_object(obj, context, path) ⇒ Object

as a side effect, findInObject() will have to resolve all parents of the child being peeked, but NOT the child itself.Caller has to resolve the child itself if needed.ValueWithPath.value can be null but the ValueWithPath instance itself should not be.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/hocon/impl/resolve_source.rb', line 29

def find_in_object(obj, context, path)
  # resolve ONLY portions of the object which are along our path
  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace("*** finding '#{path}' in #{obj}")
  end
  restriction = context.restrict_to_child
  partially_resolved = context.restrict(path).resolve(obj, self.class.new(obj))
  new_context = partially_resolved.context.restrict(restriction)
  if partially_resolved.value.is_a?(Hocon::Impl::AbstractConfigObject)
    pair = self.class.find_in_object_impl(partially_resolved.value, path)
    ResultWithPath.new(Hocon::Impl::ResolveResult.make(new_context, pair.value), pair.path_from_root)
  else
    raise ConfigBugOrBrokenError.new("resolved object to non-object " + obj + " to " + partially_resolved)
  end
end

#lookup_subst(context, subst, prefix_length) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/hocon/impl/resolve_source.rb', line 45

def lookup_subst(context, subst, prefix_length)
  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace("searching for #{subst}", context.depth)
  end

  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace("#{subst} - looking up relative to file it occurred in",
                                  context.depth)
  end
  # First we look up the full path, which means relative to the
  # included file if we were not a root file
  result = find_in_object(@root, context, subst.path)

  if result.result.value == nil
    # Then we want to check relative to the root file.We don 't
    # want the prefix we were included at to be used when looking
    # up env variables either.
    unprefixed = subst.path.sub_path_to_end(prefix_length)

    if prefix_length > 0
      if Hocon::Impl::ConfigImpl.trace_substitution_enabled
        Hocon::Impl::ConfigImpl.trace(
            unprefixed + " - looking up relative to parent file",
            result.result.context.depth)
      end
      result = find_in_object(@root, result.result.context, unprefixed)
    end

    if result.result.value == nil && result.result.context.options.use_system_environment
      if Hocon::Impl::ConfigImpl.trace_substitution_enabled
        Hocon::Impl::ConfigImpl.trace(
            "#{unprefixed} - looking up in system environment",
            result.result.context.depth)
      end
      result = find_in_object(Hocon::Impl::ConfigImpl.env_variables_as_config_object, context, unprefixed)
    end
  end

  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace(
        "resolved to #{result}",
        result.result.context.depth)
  end

  result
end

#push_parent(parent) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/hocon/impl/resolve_source.rb', line 92

def push_parent(parent)
  unless parent
    raise ConfigBugOrBrokenError.new("can't push null parent")
  end

  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace("pushing parent #{parent} ==root #{(parent == root)} onto #{self}")
  end

  if @path_from_root == nil
    if parent.equal?(@root)
      return self.class.new(@root, Node.new(parent))
    else
      if Hocon::Impl::ConfigImpl.trace_substitution_enabled
        # this hasDescendant check is super-expensive so it's a
        # trace message rather than an assertion
        if @root.has_descendant?(parent)
          Hocon::Impl::ConfigImpl.trace(
              "***** BUG ***** tried to push parent #{parent} without having a path to it in #{self}")
        end
      end
      # ignore parents if we aren't proceeding from the
      # root
      return self
    end
  else
    parent_parent = @path_from_root.head
    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
      # this hasDescendant check is super-expensive so it's a
      # trace message rather than an assertion
      if parent_parent != nil && !parent_parent.has_descendant?(parent)
        Hocon::Impl::ConfigImpl.trace(
            "***** BUG ***** trying to push non-child of #{parent_parent}, non-child was #{parent}")
      end
    end

    self.class.new(@root, @path_from_root.prepend(parent))
  end
end

#replace_current_parent(old, replacement) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/hocon/impl/resolve_source.rb', line 140

def replace_current_parent(old, replacement)
  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace("replaceCurrentParent old #{old}@#{old.hash} replacement " +
                                      "#{replacement}@#{old.hash} in #{self}")
  end
  if old.equal?(replacement)
    self
  elsif @path_from_root != nil
    new_path = self.class.replace(@path_from_root, old, replacement)
    if Hocon::Impl::ConfigImpl.trace_substitution_enabled
      Hocon::Impl::ConfigImpl.trace("replaced #{old} with #{replacement} in #{self}")
      Hocon::Impl::ConfigImpl.trace("path was: #{@path_from_root} is now #{new_path}")
    end
    # if we end up nuking the root object itself, we replace it with an
    # empty root
    if new_path != nil
      return self.class.new(new_path.last, new_path)
    else
      return self.class.new(Hocon::Impl::SimpleConfigObject.empty)
    end
  else
    if old.equal?(@root)
      return self.class.new(root_must_be_obj(replacement))
    else
      raise ConfigBugOrBrokenError.new("attempt to replace root #{root} with #{replacement}")
    end
  end
end

#replace_within_current_parent(old, replacement) ⇒ Object

replacement may be null to delete



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/hocon/impl/resolve_source.rb', line 170

def replace_within_current_parent(old, replacement)
  if Hocon::Impl::ConfigImpl.trace_substitution_enabled
    Hocon::Impl::ConfigImpl.trace("replaceWithinCurrentParent old #{old}@#{old.hash}" +
                                      " replacement #{replacement}@#{old.hash} in #{self}")
  end
  if old.equal?(replacement)
    self
  elsif @path_from_root != nil
    parent = @path_from_root.head
    new_parent = parent.replace_child(old, replacement)
    return replace_current_parent(parent, new_parent.is_a?(Hocon::Impl::Container) ? new_parent : nil)
  else
    if old.equal?(@root) && replacement.is_a?(Hocon::Impl::Container)
      return self.class.new(root_must_be_obj(replacement))
    else
      raise ConfigBugOrBrokenError.new("replace in parent not possible #{old} with #{replacement}" +
                                           " in #{self}")
    end
  end
end

#reset_parentsObject



132
133
134
135
136
137
138
# File 'lib/hocon/impl/resolve_source.rb', line 132

def reset_parents
  if @path_from_root == nil
    this
  else
    self.class.new(@root)
  end
end

#to_sObject



191
192
193
# File 'lib/hocon/impl/resolve_source.rb', line 191

def to_s
  "ResolveSource(root=#{@root}, pathFromRoot=#{@path_from_root})"
end