title: Typesafe Config: best pattern for overriding substitutions in later settings?
body: <p>Ok, I have tried the following and it's not producing the effect that I'd have wished for.  I have a <code>reference.conf</code> specifying filesystem locations relative to a prefix, which looks somewhat like this:</p>
  
  <pre><code>// reference.conf
  myapp {
      // The dummy path makes the error message easy to diagnose
      s3.prefix = "s3://environment/variable/S3_PREFIX/missing"
      s3.prefix = ${?S3_PREFIX}
  
      file1 = ${myapp.s3.prefix}"/file1.csv"
      file2 = ${myapp.s3.prefix}"/file2.csv"
      // ...
  }
  </code></pre>
  
  <p>And then I supply an <code>application.conf</code> file that looks more or less like this:</p>
  
  <pre><code>// application.conf
  myapp.s3.prefix = "s3://some-bucket/some/path/to/the/files"
  myapp.file2 = "s3://some-other-bucket/some/path/file2.csv"
  </code></pre>
  
  <p>Now, when my application does a <code>ConfigFactory.load()</code>, from :</p>
  
  <ol>
  <li>Parse the <code>reference.conf</code> file, perform the substitutions, and generate a <code>Config</code> object where:
  <ul>
  <li><code>myapp.s3.prefix = "/environment/variable/S3_PREFIX/missing"</code></li>
  <li><code>myapp.file1 = "/environment/variable/S3_PREFIX/missing/file1.csv"</code></li>
  <li><code>myapp.file2 = "/environment/variable/S3_PREFIX/missing/file2.csv"</code>.</li>
  </ul></li>
  <li>Parse the <code>application.conf</code> file and generate a <code>Config</code> object where:
  <ul>
  <li><code>library.prefix = "/some/path/to/the/files"</code></li>
  <li><code>myapp.file2 = "s3://some-other-bucket/some/path/file2.csv"</code>.</li>
  </ul></li>
  <li>Merge the two objects, with the <code>reference.conf</code> object as fallback.  The resulting <code>Config</code> object therefore has:
  <ul>
  <li><code>library.prefix = "s3://some-bucket/some/path/to/the/files"</code> (as in <code>application.conf</code>)</li>
  <li><code>library.file1 = "s3://environment/variable/S3_PREFIX/missing/file1.csv"</code> (as in <code>reference.conf</code>).</li>
  <li><code>library.file2 = "s3://some-other-bucket/some/path/file2.csv"</code> (as in <code>application.conf</code>).</li>
  </ul></li>
  </ol>
  
  <p>But as you may have guessed from my example, what I'm trying to do is have the <code>reference.conf</code> specify default paths <em>relative</em> to a root directory, and allow any mix of <strong>both</strong> of these:</p>
  
  <ol>
  <li>Override the default root directory from the <code>application.conf</code>, so that the default relative paths from the <code>reference.conf</code> are looked up from there.</li>
  <li>Override the path for any individual file in the <code>application.conf</code>, so the application can use a path not in the root directory.</li>
  </ol>
  
  <p>The only thing I've been able to come up with so far is this:</p>
  
  <pre><code>// reference.conf
  myapp {
      // The dummy path makes the error message easy to diagnose
      s3.prefix = "s3:/environment/variable/S3_PREFIX/missing"
      s3.prefix = ${?S3_PREFIX}
  
      file1 = "file1.csv"
      file2 = "file2.csv"
      // ...
  }
  
  // application.conf
  myapp.s3.prefix = "s3://some-bucket/some/path/to/the/files"
  myapp.file2 = "s3://some-other-bucket/some/path/file2.csv"
  
  
  // The Java code for using the config must append prefix and file location,
  // and needs to have smarts about relative vs. absolute paths.
  
  final Config CONF = ConfigFactory.load();
  
  String getS3URLFor(String file) {
      String root = CONF.getString("myapp.s3.prefix");
      String path = CONF.getString("myapp." + file);
      return relativeVsAbsoluteSensitiveMerge(root, path);
  }
  
  String relativeVsAbsoluteSensitiveMerge(String root, String path) {
      if (isAbsoluteReference(path)) {
          return path; 
      } else {
          return root + "/" + path;
      }
  }
  
  boolean isAbsoluteReference(String path) {
     // ...
  }
  </code></pre>
  
  <p>I don't really like this solution.  Can anybody think of something better?</p>