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

com.eventsourcing.repository.QuerySubscriber Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2016, All Contributors (see CONTRIBUTORS file)
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package com.eventsourcing.repository;

import com.eventsourcing.Entity;
import com.eventsourcing.EntityHandle;
import com.eventsourcing.EntitySubscriber;
import com.eventsourcing.Repository;
import com.eventsourcing.index.IndexEngine;
import com.eventsourcing.index.IndexLoader;
import com.eventsourcing.index.MemoryIndexEngine;
import com.googlecode.cqengine.IndexedCollection;
import com.googlecode.cqengine.index.Index;
import com.googlecode.cqengine.query.Query;
import com.googlecode.cqengine.resultset.ResultSet;
import lombok.SneakyThrows;
import lombok.Value;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class QuerySubscriber implements EntitySubscriber {

    private Repository repository;

    private final Set indexLoaders = new LinkedHashSet<>();

    @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE)
    public void bindIndexLoader(IndexLoader loader) {
        indexLoaders.add(loader);
    }

    public void unbindIndexLoader(IndexLoader loader) {
        indexLoaders.remove(loader);
    }

    @Reference
    public void setRepository(Repository repository) {
        this.repository = repository;
    }

    public void unsetRepository(Repository repository) {
        this.repository = null;
    }

    public QuerySubscriber() {
    }

    public QuerySubscriber(Repository repository) {
        this.repository = repository;
    }

    @Value
    private static class QueryHolder {
        private Class klass;
        private Query> query;

        public int hashCode() {
            return query.hashCode();
        }
    }
    private Map queries = new HashMap<>();

    public  void addQuery(Class klass, Query> query,
                                            Consumer>> consumer) {
        queries.put(new QueryHolder<>(klass, query), () -> consumer.accept(query));
    }

    public  void removeQuery(Class klass, Query> query) {
        queries.remove(new QueryHolder<>(klass, query));
    }


    @SneakyThrows
    @Override public void accept(Repository repository, Stream> entityStream) {
        MemoryIndexEngine indexEngine = new MemoryIndexEngine();
        indexEngine.setJournal(repository.getJournal());
        indexEngine.setRepository(repository);

        for (Class klass : repository.getCommands()) {
            configureIndices(indexEngine, klass);
        }
        for (Class klass : repository.getEvents()) {
            configureIndices(indexEngine, klass);
        }

        indexEngine.startAsync().awaitRunning();

        entityStream.forEachOrdered(h -> {
            Entity entity = h.get();
            IndexedCollection> indexedCollection =
                    indexEngine.getIndexedCollection((Class)entity.getClass());
            indexedCollection.add(h);
        });

        //
        queries.forEach((query, runnable) -> {
            IndexedCollection collection = indexEngine.getIndexedCollection(query.getKlass());
            try (ResultSet resultSet = collection.retrieve(query.getQuery())) {
                if (resultSet.isNotEmpty()) {
                    runnable.run();
                }
            }
        });

        //
        indexEngine.stopAsync().awaitTerminated();
    }

    private void configureIndices(IndexEngine engine, Class klass) throws IndexEngine.IndexNotSupported {
        for (IndexLoader indexLoader : indexLoaders) {
            Iterable indices = indexLoader.load(engine, klass);
            for (Index i : indices) {
                IndexedCollection> collection =
                        engine.getIndexedCollection(klass);
                boolean hasIndex = StreamSupport.stream(collection.getIndexes().spliterator(), false)
                                                .anyMatch(index -> index.equals(i));
                if (!hasIndex) {
                    collection.addIndex(i);
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy