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

org.javers.repository.jql.ShadowStreamQueryRunner Maven / Gradle / Ivy

There is a newer version: 7.6.2
Show newest version
package org.javers.repository.jql;

import org.javers.common.collections.Pair;
import org.javers.common.exception.JaversException;
import org.javers.common.exception.JaversExceptionCode;
import org.javers.common.validation.Validate;
import org.javers.core.metamodel.object.CdoSnapshot;
import org.javers.shadow.Shadow;

import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Spliterator.*;

class ShadowStreamQueryRunner {
    private final ShadowQueryRunner shadowQueryRunner;

    ShadowStreamQueryRunner(ShadowQueryRunner shadowQueryRunner) {
        this.shadowQueryRunner = shadowQueryRunner;
    }

    Stream queryForShadowsStream(JqlQuery query) {

        if (query.getQueryParams().skip() > 0) {
            throw new JaversException(JaversExceptionCode.MALFORMED_JQL, "skip can't be set on a JqlStreamQuery. Use Stream.skip() on a resulting Stream.");
        }

        int characteristics = IMMUTABLE | ORDERED;
        StreamQuery streamQuery = new StreamQuery(query);
        Spliterator spliterator = Spliterators
                .spliteratorUnknownSize(streamQuery.lazyIterator(), characteristics);

        Stream stream = StreamSupport.stream(spliterator, false);

        return stream;
    }

    class StreamQuery {
        private JqlQuery awaitingQuery;
        private final List queries = new ArrayList<>();
        private final List filledGapsSnapshots = new ArrayList<>();

        StreamQuery(JqlQuery initialQuery) {
            Validate.argumentIsNotNull(initialQuery);
            this.awaitingQuery = initialQuery;
        }

        List loadNextPage() {
            JqlQuery currentQuery = awaitingQuery;

            Pair, List> result =
                    shadowQueryRunner.queryForShadows(currentQuery, filledGapsSnapshots);

            queries.add(currentQuery);
            queries.get(0).appendNextStatsForStream(currentQuery.stats());
            filledGapsSnapshots.addAll(result.right());

            awaitingQuery = currentQuery.nextQueryForStream();

            return result.left();
        }

        Iterator lazyIterator() {
            return new LazyIterator();
        }

        class LazyIterator implements Iterator {
            private boolean terminated = false;
            private List loadedShadows = new ArrayList<>();
            private int nextIdx = 0;

            @Override
            public boolean hasNext() {
                if (terminated) {
                    return false;
                }

                if (shouldLoadNextPage()) {
                    List nextPage = loadNextPage();

                    if (nextPage.size() == 0) {
                        terminate();
                        return false;
                    } else {
                        loadedShadows.addAll(nextPage);
                    }
                }

                return !terminated;
            }

            private void terminate() {
                loadedShadows.clear();
                terminated = true;
            }

            private boolean shouldLoadNextPage() {
                return nextIdx >= loadedShadows.size();
            }

            @Override
            public Shadow next() {
                if (terminated) {
                    throw new IllegalStateException("attempt to read from the terminated iterator");
                }

                Shadow result = loadedShadows.get(nextIdx);
                nextIdx++;
                return result;
            }
        }
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy