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

tech.ydb.yoj.repository.db.cache.FirstLevelCache Maven / Gradle / Ivy

Go to download

Core YOJ (YDB ORM for Java) abstractions and APIs for domain entities, repositories, transactions etc.

There is a newer version: 2.6.1
Show newest version
package tech.ydb.yoj.repository.db.cache;

import com.google.common.collect.Maps;
import lombok.NonNull;
import tech.ydb.yoj.repository.db.Entity;

import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;


public interface FirstLevelCache {
    > E get(@NonNull Entity.Id id, @NonNull Function, E> loader);

    > Optional peek(@NonNull Entity.Id id);

    /**
     * Returns a immutable copy of the entities of {@code entityType} type that are in the
     * transaction L1 cache.
     */
    > List snapshot(@NonNull Class entityType);

    /**
     * Returns a unmodifiable map containing the entities of {@code entityType} type that are in the
     * transaction L1 cache. The returned map is a unmodifiable live view of transaction L1 cache;
     * changes to second affect the first. To avoid an {@link ConcurrentModificationException} exception
     * when iterating and simultaneous modification of the transaction L1 cache, you may need to make a copy.
     */
    > Map, E> entities(@NonNull Class entityType);

    > void put(@NonNull E e);

    > void putEmpty(@NonNull Entity.Id id);

    > boolean containsKey(@NonNull Entity.Id id);

    static FirstLevelCache empty() {
        return new FirstLevelCache() {
            @Override
            public > E get(@NonNull Entity.Id id, Function, E> loader) {
                return loader.apply(id);
            }

            @Override
            public > Optional peek(@NonNull Entity.Id id) {
                throw new NoSuchElementException();
            }

            @Override
            public > List snapshot(@NonNull Class entityType) {
                return List.of();
            }

            @Override
            public > Map, E> entities(@NonNull Class entityType) {
                return Map.of();
            }

            @Override
            public > void put(@NonNull E e) {
            }

            @Override
            public > void putEmpty(@NonNull Entity.Id id) {
            }

            @Override
            public > boolean containsKey(Entity.@NonNull Id id) {
                return false;
            }
        };
    }

    static FirstLevelCache create() {
        class EntityCache> extends HashMap, Optional> {
        }

        return new FirstLevelCache() {
            private final EntityCache entityCache = new EntityCache<>();

            @SuppressWarnings("unchecked")
            private > EntityCache getEntityCache() {
                return (EntityCache) entityCache;
            }

            @Override
            public > Optional peek(@NonNull Entity.Id id) {
                EntityCache cache = getEntityCache();
                if (cache.containsKey(id)) {
                    return cache.get(id);
                }
                throw new NoSuchElementException();
            }

            @Override
            public > E get(@NonNull Entity.Id id, @NonNull Function, E> loader) {
                EntityCache cache = getEntityCache();
                if (cache.containsKey(id)) {
                    return cache.get(id).orElse(null);
                }

                E entity = loader.apply(id);
                cache.put(id, Optional.ofNullable(entity));

                return entity;
            }

            @Override
            public > List snapshot(@NonNull Class entityType) {
                EntityCache cache = getEntityCache();
                return cache.values().stream()
                        .flatMap(Optional::stream)
                        .filter(v -> entityType.equals(v.getId().getType()))
                        .collect(Collectors.toUnmodifiableList());
            }

            @Override
            public > Map, E> entities(@NonNull Class entityType) {
                EntityCache cache = getEntityCache();
                return Collections.unmodifiableMap(Maps.transformValues(
                        Maps.filterEntries(cache, e -> entityType.equals(e.getKey().getType()) && e.getValue().isPresent()),
                        Optional::get
                ));
            }

            @Override
            public > void put(@NonNull E e) {
                EntityCache cache = getEntityCache();
                cache.put(e.getId(), Optional.of(e));
            }

            @Override
            public > void putEmpty(@NonNull Entity.Id id) {
                EntityCache cache = getEntityCache();
                cache.put(id, Optional.empty());
            }

            @Override
            public > boolean containsKey(Entity.@NonNull Id id) {
                return getEntityCache().containsKey(id);
            }
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy