All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.graphglue.connection.model.Connection.kt Maven / Gradle / Ivy

Go to download

A library to develop annotation-based code-first GraphQL servers using GraphQL Kotlin, Spring Boot and Neo4j - excluding Spring GraphQL server dependencies

The newest version!
package io.github.graphglue.connection.model

import com.fasterxml.jackson.databind.ObjectMapper
import graphql.execution.DataFetcherResult
import graphql.schema.DataFetchingEnvironment
import io.github.graphglue.connection.order.Order
import io.github.graphglue.data.execution.NodeQueryResult
import io.github.graphglue.graphql.extensions.getDataFetcherResult
import io.github.graphglue.model.Node

/**
 * Connection used as ObjectType in the GraphQL API
 * Represents the many side of a relation and supports filtering, ordering and pagination
 *
 * @param nodes all related nodes
 * @param pageInfo general connection information
 * @param totalCount if fetched, the total amount of items in the relation
 * @param order defines how the items are ordered in the connection, necessary for cursor definition
 */
class Connection(
    private val nodes: List,
    val pageInfo: PageInfo,
    private val totalCount: Int?,
    private val order: Order
) {

    /**
     * Returns the nodes and sets the local context necessary to use caching
     *
     * @param dataFetchingEnvironment defines how the query fetches data
     * @return all nodes and the local context necessary for caching
     */
    fun nodes(dataFetchingEnvironment: DataFetchingEnvironment): DataFetcherResult> {
        return dataFetchingEnvironment.getDataFetcherResult(nodes, dataFetchingEnvironment.executionStepInfo.resultKey)
    }

    /**
     * Returns the nodes associated with a cursor
     * local context is handled by the returned [Edge] (see [Edge.node]) and therefore not set by this method
     *
     * @return a list of all edges
     */
    fun edges(): List> {
        return nodes.map { Edge(it, order) }
    }

    /**
     * The total count of nodes in the connection (before filtering and pagination)
     *
     * @return the total count
     * @throws IllegalStateException if totalCount is not available because it was not fetched
     */
    fun totalCount(): Int {
        return totalCount ?: throw IllegalStateException("totalCount not available")
    }

    companion object {

        /**
         * Creates a [Connection] from a [NodeQueryResult]
         * The provided `queryResult` may contain one more [Node] then defined by first or last
         * to calculate hasNextPage and hasPreviousPage. If so, this node is removed from the node list
         *
         * @param T the [Node] type of the returned [Connection]
         * @param queryResult the result of the database query
         * @param objectMapper necessary for cursor generation
         * @return the generated [Connection]
         */
        @Suppress("UNCHECKED_CAST")
        fun  fromQueryResult(
            queryResult: NodeQueryResult,
            objectMapper: ObjectMapper
        ): Connection {
            val options = queryResult.options
            val nodes = if (options.first != null) {
                queryResult.nodes.subList(0, (options.first - 1).coerceAtMost(queryResult.nodes.size))
            } else if (options.last != null) {
                queryResult.nodes.subList(
                    (queryResult.nodes.size - (options.last - 1)).coerceAtLeast(0),
                    queryResult.nodes.size
                )
            } else {
                queryResult.nodes
            }
            val pageInfo = PageInfo(options, queryResult.nodes, nodes, objectMapper)
            return Connection(nodes, pageInfo, queryResult.totalCount, options.orderBy as Order)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy