All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.specmatic.core.pattern.HasValue.kt Maven / Gradle / Ivy

Go to download

Turn your contracts into executable specifications. Contract Driven Development - Collaboratively Design & Independently Deploy MicroServices & MicroFrontends.

There is a newer version: 2.0.37
Show newest version
package io.specmatic.core.pattern

data class HasValue(override val value: T, val valueDetails: List = emptyList()): ReturnValue {
    constructor(value: T, message: String): this(value, listOf(ValueDetails(listOf(message))))
    constructor(value: T, message: String, key: String): this(value, listOf(ValueDetails(listOf(message), listOf(key))))

    override fun hashCode(): Int {
        return value.hashCode()
    }

    override fun equals(other: Any?): Boolean {
        if(other !is HasValue<*>)
            return false

        val thisValue: T = this.value
        val otherValue: Any? = other.value

        return thisValue?.equals(otherValue) == true
    }

    override fun  withDefault(default: U, fn: (T) -> U): U {
        return fn(value)
    }

    override fun  ifValue(fn: (T) -> U): ReturnValue {
        return try {
            HasValue(fn(value), valueDetails)
        } catch(t: Throwable) {
            HasException(t)
        }
    }

    override fun update(fn: (T) -> T): ReturnValue {
        return try {
            val newValue = fn(value)
            HasValue(newValue, valueDetails)
        } catch(t: Throwable) {
            HasException(t)
        }
    }

    override fun  assimilate(valueResult: ReturnValue, fn: (T, U) -> T): ReturnValue {
        if(valueResult is ReturnFailure)
            return valueResult.cast()
        else if(valueResult is HasException)
            return valueResult.cast()

        valueResult as HasValue

        return try {
            val newValue = fn(value, valueResult.value)
            HasValue(newValue, valueDetails.plus(valueResult.valueDetails))
        } catch(t: Throwable) {
            HasException(t)
        }
    }

    fun comments(): String? {
        if(valueDetails.isEmpty())
            return null

        val blankLineSeparator = System.lineSeparator() + System.lineSeparator()

        val comments = """
            ${valueDetails.mapNotNull { it.comments() }.joinToString(blankLineSeparator)}
        """.trimIndent().trim()

        return comments
    }

    override fun  realise(hasValue: (T, String?) -> U, orFailure: (HasFailure) -> U, orException: (HasException) -> U): U {
        return hasValue(value, comments())
    }

    override fun  ifHasValue(fn: (HasValue) -> ReturnValue): ReturnValue {
        return fn(this)
    }

    override fun  combine(valueResult: ReturnValue, fn: (T, U) -> V): ReturnValue {
        if(valueResult is ReturnFailure)
            return valueResult.cast()

        valueResult as HasValue

        return try {
            val newValue = fn(value, valueResult.value)
            HasValue(newValue, valueDetails.plus(valueResult.valueDetails))
        } catch(t: Throwable) {
            HasException(t)
        }
    }

    override fun addDetails(message: String, breadCrumb: String): ReturnValue {
        if(message.isBlank() && breadCrumb.isBlank())
            return this

        return HasValue(
            value,
            valueDetails.map { it.addDetails(message, breadCrumb) })
    }
}