/** * 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.commands; import com.eventsourcing.*; import com.eventsourcing.layout.Layout; import com.eventsourcing.layout.LayoutConstructor; import com.eventsourcing.migrations.events.EntityLayoutIntroduced; import com.googlecode.cqengine.query.Query; import com.googlecode.cqengine.resultset.ResultSet; import lombok.SneakyThrows; import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static com.eventsourcing.queries.QueryFactory.equal; public class IntroduceEntityLayouts extends StandardCommand<Lock, Void> { private Iterable<Class<? extends Entity>> entities; @LayoutConstructor public IntroduceEntityLayouts() {} public IntroduceEntityLayouts(Iterable<Class<? extends Entity>> entities) {this.entities = entities;} @Override public EventStream<Lock> events(Repository repository, LockProvider lockProvider) throws Exception { Lock lock = lockProvider.lock(getClass().getName()); Stream<Class<? extends Entity>> stream = StreamSupport .stream(Spliterators.spliteratorUnknownSize(entities.iterator(), Spliterator.IMMUTABLE), false); return EventStream.ofWithState(lock, stream.flatMap(new EntityStreamFunction(repository))); } @Override public Void result(Lock lock) { lock.unlock(); return null; } private static class EntityStreamFunction implements Function<Class<? extends Entity>, Stream<Event>> { private final Repository repository; public EntityStreamFunction(Repository repository) {this.repository = repository;} @SneakyThrows @Override public Stream<Event> apply(Class<? extends Entity> entity) { Layout<? extends Entity> layout = Layout.forClass(entity); byte[] fingerprint = layout.getHash(); Query<EntityHandle<EntityLayoutIntroduced>> query = equal(EntityLayoutIntroduced.FINGERPRINT, fingerprint); try (ResultSet<EntityHandle<EntityLayoutIntroduced>> resultSet = repository .query(EntityLayoutIntroduced.class, query)) { if (resultSet.isEmpty()) { return Stream.of(new EntityLayoutIntroduced(fingerprint, Optional.of(layout))); } else { return Stream.empty(); } } } } }