Skip to content

Commit b4dbf25

Browse files
committed
LCE Fold function
1 parent 9232ad7 commit b4dbf25

7 files changed

Lines changed: 153 additions & 25 deletions

File tree

lce/api/jvm/lce.api

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,19 @@ public final class com/motorro/rxlcemodel/lce/LceStateKt {
7373
public static final fun catchToLce (Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function1;)Lcom/motorro/rxlcemodel/lce/LceState;
7474
public static final fun combine (Lcom/motorro/rxlcemodel/lce/LceState;Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function2;)Lcom/motorro/rxlcemodel/lce/LceState;
7575
public static final fun flatMap (Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function1;)Lcom/motorro/rxlcemodel/lce/LceState;
76+
public static final fun fold (Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V
77+
public static synthetic fun fold$default (Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
7678
public static final fun map (Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function1;)Lcom/motorro/rxlcemodel/lce/LceState;
7779
public static final fun mapEmptyDataItem (Lcom/motorro/rxlcemodel/lce/LceState;Lkotlin/jvm/functions/Function0;)Lcom/motorro/rxlcemodel/lce/LceState;
7880
}
7981

82+
public final class com/motorro/rxlcemodel/lce/exception/UnhandledTerminationException : java/lang/IllegalStateException {
83+
public fun <init> ()V
84+
public fun <init> (Ljava/lang/Throwable;)V
85+
public synthetic fun <init> (Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
86+
public fun equals (Ljava/lang/Object;)Z
87+
public fun getCause ()Ljava/lang/Throwable;
88+
public fun hashCode ()I
89+
public fun toString ()Ljava/lang/String;
90+
}
91+

lce/api/lce.klib.api

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
// - Show declarations: true
77

88
// Library unique name: <com.motorro.rxlcemodel:lce>
9+
final class com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException : kotlin/IllegalStateException { // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException|null[0]
10+
constructor <init>(kotlin/Throwable? = ...) // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException.<init>|<init>(kotlin.Throwable?){}[0]
11+
12+
final val cause // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException.cause|{}cause[0]
13+
final fun <get-cause>(): kotlin/Throwable? // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException.cause.<get-cause>|<get-cause>(){}[0]
14+
15+
final fun equals(kotlin/Any?): kotlin/Boolean // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException.equals|equals(kotlin.Any?){}[0]
16+
final fun hashCode(): kotlin/Int // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException.hashCode|hashCode(){}[0]
17+
final fun toString(): kotlin/String // com.motorro.rxlcemodel.lce.exception/UnhandledTerminationException.toString|toString(){}[0]
18+
}
19+
920
sealed class <#A: out kotlin/Any> com.motorro.rxlcemodel.lce/LceState { // com.motorro.rxlcemodel.lce/LceState|null[0]
1021
abstract val data // com.motorro.rxlcemodel.lce/LceState.data|{}data[0]
1122
abstract fun <get-data>(): #A? // com.motorro.rxlcemodel.lce/LceState.data.<get-data>|<get-data>(){}[0]
@@ -97,5 +108,6 @@ final inline fun <#A: kotlin/Any, #B: kotlin/Any, #C: kotlin/Any> (com.motorro.r
97108
final inline fun <#A: kotlin/Any, #B: kotlin/Any> (com.motorro.rxlcemodel.lce/LceState<#A>).com.motorro.rxlcemodel.lce/catchToLce(kotlin/Function1<com.motorro.rxlcemodel.lce/LceState<#A>, com.motorro.rxlcemodel.lce/LceState<#B>>): com.motorro.rxlcemodel.lce/LceState<#B> // com.motorro.rxlcemodel.lce/catchToLce|catchToLce@com.motorro.rxlcemodel.lce.LceState<0:0>(kotlin.Function1<com.motorro.rxlcemodel.lce.LceState<0:0>,com.motorro.rxlcemodel.lce.LceState<0:1>>){0§<kotlin.Any>;1§<kotlin.Any>}[0]
98109
final inline fun <#A: kotlin/Any, #B: kotlin/Any> (com.motorro.rxlcemodel.lce/LceState<#A>).com.motorro.rxlcemodel.lce/flatMap(kotlin/Function1<#A, com.motorro.rxlcemodel.lce/LceState<#B>>): com.motorro.rxlcemodel.lce/LceState<#B> // com.motorro.rxlcemodel.lce/flatMap|flatMap@com.motorro.rxlcemodel.lce.LceState<0:0>(kotlin.Function1<0:0,com.motorro.rxlcemodel.lce.LceState<0:1>>){0§<kotlin.Any>;1§<kotlin.Any>}[0]
99110
final inline fun <#A: kotlin/Any, #B: kotlin/Any> (com.motorro.rxlcemodel.lce/LceState<#A>).com.motorro.rxlcemodel.lce/map(kotlin/Function1<#A, #B>): com.motorro.rxlcemodel.lce/LceState<#B> // com.motorro.rxlcemodel.lce/map|map@com.motorro.rxlcemodel.lce.LceState<0:0>(kotlin.Function1<0:0,0:1>){0§<kotlin.Any>;1§<kotlin.Any>}[0]
111+
final inline fun <#A: kotlin/Any> (com.motorro.rxlcemodel.lce/LceState<#A>).com.motorro.rxlcemodel.lce/fold(kotlin/Function1<com.motorro.rxlcemodel.lce/LceState.Loading<#A>, kotlin/Unit>, kotlin/Function1<com.motorro.rxlcemodel.lce/LceState.Content<#A>, kotlin/Unit>, kotlin/Function1<com.motorro.rxlcemodel.lce/LceState.Error<#A>, kotlin/Unit>, kotlin/Function0<kotlin/Unit> = ...) // com.motorro.rxlcemodel.lce/fold|fold@com.motorro.rxlcemodel.lce.LceState<0:0>(kotlin.Function1<com.motorro.rxlcemodel.lce.LceState.Loading<0:0>,kotlin.Unit>;kotlin.Function1<com.motorro.rxlcemodel.lce.LceState.Content<0:0>,kotlin.Unit>;kotlin.Function1<com.motorro.rxlcemodel.lce.LceState.Error<0:0>,kotlin.Unit>;kotlin.Function0<kotlin.Unit>){0§<kotlin.Any>}[0]
100112
final inline fun <#A: kotlin/Any> (com.motorro.rxlcemodel.lce/LceState<#A>).com.motorro.rxlcemodel.lce/mapEmptyDataItem(crossinline kotlin/Function0<#A?>): com.motorro.rxlcemodel.lce/LceState<#A> // com.motorro.rxlcemodel.lce/mapEmptyDataItem|mapEmptyDataItem@com.motorro.rxlcemodel.lce.LceState<0:0>(kotlin.Function0<0:0?>){0§<kotlin.Any>}[0]
101113
final inline fun <#A: reified kotlin/Any> (com.motorro.rxlcemodel.lce/LceState<#A>).com.motorro.rxlcemodel.lce/mapEmptyData(crossinline kotlin/Function1<com.motorro.rxlcemodel.lce/LceState<#A>, com.motorro.rxlcemodel.lce/LceState<#A>>): com.motorro.rxlcemodel.lce/LceState<#A> // com.motorro.rxlcemodel.lce/mapEmptyData|mapEmptyData@com.motorro.rxlcemodel.lce.LceState<0:0>(kotlin.Function1<com.motorro.rxlcemodel.lce.LceState<0:0>,com.motorro.rxlcemodel.lce.LceState<0:0>>){0§<kotlin.Any>}[0]

lce/src/commonMain/kotlin/com/motorro/rxlcemodel/lce/LceState.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
package com.motorro.rxlcemodel.lce
1515

16+
import com.motorro.rxlcemodel.lce.exception.UnhandledTerminationException
17+
1618
/**
1719
* State for "Loading-Content-Error" resource which retrieves [data]
1820
* @param DATA Data Type of data being held
@@ -312,3 +314,24 @@ inline fun <DATA : Any> LceState<DATA>.mapEmptyDataItem(crossinline block: () ->
312314
else -> this
313315
}
314316
}
317+
318+
/**
319+
* Calls handlers for each state type
320+
* @param onLoading State handler for [LceState.Loading]
321+
* @param onContent State handler for [LceState.Content]
322+
* @param onError State handler for [LceState.Error]
323+
* @param terminated State handler for [LceState.Terminated]
324+
*/
325+
inline fun <DATA : Any> LceState<DATA>.fold(
326+
onLoading: (LceState.Loading<DATA>) -> Unit,
327+
onContent: (LceState.Content<DATA>) -> Unit,
328+
onError: (LceState.Error<DATA>) -> Unit,
329+
terminated: () -> Unit = { throw UnhandledTerminationException() }
330+
) {
331+
when (this) {
332+
is LceState.Loading -> onLoading(this)
333+
is LceState.Content -> onContent(this)
334+
is LceState.Error -> onError(this)
335+
LceState.Terminated -> terminated()
336+
}
337+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.motorro.rxlcemodel.lce.exception
2+
3+
/**
4+
* Error thrown on unhandled termination
5+
*/
6+
class UnhandledTerminationException(override val cause: Throwable? = null) : IllegalStateException("Unhandled termination") {
7+
8+
override fun toString(): String {
9+
return "UnhandledTerminationException: $message"
10+
}
11+
12+
override fun equals(other: Any?): Boolean {
13+
if (this === other) return true
14+
if (other == null || this::class != other::class) return false
15+
16+
other as UnhandledTerminationException
17+
18+
return cause == other.cause
19+
}
20+
21+
override fun hashCode(): Int {
22+
return cause?.hashCode() ?: 0
23+
}
24+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2022 Nikolai Kotchetkov.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
14+
package com.motorro.rxlcemodel.lce
15+
16+
import kotlin.test.Test
17+
import kotlin.test.assertEquals
18+
19+
class LceStateFoldTest {
20+
@Test
21+
fun foldsLoading() {
22+
val state = LceState.Loading(1, true)
23+
var called = false
24+
state.fold(
25+
onLoading = {
26+
assertEquals(state, it)
27+
called = true
28+
},
29+
onContent = { error("Should not be called") },
30+
onError = { error("Should not be called") }
31+
)
32+
assertEquals(true, called)
33+
}
34+
35+
@Test
36+
fun foldsContent() {
37+
val state = LceState.Content(1, true)
38+
var called = false
39+
state.fold(
40+
onLoading = { error("Should not be called") },
41+
onContent = {
42+
assertEquals(state, it)
43+
called = true
44+
},
45+
onError = { error("Should not be called") }
46+
)
47+
assertEquals(true, called)
48+
}
49+
50+
@Test
51+
fun foldsError() {
52+
val error = Exception("error")
53+
val state = LceState.Error(1, true, error)
54+
var called = false
55+
state.fold(
56+
onLoading = { error("Should not be called") },
57+
onContent = { error("Should not be called") },
58+
onError = {
59+
assertEquals(state, it)
60+
called = true
61+
}
62+
)
63+
assertEquals(true, called)
64+
}
65+
66+
@Test
67+
fun foldsTerminated() {
68+
val state = LceState.Terminated
69+
var called = false
70+
state.fold(
71+
onLoading = { error("Should not be called") },
72+
onContent = { error("Should not be called") },
73+
onError = { error("Should not be called") },
74+
terminated = { called = true }
75+
)
76+
assertEquals(true, called)
77+
}
78+
}

viewmodel/src/main/kotlin/com/motorro/rxlcemodel/viewmodel/BaseLceModel.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ import androidx.lifecycle.LiveData
1818
import androidx.lifecycle.MutableLiveData
1919
import com.motorro.rxlcemodel.lce.LceState
2020
import com.motorro.rxlcemodel.lce.combine
21+
import com.motorro.rxlcemodel.lce.exception.UnhandledTerminationException
2122
import com.motorro.rxlcemodel.rx.LceUseCase
22-
import com.motorro.rxlcemodel.viewmodel.error.UnhandledException
2323
import io.reactivex.rxjava3.core.Completable
2424
import io.reactivex.rxjava3.core.Observable
2525
import io.reactivex.rxjava3.disposables.CompositeDisposable
2626
import io.reactivex.rxjava3.disposables.Disposable
2727
import io.reactivex.rxjava3.subjects.BehaviorSubject
28-
import java.util.*
28+
import java.util.Optional
2929

3030
/**
3131
* Base model with [state] and [refresh]
@@ -138,7 +138,7 @@ abstract class BaseLceModel<DATA : Any> : BaseViewModel() {
138138
protected fun addSubscription(completable: Completable) {
139139
val subscription = completable.subscribe(
140140
{ /* NOOP */ },
141-
{ error -> throw UnhandledException(error) }
141+
{ error -> throw UnhandledTerminationException(error) }
142142
)
143143

144144
addSubscription(subscription)
@@ -166,7 +166,7 @@ abstract class BaseLceModel<DATA : Any> : BaseViewModel() {
166166
val subscription = stateObservable
167167
.subscribe(
168168
{ state -> stateData.value = state },
169-
{ error -> throw UnhandledException(error) }
169+
{ error -> throw UnhandledTerminationException(error) }
170170
)
171171
disposables.add(subscription)
172172
}

viewmodel/src/main/kotlin/com/motorro/rxlcemodel/viewmodel/error/UnhandledException.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)