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

com.eventsourcing.inmem.MemoryJournal 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.inmem;

import com.eventsourcing.*;
import com.eventsourcing.layout.ObjectDeserializer;
import com.eventsourcing.layout.ObjectSerializer;
import com.eventsourcing.layout.Serialization;
import com.eventsourcing.layout.binary.BinarySerialization;
import com.eventsourcing.utils.CloseableWrappingIterator;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.AbstractService;
import com.googlecode.cqengine.index.support.CloseableIterator;
import lombok.Getter;
import lombok.Setter;
import org.osgi.service.component.annotations.Component;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Memory-based {@link Journal} implementation. Not meant to be used in production.
 */
@Component(property = {"type=MemoryJournal"}, service = Journal.class)
public class MemoryJournal extends AbstractService implements Journal {

    private static final Serialization serialization = BinarySerialization.getInstance();

    @Getter @Setter
    private Repository repository;

    private Map commands = new ConcurrentHashMap<>();
    private Map events = new ConcurrentHashMap<>();

    @Override
    protected void doStart() {
        if (repository == null) {
            notifyFailed(new IllegalStateException("repository == null"));
        }
        notifyStarted();
    }

    @Override
    protected void doStop() {
        notifyStopped();
    }

    static class Transaction implements Journal.Transaction {
        private final Map events = new HashMap<>();
        @Setter
        private Command command;
        private final MemoryJournal journal;

        Transaction(MemoryJournal journal) {this.journal = journal;}

        @Override public void rollback() {
        }

        @Override public void commit() {
            journal.events.putAll(events);
            journal.commands.put(command.uuid(), command);
        }
    }

    @Override public  Command journal(Journal.Transaction tx, Command command) {
        ObjectSerializer serializer = serialization.getSerializer(command.getClass());
        ObjectDeserializer deserializer = serialization.getDeserializer(command.getClass());

        ByteBuffer buffer = serializer.serialize(command);
        buffer.rewind();
        Command command1 = deserializer.deserialize(buffer);
        command1.uuid(command.uuid());

        ((Transaction) tx).setCommand(command1);

        return command1;
    }

    @Override public Event journal(Journal.Transaction tx, Event event) {
        ObjectSerializer serializer = serialization.getSerializer(event.getClass());
        ObjectDeserializer deserializer = serialization.getDeserializer(event.getClass());

        ByteBuffer buffer = serializer.serialize(event);
        buffer.rewind();
        Event event1 = deserializer.deserialize(buffer);
        event1.uuid(event.uuid());

        ((Transaction) tx).events.put(event1.uuid(), event1);

        return event1;
    }

    @Override public Journal.Transaction beginTransaction() {
        return new Transaction(this);
    }

    @Override @SuppressWarnings("unchecked")
    public  Optional get(UUID uuid) {
        if (commands.containsKey(uuid)) {
            return Optional.of((T) commands.get(uuid));
        }
        if (events.containsKey(uuid)) {
            return Optional.of((T) events.get(uuid));
        }
        return Optional.empty();
    }

    @Override
    public > CloseableIterator> commandIterator(Class klass) {
        return new CloseableWrappingIterator<>(commands.values().stream()
                                                       .filter(command -> klass.isAssignableFrom(command.getClass()))
                                                       .map(command -> (EntityHandle) new JournalEntityHandle(
                                                               this, command.uuid())).iterator());
    }

    @Override
    public  CloseableIterator> eventIterator(Class klass) {
        return new CloseableWrappingIterator<>(events.values().stream()
                                                     .filter(event -> klass.isAssignableFrom(event.getClass()))
                                                     .map(event -> (EntityHandle) new JournalEntityHandle(this,
                                                                                                                event.uuid()))
                                                     .iterator());
    }

    @Override
    public void clear() {
        events.clear();
        commands.clear();
    }

    @Override @SuppressWarnings("unchecked")
    public  long size(Class klass) {
        if (Event.class.isAssignableFrom(klass)) {
            return Iterators.size(eventIterator((Class) klass));
        }
        if (Command.class.isAssignableFrom(klass)) {
            return Iterators.size(commandIterator((Class>) klass));
        }
        return 0;
    }

    @Override @SuppressWarnings("unchecked")
    public  boolean isEmpty(Class klass) {
        if (Event.class.isAssignableFrom(klass)) {
            return !eventIterator((Class) klass).hasNext();
        }
        if (Command.class.isAssignableFrom(klass)) {
            return !commandIterator((Class>) klass).hasNext();
        }
        return true;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy