InMemoryMessageListStore.java

package net.morimekta.providence.storage;

import net.morimekta.providence.PMessage;
import net.morimekta.providence.descriptor.PField;
import net.morimekta.util.collect.UnmodifiableList;
import net.morimekta.util.concurrent.ReadWriteMutex;
import net.morimekta.util.concurrent.ReentrantReadWriteMutex;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * Simple in-memory storage of lists providence messages. Uses a local hash map for
 * storing the instances.The store is thread safe through using reentrand
 * read-write mutex handling, so reading can happen in parallel.
 *
 * @param <K> The key type.
 * @param <M> The stored message type.
 */
public class InMemoryMessageListStore<K, M extends PMessage<M>> implements MessageListStore<K,M> {
    private final Map<K, List<M>> map;
    private final ReadWriteMutex  mutex;

    public InMemoryMessageListStore() {
        map   = new HashMap<>();
        mutex = new ReentrantReadWriteMutex();
    }

    @Nonnull
    @Override
    public Map<K, List<M>> getAll(@Nonnull Collection<K> keys) {
        return mutex.lockForReading(() -> {
            Map<K, List<M>> out = new HashMap<>();
            for (K key : keys) {
                if (map.containsKey(key)) {
                    out.put(key, map.get(key));
                }
            }
            return out;
        });
    }

    @Override
    public boolean containsKey(@Nonnull K key) {
        return mutex.lockForReading(() -> map.containsKey(key));
    }

    @Override @Nonnull
    public Collection<K> keys() {
        return mutex.lockForReading(() -> new HashSet<>(map.keySet()));
    }

    @Override
    public int size() {
        return mutex.lockForReading(map::size);
    }

    @Override
    public void putAll(@Nonnull Map<K, List<M>> values) {
        mutex.lockForWriting(() -> {
            for (Map.Entry<K,List<M>> entry : values.entrySet()) {
                map.put(entry.getKey(), UnmodifiableList.copyOf(entry.getValue()));
            }
        });
    }

    @Override
    public void removeAll(Collection<K> keys) {
        mutex.lockForWriting(() -> map.keySet().removeAll(keys));
    }
}