Skip to content
This repository was archived by the owner on Jun 18, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions src/main/scala/eri/commons/config/SSConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@

package eri.commons.config

import com.typesafe.config.{Config ⇒ TConfig, ConfigException, ConfigFactory}

import com.typesafe.config.{ConfigException, ConfigFactory, Config ⇒ TConfig}
import scala.language.dynamics

/**
Expand All @@ -30,6 +29,10 @@ import scala.language.dynamics
* other {
* fred = "fun"
* }
* dashed-name = 23
* underscored_name = "happy"
* lowercased = false
* UPPERCASED = true
* }
* }}}
*
Expand All @@ -49,12 +52,22 @@ import scala.language.dynamics
* val n2 = Config2.other.fred.as[String]
* }}}
*
* If created with lenient set to true dashed (i.e. foo-bar), underscored (i.e. foo_bar), all uppercased (i.e. FOO) and all lowercased config keys can be looked up via camelCased (i.e. fooBar) identifiers:
* {{{
* object Config3 extends SSConfig(lenient = true)
* val i = Config3.farmer.fred.dashedName.as[Int]
* val s = Config3.farmer.fred.underscoredName.as[String]
* val b1 = Config3.farmer.fred.lowerCased.as[Boolean]
* val b2 = Config3.farmer.fred.upperCased.as[Boolean]
* }}}
*
* @param relPath Scoping path specifier
* @param relConfig Configuration data
* @param lenient Use lenient lookup (default is false)
* @author <a href="mailto:fitch@datamininglab.com">Simeon H.K. Fitch</a>
* @since 3/24/16
*/
class SSConfig(relPath: String = "", relConfig: TConfig = ConfigFactory.load()) extends Dynamic {
class SSConfig(relPath: String = "", relConfig: TConfig = ConfigFactory.load(), lenient: Boolean = false) extends Dynamic {
def this(config: TConfig) = this("", config)

/**
Expand Down Expand Up @@ -85,6 +98,27 @@ class SSConfig(relPath: String = "", relConfig: TConfig = ConfigFactory.load())
val next = if (relPath.nonEmpty && relConfig.hasPath(relPath))
relConfig.getConfig(relPath)
else relConfig
new SSConfig(name, next)
new SSConfig(aliases(name).find(next.hasPath).getOrElse(name), next)
}

private[this] def aliases(name: String): Seq[String] = {
if (!lenient) Seq(name, name.toLowerCase(), name.toUpperCase)
else {
val dashed = StringBuilder.newBuilder
val underscored = StringBuilder.newBuilder
var current: Char = 0
var i: Int = 0
while (i < name.length) {
current = name.charAt(i)
if (i > 0 && current.isUpper) {
dashed.append('-')
underscored.append('_')
}
dashed.append(current.toLower)
underscored.append(current.toLower)
i += 1
}
Seq(name, dashed.mkString, underscored.mkString, name.toLowerCase(), name.toUpperCase).distinct
}
}
}
6 changes: 6 additions & 0 deletions src/test/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,10 @@
akka.actor.creation-timeout = 3s
myapp.tempdir = /tmp/foo
my.phone = "1-881-555-1212"

// leniency
nameinlowercase = valueinlowercase
NAMEINUPPERCASE = VALUEINUPPERCASE
name_with_underscore = value_with_underscore
name-with-dash = value-with-dash
}
23 changes: 23 additions & 0 deletions src/test/scala/eri/commons/config/SSConfigTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,27 @@ class SSConfigTest extends FunSpec {
assert(phone.extension === 1212)
}
}
describe("leniency") {
val conf = new SSConfig(lenient = true)
it("should support lookups converted to all lower or upper case") {
assert(conf.nameinlowercase.as[String] === "valueinlowercase")
assert(conf.NAMEINLOWERCASE.as[String] === "valueinlowercase")
assert(conf.nameInLowerCase.as[String] === "valueinlowercase")
assert(conf.nameinuppercase.as[String] === "VALUEINUPPERCASE")
assert(conf.NAMEINUPPERCASE.as[String] === "VALUEINUPPERCASE")
assert(conf.nameInUpperCase.as[String] === "VALUEINUPPERCASE")
}
it("should support names with underscores") {
assert(conf.name_with_underscore.as[String] === "value_with_underscore")
}
it("should support names with underscores if written as camelCase") {
assert(conf.nameWithUnderscore.as[String] === "value_with_underscore")
}
it("should support names with dashes if written as symbol") {
assert(conf.`name-with-dash`.as[String] === "value-with-dash")
}
it("should support names with dashes if written as camelCase") {
assert(conf.nameWithDash.as[String] === "value-with-dash")
}
}
}