Skip to content

Instantly share code, notes, and snippets.

@marcellogalhardo
Last active December 20, 2018 10:46
Show Gist options
  • Save marcellogalhardo/007a48263cddd379d593d4e002981280 to your computer and use it in GitHub Desktop.
Save marcellogalhardo/007a48263cddd379d593d4e002981280 to your computer and use it in GitHub Desktop.
The [Lce] interface and its subclasses are a form of container to help handling with loading, data fetch, and error handling on Streams. This class was designed as an Immutable object that contains the data and status of each Stream operation.
/**
* The [Lce] interface and its subclasses are a form of container
* to help handling with loading, data fetch, and error handling
* on Streams. This class was designed as an Immutable object that contains
* the data and status of each Stream operation.
*/
interface Lce<T> {
fun getData(): T?
fun getError(): Throwable?
fun isSuccess(): Boolean
fun isError(): Boolean
fun isLoading(): Boolean
fun hasData(): Boolean
fun hasError(): Boolean
fun requireData(): T
fun requireError(): Throwable
enum class Status {
SUCCESS,
ERROR,
LOADING
}
companion object {
fun <T> success(): Lce<T> = SingleLce(Lce.Status.SUCCESS)
fun <T> success(data: T): Lce<T> = SingleLce(Lce.Status.SUCCESS, _data = data)
fun <T> error(error: Throwable): Lce<T> = SingleLce(Lce.Status.ERROR, _error = error)
fun <T> error(): Lce<T> = SingleLce(Lce.Status.ERROR)
fun <T> loading(): Lce<T> = SingleLce(Lce.Status.LOADING)
fun from(lces: List<Lce<*>>): Lce<*> = CompositeLce(lces)
fun from(vararg lces: Lce<*>): Lce<*> = CompositeLce(lces.toList())
}
}
import io.reactivex.exceptions.CompositeException
/**
* The [CompositeLce] class implements the Load-Content-Error Pattern
* for a composition of one of more other [Lce].
*
* A [CompositeLce] does not modify the structure of any [Lce] it
* wraps, but at print-time it iterates through the list of [Lce]
* contained in the composite.
*/
internal data class CompositeLce constructor(
private val lceList: List<Lce<*>>
) : Lce<Any> {
override fun getData(): List<Any?> = arrayListOf<Any?>().apply {
lceList.filter { it.isSuccess() }.map { add(it.getData()) }
}
override fun getError(): Throwable? = CompositeException().apply {
lceList.filter { it.isError() }.map { addSuppressed(it.getError()) }
}
override fun isSuccess(): Boolean = lceList.all { it.isSuccess() }
override fun isError(): Boolean = lceList.any { it.isError() }
override fun isLoading(): Boolean = lceList.any { it.isLoading() }
override fun hasData(): Boolean = lceList.any { it.hasData() }
override fun hasError(): Boolean = lceList.any { it.hasError() }
override fun requireData(): List<Any> = arrayListOf<Any>().apply {
lceList.filter { it.hasData() }.map { add(it.getData()!!) }
}
override fun requireError(): Throwable = CompositeException().apply {
lceList.filter { it.hasError() }.map { addSuppressed(it.getError()) }
}
}
/**
* The [SingleLce] class implements the Load-Content-Error Pattern
* for a single [Lce].
*/
internal data class SingleLce<T> constructor(
private val _status: Lce.Status,
private val _data: T? = null,
private val _error: Throwable? = null
) : Lce<T> {
override fun getData(): T? = _data
override fun getError(): Throwable? = _error
override fun isSuccess(): Boolean = _status == Lce.Status.SUCCESS
override fun isError(): Boolean = _status == Lce.Status.ERROR
override fun isLoading(): Boolean = _status == Lce.Status.LOADING
override fun hasData(): Boolean = isSuccess() && _data != null
override fun hasError(): Boolean = isError() && _error != null
override fun requireData(): T = getData()!!
override fun requireError(): Throwable = getError()!!
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment