commonMain.com.apollographql.apollo3.api.BooleanExpression.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apollo-api-jvm Show documentation
Show all versions of apollo-api-jvm Show documentation
Apollo GraphQL API classes
@file:JvmName("BooleanExpressions")
package com.apollographql.apollo3.api
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince
import com.apollographql.apollo3.annotations.ApolloDeprecatedSince.Version.v4_0_0
import kotlin.jvm.JvmName
import kotlin.reflect.KClass
/**
* A boolean expression
*
* @param T the type of the variable elements. This allows representing BooleanExpression that only contain variables and
* other that may also contain possibleTypes
*/
sealed class BooleanExpression {
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
abstract fun simplify(): BooleanExpression
object True : BooleanExpression() {
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
override fun simplify() = this
}
object False : BooleanExpression() {
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
override fun simplify() = this
}
data class Not(val operand: BooleanExpression) : BooleanExpression() {
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
override fun simplify() = when (this.operand) {
is True -> False
is False -> True
else -> this
}
}
data class Or(val operands: Set>) : BooleanExpression() {
constructor(vararg operands: BooleanExpression) : this(operands.toSet())
init {
check(operands.isNotEmpty()) {
"Apollo: cannot create a 'Or' condition from an empty list"
}
}
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
@Suppress("DEPRECATION_ERROR")
override fun simplify() = operands.filter {
it != False
}.map { it.simplify() }
.let {
when {
it.contains(True) -> True
it.isEmpty() -> False
it.size == 1 -> it.first()
else -> {
Or(it.toSet())
}
}
}
override fun toString() = operands.joinToString(" | ")
}
data class And(val operands: Set>) : BooleanExpression() {
constructor(vararg operands: BooleanExpression) : this(operands.toSet())
init {
check(operands.isNotEmpty()) {
"Apollo: cannot create a 'And' condition from an empty list"
}
}
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
@Suppress("DEPRECATION_ERROR")
override fun simplify() = operands.filter {
it != True
}.map { it.simplify() }
.let {
when {
it.contains(False) -> False
it.isEmpty() -> True
it.size == 1 -> it.first()
else -> {
And(it.toSet())
}
}
}
}
data class Element(
val value: T,
) : BooleanExpression() {
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
@Suppress("DEPRECATION_ERROR")
override fun simplify() = this
}
}
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
fun BooleanExpression.or(vararg other: BooleanExpression): BooleanExpression = BooleanExpression.Or((other.toList() + this).toSet())
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
fun BooleanExpression.and(vararg other: BooleanExpression): BooleanExpression = BooleanExpression.And((other.toList() + this).toSet())
fun or(vararg other: BooleanExpression): BooleanExpression = BooleanExpression.Or((other.toList()).toSet())
fun and(vararg other: BooleanExpression): BooleanExpression = BooleanExpression.And((other.toList()).toSet())
fun not(other: BooleanExpression): BooleanExpression = BooleanExpression.Not(other)
fun variable(name: String): BooleanExpression = BooleanExpression.Element(BVariable(name))
fun label(label: String? = null): BooleanExpression = BooleanExpression.Element(BLabel(label))
fun possibleTypes(vararg typenames: String): BooleanExpression = BooleanExpression.Element(BPossibleTypes(typenames.toSet()))
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
@Suppress("DEPRECATION_ERROR")
fun BooleanExpression.evaluate(block: (T) -> Boolean): Boolean {
return when (this) {
BooleanExpression.True -> true
BooleanExpression.False -> false
is BooleanExpression.Not -> !operand.evaluate(block)
is BooleanExpression.Or -> operands.any { it.evaluate(block) }
is BooleanExpression.And -> operands.all { it.evaluate(block) }
is BooleanExpression.Element -> block(value)
}
}
@Suppress("DEPRECATION_ERROR")
fun BooleanExpression.evaluate(
variables: Set,
typename: String?,
deferredFragmentIdentifiers: Set?,
path: List?,
): Boolean {
// Remove "data" from the path
val croppedPath = path?.drop(1)
return evaluate {
when (it) {
is BVariable -> !variables.contains(it.name)
is BLabel -> hasDeferredFragment(deferredFragmentIdentifiers, croppedPath!!, it.label)
is BPossibleTypes -> it.possibleTypes.contains(typename)
}
}
}
private fun hasDeferredFragment(deferredFragmentIdentifiers: Set?, path: List, label: String?): Boolean {
if (deferredFragmentIdentifiers == null) {
// By default, parse all deferred fragments - this is the case when parsing from the normalized cache.
return true
}
return deferredFragmentIdentifiers.contains(DeferredFragmentIdentifier(path, label))
}
/**
* A generic term in a [BooleanExpression]
*/
sealed class BTerm
/**
* A term that comes from @include/@skip or @defer directives and that needs to be matched against operation variables
*/
data class BVariable(val name: String) : BTerm()
/**
* A term that comes from @defer directives and that needs to be matched against label and current JSON path
*/
data class BLabel(val label: String?) : BTerm()
/**
* A term that comes from a fragment type condition and that needs to be matched against __typename
*/
data class BPossibleTypes(val possibleTypes: Set) : BTerm() {
constructor(vararg types: String) : this(types.toSet())
}
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
@Suppress("DEPRECATION_ERROR")
fun BooleanExpression.containsPossibleTypes(): Boolean {
return when (this) {
BooleanExpression.True -> false
BooleanExpression.False -> false
is BooleanExpression.Not -> operand.containsPossibleTypes()
is BooleanExpression.Or -> operands.any { it.containsPossibleTypes() }
is BooleanExpression.And -> operands.any { it.containsPossibleTypes() }
is BooleanExpression.Element -> value is BPossibleTypes
}
}
@Deprecated(message = "This was only used in internal API and shouldn't have been part of the public API. If you needed this, please open an issue.", level = DeprecationLevel.ERROR)
@ApolloDeprecatedSince(v4_0_0)
@Suppress("DEPRECATION_ERROR")
fun BooleanExpression.firstElementOfType(type: KClass): U? {
return when (this) {
BooleanExpression.True -> null
BooleanExpression.False -> null
is BooleanExpression.Element -> @Suppress("UNCHECKED_CAST") if (type.isInstance(this.value)) this.value as U else null
is BooleanExpression.Not -> this.operand.firstElementOfType(type)
is BooleanExpression.And -> (this.operands.firstOrNull { it.firstElementOfType(type) != null })?.firstElementOfType(type)
is BooleanExpression.Or -> (this.operands.firstOrNull { it.firstElementOfType(type) != null })?.firstElementOfType(type)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy