Created
December 21, 2017 17:37
-
-
Save mikehearn/518e44670811a8af735708d46d1e5721 to your computer and use it in GitHub Desktop.
Simple dependency helpers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package net.corda.node.internal | |
import java.time.Clock | |
import java.time.Duration | |
import java.time.Instant | |
import java.time.ZoneId | |
import kotlin.properties.ReadWriteProperty | |
import kotlin.reflect.KProperty | |
/** | |
* A dependency delegate can be used with the Kotlin `by` keyword. It is intended for global variables that are lazily | |
* initialised on access to the result of some lambda, but which can be changed after the fact. | |
*/ | |
class DependencyDelegate<T : Any>(private val newEachTime: Boolean = false, private val ctor: () -> T) : ReadWriteProperty<Nothing?, T> { | |
private var value: T? = null | |
override fun getValue(thisRef: Nothing?, property: KProperty<*>): T { | |
if (newEachTime) { | |
return ctor() | |
} | |
synchronized(this) { | |
if (value == null) | |
value = ctor() | |
return value!! | |
} | |
} | |
@Synchronized | |
override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: T) { | |
this.value = value | |
} | |
} | |
internal var defaultClock: Clock by DependencyDelegate { Clock.systemUTC() } | |
class SomethingThatNeedsAClock(val clock: Clock = defaultClock) { | |
override fun toString() = clock.instant().toString() | |
} | |
/** | |
* | |
*/ | |
class TestSensitiveDependency<T : Any>(private val regular: () -> T, | |
private val test: () -> T) : ReadWriteProperty<Nothing?, T> { | |
private val oldValue = ThreadLocal<T?>() | |
private val value = ThreadLocal<T?>() | |
companion object { | |
private val isJUnitPresent: Boolean by lazy { | |
try { Class.forName("org.junit.Test"); true } catch(e: ClassNotFoundException) { false } | |
} | |
} | |
private fun construct(): T = if (isJUnitPresent) | |
test() | |
else | |
regular() | |
override fun getValue(thisRef: Nothing?, property: KProperty<*>): T { | |
if (value.get() == null) { | |
value.set(construct()) | |
} | |
return value.get()!! | |
} | |
override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: T) { | |
oldValue.set(this.value.get()) | |
this.value.set(value) | |
} | |
fun restore() { | |
value.set(oldValue.get()) | |
oldValue.set(null) | |
} | |
} | |
internal var testableClockDependency = TestSensitiveDependency( | |
regular = { defaultClock }, | |
test = { Clock.fixed(Instant.ofEpochSecond(1513877662), ZoneId.of("UTC")) } | |
) | |
var testableClock: Clock by testableClockDependency | |
fun main(args: Array<String>) { | |
println("Time is ${testableClock.instant()}") | |
testableClock = Clock.offset(defaultClock, Duration.ofDays(5)) | |
println("Time is ${testableClock.instant()}") | |
testableClockDependency.restore() | |
println("Time is ${testableClock.instant()}") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment