Skip to content

Instantly share code, notes, and snippets.

@abdallaadelessa
Last active July 11, 2019 10:24
Show Gist options
  • Save abdallaadelessa/be04ef659941068ea3c75a314e24d27d to your computer and use it in GitHub Desktop.
Save abdallaadelessa/be04ef659941068ea3c75a314e24d27d to your computer and use it in GitHub Desktop.
@file:UseExperimental(ExperimentalContracts::class)
package de.android.kotlin
import java.io.Serializable
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
/**
* @author Created by Abdullah Essa on 2019-06-18.
*/
//region Params
/**
* Wrapper class for 4 null safe parameters
*/
data class FourParams<out A, out B, out C, out D>(
val first: A,
val second: B,
val third: C,
val fourth: D
) : Serializable {
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String = "($first, $second, $third, $fourth)"
}
/**
* Converts this FourParams into a list.
*/
fun <T> FourParams<T, T, T, T>.toList(): List<T> = listOf(first, second, third, fourth)
/**
* Wrapper class for 5 null safe parameters
*/
data class FiveParams<out A, out B, out C, out D, out E>(
val first: A,
val second: B,
val third: C,
val fourth: D,
val fifth: E
) : Serializable {
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String = "($first, $second, $third, $fourth, $fifth)"
}
/**
* Converts this FiveParams into a list.
*/
fun <T> FiveParams<T, T, T, T, T>.toList(): List<T> = listOf(first, second, third, fourth, fifth)
//endregion
//region All
/**
* @return either a null safe [Pair] of the given parameters (if all of them are not null)
* or null if at least one of them is null
*
* ##Usage:
*
* val v1: Activity? = null
* val v2: Fragment? = null
*
* all(v1, v2)
* ?.let { (activity, fragment) ->
* activity.toString()
* fragment.toString()
* }
*
*/
fun <A, B> all(first: A?, second: B?): Pair<A, B>? {
contract {
returnsNotNull() implies (first != null && second != null)
}
if (first == null || second == null) {
return null
} else {
return Pair(first, second)
}
}
/**
* @return either a null safe [Triple] of the given parameters (if all of them are not null)
* or null if at least one of them is null
*
* ##Usage:
*
* val v1: Activity? = null
* val v2: Fragment? = null
* val v3: Int? = null
*
* all(v1, v2, v3)
* ?.takeIf { (activity, fragment, intVar) -> !activity.isDestroyed && fragment.isAdded && intVar > 0 }
* ?.run {
* first.toString()
* second.toString()
* third.toString()
* }
*
*/
fun <A, B, C> all(first: A?, second: B?, third: C?): Triple<A, B, C>? {
contract {
returnsNotNull() implies (first != null && second != null && third != null)
}
if (first == null || second == null || third == null) {
return null
} else {
return Triple(first, second, third)
}
}
/**
* @return either a null safe [FourParams] of the given parameters (if all of them are not null)
* or null if at least one of them is null
*
* ##Usage:
*
* val v1: Activity? = null
* val v2: Fragment? = null
* val v3: Int? = null
* val v4: String? = null
*
* all(v1, v2, v3, v4)
* ?.also { (activity, fragment, intVar, stringVar) ->
* activity.toString()
* fragment.toString()
* intVar.toString()
* stringVar.toString()
* }
*
*/
@Suppress("ComplexCondition")
fun <A, B, C, D> all(first: A?, second: B?, third: C?, fourth: D?): FourParams<A, B, C, D>? {
contract {
returnsNotNull() implies (first != null && second != null && third != null && fourth != null)
}
if (first == null || second == null || third == null || fourth == null) {
return null
} else {
return FourParams(first, second, third, fourth)
}
}
/**
* @return either a null safe [FiveParams] of the given parameters (if all of them are not null)
* or null if at least one of them is null
*
* ##Usage:
*
* val v1: Activity? = null
* val v2: Fragment? = null
* val v3: Int? = null
* val v4: String? = null
* val v5: Boolean? = null
*
* all(v1, v2, v3, v4 ,v5)
* ?.apply {
* first.toString()
* second.toString()
* third.toString()
* fourth.toString()
* fifth.toString()
* }
*
*/
@Suppress("ComplexCondition")
fun <A, B, C, D, E> all(first: A?, second: B?, third: C?, fourth: D?, fifth: E?):
FiveParams<A, B, C, D, E>? {
contract {
returnsNotNull() implies (first != null && second != null
&& third != null && fourth != null && fifth != null)
}
if (first == null || second == null || third == null || fourth == null || fifth == null) {
return null
} else {
return FiveParams(first, second, third, fourth, fifth)
}
}
/**
* @return either a null safe [List] of the given parameters (if all of them are not null)
* or null if at least one of them is null
*
* ##Usage:
*
* val v1: Activity? = null
* val v2: Fragment? = null
* val v3: Int? = null
* val v4: String? = null
* val v5: Boolean? = null
*
* allAsList(v1, v2, v3, v4 ,v5)
* ?.let {
* val first = it[0] as Activity
* val second = it[1] as Fragment
* val third = it[2] as Int
* val fourth = it[3] as String
* val fifth = it[4] as Boolean
* }
*
*/
fun <T : Any> allAsList(vararg params: T?): List<T>? =
params.filterNotNull().takeIf { it.size == params.size }
//endregion
//region Mit
infix fun <A, B> A?.mit(other: B?) = all(
this,
other
)
infix fun <A, B, C> Pair<A?, B?>?.mit(other: C?) = all(
this?.first,
this?.second,
other
)
infix fun <A, B, C, D> Triple<A?, B?, C?>?.mit(other: D?) = all(
this?.first,
this?.second,
this?.third,
other
)
infix fun <A, B, C, D, E> FourParams<A?, B?, C?, D?>?.mit(other: E?) = all(
this?.first,
this?.second,
this?.third,
this?.fourth,
other
)
infix fun <A : Any, B : Any, C : Any, D : Any, E : Any, F : Any> FiveParams<A?, B?, C?, D?, E?>?.mit(other: F?) =
allAsList(
this?.first,
this?.second,
this?.third,
this?.fourth,
this?.fifth,
other
)
infix fun List<Any?>?.mit(other: Any?): List<Any>? {
if (this == null) return allAsList(other)
return allAsList(*this.toTypedArray(), other)
}
//endregion
fun main() {
val v1: Long? = 1L
val v2: Char? = 'a'
val v3: Int? = 1
val v4: String? = "a"
val v5: Boolean? = true
all(v1, v2)?.let { (activity, fragment) ->
activity.toString()
fragment.toString()
}
if (all(v1, v2) != null) {
//Smart cast
v1.toString()
v2.toString()
}
//=========>
all(v1, v2, v3)?.run {
first.toString()
second.toString()
third.toString()
}
all(v1, v2, v3)
?.takeIf { (activity, fragment, intVar) -> intVar > 0 }
?.let { (first, second, third) ->
first.toString()
second.toString()
third.toString()
}
if (all(v1, v2, v3) != null) {
//Smart cast
v1.toString()
v2.toString()
v3.toString()
}
//=========>
all(v1, v2, v3, v4)
?.also { (activity, fragment, intVar, stringVar) ->
activity.toString()
fragment.toString()
intVar.toString()
stringVar.toString()
}
if (all(v1, v2, v3, v4) != null) {
//Smart cast
v1.toString()
v2.toString()
v3.toString()
v4.toString()
}
//=========>
all(v1, v2, v3, v4, v5)
?.apply {
first.toString()
second.toString()
third.toString()
fourth.toString()
fifth.toString()
}
if (all(v1, v2, v3, v4, v5) != null) {
//Smart cast
v1.toString()
v2.toString()
v3.toString()
v4.toString()
v5.toString()
}
//=========>
allAsList(v1, v2, v3, v4, v5)
?.let {
val first = it[0] as Long
val second = it[1] as Char
val third = it[2] as Int
val fourth = it[3] as String
val fifth = it[4] as Boolean
}
//=========>
(v1 mit v2)?.run {
first.toString()
second.toString()
}
(v1 mit v2 mit v3)?.run {
first.toString()
second.toString()
third.toString()
}
(v1 mit v2 mit v3 mit v4)?.run {
first.toString()
second.toString()
third.toString()
fourth.toString()
}
(v1 mit v2 mit v3 mit v4 mit v5)?.run {
first.toString()
second.toString()
third.toString()
fourth.toString()
fifth.toString()
}
(v1 mit v2 mit v3 mit v4 mit v5 mit v5 mit v5)?.run {
toString()
}
}
package de.android.kotlin
import android.app.Activity
import androidx.fragment.app.Fragment
import de.android.BaseUnitTest
import de.android.utils.tuples.FiveParams
import de.android.utils.tuples.FourParams
import de.android.utils.tuples.toList
import org.junit.Test
import org.mockito.Mockito.mock
import kotlin.contracts.ExperimentalContracts
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
/**
* @author Created by Abdullah Essa on 2019-06-18.
*/
@ExperimentalContracts
class C24StandardTest : BaseUnitTest() {
private var v1: Activity? = null
private var v2: Fragment? = null
private var v3: Int? = null
private var v4: String? = null
private var v5: Boolean? = null
private var v6: Int? = null
private var v7: Int? = null
private var v8: Int? = null
override fun setUp() {
super.setUp()
v1 = null
v2 = null
v3 = null
v4 = null
v5 = null
v6 = null
v7 = null
v8 = null
}
@Test
fun testAllWithTwoNullParams() {
val all = all(v1, v2)
assertNull(all)
}
@Test
fun testAllWithTwoNotNullParams() {
v1 = mock(Activity::class.java)
v2 = mock(Fragment::class.java)
val all = all(v1, v2)
assertNotNull(all)
assertNotNull(all.first)
assertNotNull(all.second)
}
@Test
fun testAllWithThreeNullParams() {
val all = all(v1, v2, v3)
assertNull(all)
}
@Test
fun testAllWithThreeNotNullParams() {
v1 = mock(Activity::class.java)
v2 = mock(Fragment::class.java)
v3 = 1
val all = all(v1, v2, v3)
assertNotNull(all)
assertNotNull(all.first)
assertNotNull(all.second)
assertNotNull(all.third)
}
@Test
fun testAllWithFourNullParams() {
val all = all(v1, v2, v3, v4)
assertNull(all)
}
@Test
fun testAllWithFourNotNullParams() {
v1 = mock(Activity::class.java)
v2 = mock(Fragment::class.java)
v3 = 1
v4 = ""
val all = all(v1, v2, v3, v4)
assertNotNull(all)
assertNotNull(all.first)
assertNotNull(all.second)
assertNotNull(all.third)
assertNotNull(all.fourth)
}
@Test
fun testAllWithFiveNullParams() {
val all = all(v1, v2, v3, v4, v5)
assertNull(all)
}
@Test
fun testAllWithFiveNotNullParams() {
v1 = mock(Activity::class.java)
v2 = mock(Fragment::class.java)
v3 = 1
v4 = ""
v5 = true
val all = all(v1, v2, v3, v4, v5)
assertNotNull(all)
assertNotNull(all.first)
assertNotNull(all.second)
assertNotNull(all.third)
assertNotNull(all.fourth)
assertNotNull(all.fifth)
}
@Test
fun testAllAsListWithNullableValues() {
val all = all(v1, v2, v3, v4, v5)
assertNull(all)
}
@Test
fun testAllAsListWithNotNullValues() {
v1 = mock(Activity::class.java)
v2 = mock(Fragment::class.java)
v3 = 1
v4 = ""
v5 = true
v6 = 2
v7 = 3
v8 = 4
val all = allAsList(v1, v2, v3, v4, v5, v6, v7, v8)
assertNotNull(all)
assertTrue { all.size == 8 }
assertTrue { all[0] == v1 }
assertTrue { all[1] == v2 }
assertTrue { all[2] == v3 }
assertTrue { all[3] == v4 }
assertTrue { all[4] == v5 }
assertTrue { all[5] == v6 }
assertTrue { all[6] == v7 }
assertTrue { all[7] == v8 }
}
@Test
fun testFourParamsToList() {
val v1 = 10
val v2 = 20
val v3 = 30
val v4 = 40
val fourParamsList = FourParams(v1, v2, v3, v4).toList()
val compareList = listOf(v1, v2, v3, v4)
assertTrue { fourParamsList.size == 4 }
assertTrue { fourParamsList[0] == compareList[0] }
assertTrue { fourParamsList[1] == compareList[1] }
assertTrue { fourParamsList[2] == compareList[2] }
assertTrue { fourParamsList[3] == compareList[3] }
}
@Test
fun testFiveParamsToList() {
val v1 = 10
val v2 = 20
val v3 = 30
val v4 = 40
val v5 = 50
val fourParamsList = FiveParams(v1, v2, v3, v4, v5).toList()
val compareList = listOf(v1, v2, v3, v4, v5)
assertTrue { fourParamsList.size == 5 }
assertTrue { fourParamsList[0] == compareList[0] }
assertTrue { fourParamsList[1] == compareList[1] }
assertTrue { fourParamsList[2] == compareList[2] }
assertTrue { fourParamsList[3] == compareList[3] }
assertTrue { fourParamsList[4] == compareList[4] }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment