public PaginatorResult Materialize()

in src/Epam.GraphQL/Relay/Paginator.cs [114:276]


        public PaginatorResult<TSource> Materialize()
#pragma warning restore CA1502
        {
            // Dragons live here...
            var query = _query;

            if (!_shouldMaterialize && !_shouldSkip && !_shouldTake && !_shouldTakeBefore && !_shouldTakeLast)
            {
                return new PaginatorResult<TSource>
                {
                    StartOffset = 0,
                    Page = _executer.ToEnumerable(_configurationContext, _stepNameFactory, query),
                };
            }

            var liveSkipCount = _skipCount - (_shouldSkip ? 1 : 0);

            if (_shouldSkip)
            {
                // Skip items excluding the last one.
                // It is intended to ensure that we did not skip the whole data sequence.
                query = query.Skip(liveSkipCount);
            }

            var liveTakeCount = _takeCount + 1 + (_shouldSkip ? 1 : 0);

            if (_shouldTake)
            {
                // Take items including the next item and maybe including previous one (if 'Skip' was performed).
                query = query.Take(liveTakeCount);
            }

            var sample = _executer.ToList(_configurationContext, _stepNameFactory, query);
            var shouldRemoveLast = false;
            var skipCanceled = false;
            var hasNextPage = false;
            var hasPreviousPage = false;
            int? offset = 0;
            int? totalCount = null;

            if (_shouldTake)
            {
                if (sample.Count > 0)
                {
                    if (sample.Count == liveTakeCount)
                    {
                        if (!_shouldTakeBefore || _takeBeforeCount > 0)
                        {
                            hasNextPage = true;
                        }

                        shouldRemoveLast = true;
                    }
                    else
                    {
                        // If sample.Count < liveTakeCount then 'Take' operation gave us one item at least.
                        // It means that we reached the end of data sequence, so there is no the next page for current page.
                        totalCount = liveSkipCount + sample.Count;
                    }
                }
                else if (_shouldSkip)
                {
                    // Query is being executed the second time because 'Take' gave us no items. It is possible by two reasons:
                    // 1) we reached the end of data sequence by skiping items. This case will be handled below by taking items again.
                    // 2) the sequence is initially empty. This case should not be handled here.

                    // Again, we apply the same technique (take one more item from data sequence) to ensure that we have items after the current page.
                    sample = _executer.ToList(_configurationContext, _stepNameFactory, _query.Take(_takeCount + 1));

                    skipCanceled = true;

                    if (sample.Count == _takeCount + 1)
                    {
                        hasNextPage = true;
                        shouldRemoveLast = true;
                    }
                }
            }
            else
            {
                // 'Take' operation was not performed, so we've got all the items from the sequence till the end.
                totalCount = liveSkipCount + sample.Count;
            }

            if (sample.Count > 0)
            {
                // Remove extra items if necessary...
                if (shouldRemoveLast)
                {
                    sample.RemoveAt(sample.Count - 1);
                }

                if (_shouldSkip && !skipCanceled)
                {
                    sample.RemoveAt(0);
                    offset = _skipCount;
                }

                if (!skipCanceled && !hasNextPage && sample.Count == 0)
                {
                    offset = null;
                }
            }
            else
            {
                skipCanceled = true;

                if (_shouldSkip && !_shouldTake)
                {
                    // If there is no items after skipping (and we did not perform taking), try to materialize query again.
                    sample = _executer.ToList(_configurationContext, _stepNameFactory, _query);
                }

                if (sample.Count == 0)
                {
                    offset = null;
                }

                totalCount = sample.Count;
            }

            if (_shouldSkip && !skipCanceled)
            {
                hasPreviousPage = true;
            }

            if (_shouldTakeLast)
            {
                var removeCount = Math.Max(0, sample.Count - _takeLastCount);
                if (removeCount > 0)
                {
                    offset += removeCount;
                    sample.RemoveRange(0, removeCount);
                    hasPreviousPage = true;
                }

                if (sample.Count == 0 && !_shouldTakeBefore)
                {
                    hasPreviousPage = false;
                    offset = null;
                }
            }

            // Reset wrapper
            _skipCount = 0;
            _takeCount = 0;
            _takeLastCount = 0;
            _takeBeforeCount = 0;
            _shouldTake = false;
            _shouldSkip = false;
            _shouldTakeLast = false;
            _shouldTakeBefore = false;

            return new PaginatorResult<TSource>
            {
                StartOffset = offset,
                EndOffset = offset + Math.Max(sample.Count - 1, 0),
                HasPreviousPage = hasPreviousPage,
                HasNextPage = hasNextPage,
                Page = sample,
                TotalCount = totalCount,
            };
        }