mirror of
https://github.com/corda/corda.git
synced 2025-06-23 09:25:36 +00:00
Refactored ErrorOr into Try, with Success and Failure data sub-classes, and moved it into core.utilities
This commit is contained in:
@ -23,7 +23,10 @@ import java.nio.file.*
|
||||
import java.nio.file.attribute.FileAttribute
|
||||
import java.time.Duration
|
||||
import java.time.temporal.Temporal
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import java.util.stream.Stream
|
||||
import java.util.zip.Deflater
|
||||
@ -324,63 +327,6 @@ data class InputStreamAndHash(val inputStream: InputStream, val sha256: SecureHa
|
||||
|
||||
val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
|
||||
|
||||
/** Representation of an operation that may have thrown an error. */
|
||||
@Suppress("DataClassPrivateConstructor")
|
||||
@CordaSerializable
|
||||
data class ErrorOr<out A> private constructor(val value: A?, val error: Throwable?) {
|
||||
// The ErrorOr holds a value iff error == null
|
||||
constructor(value: A) : this(value, null)
|
||||
|
||||
companion object {
|
||||
/** Runs the given lambda and wraps the result. */
|
||||
inline fun <T> catch(body: () -> T): ErrorOr<T> {
|
||||
return try {
|
||||
ErrorOr(body())
|
||||
} catch (t: Throwable) {
|
||||
ErrorOr.of(t)
|
||||
}
|
||||
}
|
||||
|
||||
fun of(t: Throwable) = ErrorOr(null, t)
|
||||
}
|
||||
|
||||
fun <T> match(onValue: (A) -> T, onError: (Throwable) -> T): T {
|
||||
if (error == null) {
|
||||
return onValue(value as A)
|
||||
} else {
|
||||
return onError(error)
|
||||
}
|
||||
}
|
||||
|
||||
fun getOrThrow(): A {
|
||||
if (error == null) {
|
||||
return value as A
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Functor
|
||||
fun <B> map(function: (A) -> B) = ErrorOr(value?.let(function), error)
|
||||
|
||||
// Applicative
|
||||
fun <B, C> combine(other: ErrorOr<B>, function: (A, B) -> C): ErrorOr<C> {
|
||||
val newError = error ?: other.error
|
||||
return ErrorOr(if (newError != null) null else function(value as A, other.value as B), newError)
|
||||
}
|
||||
|
||||
// Monad
|
||||
fun <B> bind(function: (A) -> ErrorOr<B>): ErrorOr<B> {
|
||||
return if (error == null) {
|
||||
function(value as A)
|
||||
} else {
|
||||
ErrorOr.of(error)
|
||||
}
|
||||
}
|
||||
|
||||
fun mapError(function: (Throwable) -> Throwable) = ErrorOr(value, error?.let(function))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Observable that buffers events until subscribed.
|
||||
* @see UnicastSubject
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.corda.core.messaging
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.core.ErrorOr
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
@ -19,6 +18,7 @@ import net.corda.core.node.services.vault.QueryCriteria
|
||||
import net.corda.core.node.services.vault.Sort
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.Try
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import rx.Observable
|
||||
import java.io.InputStream
|
||||
@ -44,7 +44,7 @@ sealed class StateMachineUpdate {
|
||||
override val id: StateMachineRunId get() = stateMachineInfo.id
|
||||
}
|
||||
|
||||
data class Removed(override val id: StateMachineRunId, val result: ErrorOr<*>) : StateMachineUpdate()
|
||||
data class Removed(override val id: StateMachineRunId, val result: Try<*>) : StateMachineUpdate()
|
||||
}
|
||||
|
||||
@CordaSerializable
|
||||
|
74
core/src/main/kotlin/net/corda/core/utilities/Try.kt
Normal file
74
core/src/main/kotlin/net/corda/core/utilities/Try.kt
Normal file
@ -0,0 +1,74 @@
|
||||
package net.corda.core.utilities
|
||||
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.Try.Failure
|
||||
import net.corda.core.utilities.Try.Success
|
||||
|
||||
/**
|
||||
* Representation of an operation that has either succeeded with a result (represented by [Success]) or failed with an
|
||||
* exception (represented by [Failure]).
|
||||
*/
|
||||
@CordaSerializable
|
||||
sealed class Try<out A> {
|
||||
companion object {
|
||||
/**
|
||||
* Executes the given block of code and returns a [Success] capturing the result, or a [Failure] if an exception
|
||||
* is thrown.
|
||||
*/
|
||||
@JvmStatic
|
||||
inline fun <T> on(body: () -> T): Try<T> {
|
||||
return try {
|
||||
Success(body())
|
||||
} catch (t: Throwable) {
|
||||
Failure(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns `true` iff the [Try] is a [Success]. */
|
||||
abstract val isFailure: Boolean
|
||||
|
||||
/** Returns `true` iff the [Try] is a [Failure]. */
|
||||
abstract val isSuccess: Boolean
|
||||
|
||||
/** Returns the value if a [Success] otherwise throws the exception if a [Failure]. */
|
||||
abstract fun getOrThrow(): A
|
||||
|
||||
/** Maps the given function to the value from this [Success], or returns `this` if this is a [Failure]. */
|
||||
inline fun <B> map(function: (A) -> B): Try<B> = when (this) {
|
||||
is Success -> Success(function(value))
|
||||
is Failure -> this
|
||||
}
|
||||
|
||||
/** Returns the given function applied to the value from this [Success], or returns `this` if this is a [Failure]. */
|
||||
inline fun <B> flatMap(function: (A) -> Try<B>): Try<B> = when (this) {
|
||||
is Success -> function(value)
|
||||
is Failure -> this
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the given function to the values from this [Success] and [other], or returns `this` if this is a [Failure]
|
||||
* or [other] if [other] is a [Failure].
|
||||
*/
|
||||
inline fun <B, C> combine(other: Try<B>, function: (A, B) -> C): Try<C> = when (this) {
|
||||
is Success -> when (other) {
|
||||
is Success -> Success(function(value, other.value))
|
||||
is Failure -> other
|
||||
}
|
||||
is Failure -> this
|
||||
}
|
||||
|
||||
data class Success<out A>(val value: A) : Try<A>() {
|
||||
override val isSuccess: Boolean get() = true
|
||||
override val isFailure: Boolean get() = false
|
||||
override fun getOrThrow(): A = value
|
||||
override fun toString(): String = "Success($value)"
|
||||
}
|
||||
|
||||
data class Failure(val exception: Throwable) : Try<Nothing>() {
|
||||
override val isSuccess: Boolean get() = false
|
||||
override val isFailure: Boolean get() = true
|
||||
override fun getOrThrow(): Nothing = throw exception
|
||||
override fun toString(): String = "Failure($exception)"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user