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

com.eventsourcing.queries.ModelCollectionQuery Maven / Gradle / Ivy

There is a newer version: 0.4.6
Show 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.queries;

import com.eventsourcing.Model;
import com.eventsourcing.Repository;

import java.util.*;
import java.util.stream.BaseStream;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * A toolkit for composing model collections queries. An implementation of this interface
 * can be passed to {@link #query(Repository, ModelCollectionQuery)} to retrieve a collection
 * of matching model instances.
 *
 * Following logical operator functions can be used to compose a query:
 *
 * 
    *
  • {@link LogicalOperators#or(Collection)}
  • *
  • {@link LogicalOperators#and(Collection)}
  • *
* * @param */ public interface ModelCollectionQuery { Stream getCollectionStream(Repository repository); static Collection query(Repository repository, ModelCollectionQuery query) { try (Stream collectionStream = query.getCollectionStream(repository)) { return collectionStream.collect(Collectors.toList()); } } final class LogicalOperators { public static ModelCollectionQuery or(Collection> queries) { return new Or<>(queries); } public static ModelCollectionQuery or(ModelCollectionQuery... queries) { return new Or<>(queries); } public static class Or implements ModelCollectionQuery { private final Collection> queries; public Or(Collection> queries) { this.queries = queries; } public Or(ModelCollectionQuery... queries) { this.queries = Arrays.asList(queries); } @Override public Stream getCollectionStream(Repository repository) { Stream stream = Stream.empty(); List> streams = new ArrayList<>(); Set seen = new HashSet<>(); for (ModelCollectionQuery query : queries) { Stream queryStream = query.getCollectionStream(repository) .filter(m -> !seen.contains(m.getId())) .map(m -> { seen.add(m.getId()); return m; }); streams.add(queryStream); stream = Stream.concat(stream, queryStream); } return stream.onClose(() -> { streams.forEach(BaseStream::close); }); } } public static ModelCollectionQuery and(Collection> queries) { return new And<>(queries); } public static ModelCollectionQuery and(ModelCollectionQuery... queries) { return new And<>(queries); } public static class And implements ModelCollectionQuery { private final Collection> queries; public And(Collection> queries) { this.queries = queries; } public And(ModelCollectionQuery... queries) { this.queries = Arrays.asList(queries); } @Override public Stream getCollectionStream(Repository repository) { Iterator> iterator = queries.iterator(); if (iterator.hasNext()) { ModelCollectionQuery first = iterator.next(); Stream firstStream = first.getCollectionStream(repository); List realizedStream = firstStream.collect(Collectors.toList()); Set set = realizedStream.stream() .map(Model::getId).collect(Collectors.toSet()); Set seen = new HashSet<>(); firstStream.close(); List> allQueries = new ArrayList<>(); iterator.forEachRemaining(allQueries::add); Stream stream = Stream.empty(); List> streams = new ArrayList<>(); for (ModelCollectionQuery query : allQueries) { Stream queryStream = query.getCollectionStream(repository) .filter(m -> set.contains(m.getId()) && !seen.contains(m.getId())) .map(m -> { seen.add(m.getId()); return m; }); streams.add(queryStream); stream = Stream.concat(stream, queryStream); } stream = Stream.concat(realizedStream.stream().filter(m -> seen.contains(m.getId())), stream); return stream.onClose(() -> streams.forEach(BaseStream::close)); } else { return Stream.empty(); } } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy