/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.geronimo.jcache.simple;

import static org.apache.geronimo.jcache.simple.Asserts.assertNotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.configuration.CacheEntryListenerConfiguration;
import javax.cache.configuration.Configuration;
import javax.cache.configuration.Factory;
import javax.cache.event.CacheEntryEvent;
import javax.cache.event.EventType;
import javax.cache.expiry.Duration;
import javax.cache.expiry.EternalExpiryPolicy;
import javax.cache.expiry.ExpiryPolicy;
import javax.cache.integration.CacheLoader;
import javax.cache.integration.CacheLoaderException;
import javax.cache.integration.CacheWriter;
import javax.cache.integration.CacheWriterException;
import javax.cache.integration.CompletionListener;
import javax.cache.processor.EntryProcessor;
import javax.cache.processor.EntryProcessorException;
import javax.cache.processor.EntryProcessorResult;
import javax.management.ObjectName;

public class SimpleCache<K, V> implements Cache<K, V> {

    private final SimpleManager manager;

    private final SimpleConfiguration<K, V> config;

    private final CacheLoader<K, V> loader;

    private final CacheWriter<? super K, ? super V> writer;

    private final ExpiryPolicy expiryPolicy;

    private final ObjectName cacheConfigObjectName;

    private final ObjectName cacheStatsObjectName;

    private final String name;

    private final ConcurrentHashMap<SimpleKey<K>, SimpleElement<V>> delegate;

    private final Map<CacheEntryListenerConfiguration<K, V>, SimpleListener<K, V>> listeners = new ConcurrentHashMap<>();

    private final Statistics statistics = new Statistics();

    private final ExecutorService pool;

    private final Serializations serializations;

    private final Collection<Future<?>> poolTasks = new CopyOnWriteArraySet<>();

    private volatile boolean closed = false;

    public SimpleCache(final ClassLoader classLoader, final SimpleManager mgr, final String cacheName,
            final SimpleConfiguration<K, V> configuration, final Properties properties,
            final ExecutorService executorService) {
        manager = mgr;

        name = cacheName;

        final int capacity = Integer.parseInt(property(properties, cacheName, "capacity", "1000"));
        final float loadFactor = Float.parseFloat(property(properties, cacheName, "loadFactor", "0.75"));
        final int concurrencyLevel = Integer.parseInt(property(properties, cacheName, "concurrencyLevel", "16"));
        delegate = new ConcurrentHashMap<>(capacity, loadFactor, concurrencyLevel);
        config = configuration;
        pool = executorService;

        final long evictionPause = Long.parseLong(
                properties.getProperty(cacheName + ".evictionPause", properties.getProperty("evictionPause", "30000")));
        if (evictionPause > 0) {
            final long maxDeleteByEvictionRun = Long.parseLong(property(properties, cacheName, "maxDeleteByEvictionRun", "100"));
            addPoolTask(new EvictionThread(evictionPause, maxDeleteByEvictionRun));
        }

        serializations = new Serializations(property(properties, cacheName, "serialization.whitelist", null));

        final Factory<CacheLoader<K, V>> cacheLoaderFactory = configuration.getCacheLoaderFactory();
        if (cacheLoaderFactory == null) {
            loader = NoLoader.INSTANCE;
        } else {
            loader = ExceptionWrapperHandler.newProxy(classLoader, cacheLoaderFactory.create(), CacheLoaderException.class,
                    CacheLoader.class);
        }

        final Factory<CacheWriter<? super K, ? super V>> cacheWriterFactory = configuration.getCacheWriterFactory();
        if (cacheWriterFactory == null) {
            writer = NoWriter.INSTANCE;
        } else {
            writer = ExceptionWrapperHandler.newProxy(classLoader, cacheWriterFactory.create(), CacheWriterException.class,
                    CacheWriter.class);
        }

        final Factory<ExpiryPolicy> expiryPolicyFactory = configuration.getExpiryPolicyFactory();
        if (expiryPolicyFactory == null) {
            expiryPolicy = new EternalExpiryPolicy();
        } else {
            expiryPolicy = expiryPolicyFactory.create();
        }

        for (final CacheEntryListenerConfiguration<K, V> listener : config.getCacheEntryListenerConfigurations()) {
            listeners.put(listener, new SimpleListener<>(listener));
        }

        statistics.setActive(config.isStatisticsEnabled());

        final String mgrStr = manager.getURI().toString().replaceAll(",|:|=|\n", ".");
        final String cacheStr = name.replaceAll(",|:|=|\n", ".");
        try {
            cacheConfigObjectName = new ObjectName(
                    "javax.cache:type=CacheConfiguration," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr);
            cacheStatsObjectName = new ObjectName(
                    "javax.cache:type=CacheStatistics," + "CacheManager=" + mgrStr + "," + "Cache=" + cacheStr);
        } catch (final Exception e) {
            throw new IllegalArgumentException(e);
        }
        if (config.isManagementEnabled()) {
            JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean<K, V>(this));
        }
        if (config.isStatisticsEnabled()) {
            JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics));
        }
    }

    private void assertNotClosed() {
        if (isClosed()) {
            throw new IllegalStateException("cache closed");
        }
    }

    @Override
    public V get(final K key) {
        assertNotClosed();
        assertNotNull(key, "key");
        final long getStart = Times.now(false);
        return doGetControllingExpiry(getStart, key, true, false, false, true, loader);
    }

    private V doLoad(final K key, final boolean update, final boolean propagateLoadException, final CacheLoader<K, V> loader) {
        V v = null;
        try {
            v = loader.load(key);
        } catch (final CacheLoaderException e) {
            if (propagateLoadException) {
                throw e;
            }
        }
        if (v != null) {
            final Duration duration = update ? expiryPolicy.getExpiryForUpdate() : expiryPolicy.getExpiryForCreation();
            if (isNotZero(duration)) {
                delegate.put(new SimpleKey<>(key), new SimpleElement<>(v, duration));
            }
        }
        return v;
    }

    private void touch(final SimpleKey<K> key, final SimpleElement<V> element) {
        if (config.isStoreByValue()) {
            delegate.put(new SimpleKey<>(serializations.copy(manager.getClassLoader(), key.getKey())), element);
        }
    }

    @Override
    public Map<K, V> getAll(final Set<? extends K> keys) {
        assertNotClosed();
        for (final K k : keys) {
            assertNotNull(k, "key");
        }

        final Map<K, V> result = new HashMap<>();
        for (final K key : keys) {
            assertNotNull(key, "key");

            final SimpleKey<K> simpleKey = new SimpleKey<>(key);
            final SimpleElement<V> elt = delegate.get(simpleKey);
            V val = elt != null ? elt.getElement() : null;
            if (val == null && config.isReadThrough()) {
                val = doLoad(key, false, false, loader);
                if (val != null) {
                    result.put(key, val);
                }
            } else if (elt != null) {
                final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
                if (isNotZero(expiryForAccess)) {
                    touch(simpleKey, elt);
                    result.put(key, val);
                } else {
                    expires(simpleKey);
                }
            }
        }
        return result;
    }

    @Override
    public boolean containsKey(final K key) {
        assertNotClosed();
        assertNotNull(key, "key");
        return delegate.get(new SimpleKey<>(key)) != null;
    }

    @Override
    public void put(final K key, final V rawValue) {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(rawValue, "value");

        final boolean storeByValue = config.isStoreByValue();
        final SimpleKey<K> simpleKey = new SimpleKey<>(storeByValue ? serializations.copy(manager.getClassLoader(), key) : key);
        final SimpleElement<V> oldElt = delegate.get(simpleKey);
        final V old = oldElt != null ? oldElt.getElement() : null;
        final V value = storeByValue ? serializations.copy(manager.getClassLoader(), rawValue) : rawValue;

        final boolean created = old == null;
        final Duration duration = created ? expiryPolicy.getExpiryForCreation() : expiryPolicy.getExpiryForUpdate();
        if (isNotZero(duration)) {
            final boolean statisticsEnabled = config.isStatisticsEnabled();
            final long start = Times.now(false);

            writer.write(new SimpleEntry<>(key, value));
            delegate.put(simpleKey, new SimpleElement<>(value, duration));
            if (!listeners.isEmpty()) {
                for (final SimpleListener<K, V> listener : listeners.values()) {
                    if (created) {
                        listener.onCreated(Collections.<CacheEntryEvent<? extends K, ? extends V>> singletonList(
                                new SimpleEvent<>(this, EventType.CREATED, null, key, value)));
                    } else
                        listener.onUpdated(Collections.<CacheEntryEvent<? extends K, ? extends V>> singletonList(
                                new SimpleEvent<>(this, EventType.UPDATED, old, key, value)));
                }
            }

            if (statisticsEnabled) {
                statistics.increasePuts(1);
                statistics.addPutTime(Times.now(false) - start);
            }
        } else {
            if (!created) {
                expires(simpleKey);
            }
        }
    }

    private void expires(final SimpleKey<K> cacheKey) {
        final SimpleElement<V> elt = delegate.get(cacheKey);
        delegate.remove(cacheKey);
        onExpired(cacheKey, elt);
    }

    private void onExpired(final SimpleKey<K> cacheKey, final SimpleElement<V> elt) {
        for (final SimpleListener<K, V> listener : listeners.values()) {
            listener.onExpired(Collections.<CacheEntryEvent<? extends K, ? extends V>> singletonList(
                    new SimpleEvent<>(this, EventType.REMOVED, null, cacheKey.getKey(), elt.getElement())));
        }
    }

    @Override
    public V getAndPut(final K key, final V value) {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(value, "value");
        final long getStart = Times.now(false);
        final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader);
        put(key, value);
        return v;
    }

    @Override
    public void putAll(final Map<? extends K, ? extends V> map) {
        assertNotClosed();
        final TempStateCacheView<K, V> view = new TempStateCacheView<K, V>(this);
        for (final Map.Entry<? extends K, ? extends V> e : map.entrySet()) {
            view.put(e.getKey(), e.getValue());
        }
        view.merge();
    }

    @Override
    public boolean putIfAbsent(final K key, final V value) {
        final boolean statisticsEnabled = config.isStatisticsEnabled();
        if (!containsKey(key)) {
            if (statisticsEnabled) {
                statistics.increaseMisses(1);
            }
            put(key, value);
            return true;
        } else {
            if (statisticsEnabled) {
                statistics.increaseHits(1);
            }
        }
        return false;
    }

    @Override
    public boolean remove(final K key) {
        assertNotClosed();
        assertNotNull(key, "key");

        final boolean statisticsEnabled = config.isStatisticsEnabled();
        final long start = Times.now(!statisticsEnabled);

        writer.delete(key);
        final SimpleKey<K> cacheKey = new SimpleKey<>(key);

        final SimpleElement<V> v = delegate.remove(cacheKey);
        if (v == null || v.isExpired()) {
            return false;
        }

        final V value = v.getElement();
        for (final SimpleListener<K, V> listener : listeners.values()) {
            listener.onRemoved(Collections.<CacheEntryEvent<? extends K, ? extends V>> singletonList(
                    new SimpleEvent<>(this, EventType.REMOVED, value, key, value)));
        }
        if (statisticsEnabled) {
            statistics.increaseRemovals(1);
            statistics.addRemoveTime(Times.now(false) - start);
        }

        return true;
    }

    @Override
    public boolean remove(final K key, final V oldValue) {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(oldValue, "oldValue");
        final long getStart = Times.now(false);
        final V v = doGetControllingExpiry(getStart, key, false, false, false, false, loader);
        if (oldValue.equals(v)) {
            remove(key);
            return true;
        } else if (v != null) {
            // weird but just for stats to be right
            // (org.jsr107.tck.expiry.CacheExpiryTest.removeSpecifiedEntryShouldNotCallExpiryPolicyMethods())
            expiryPolicy.getExpiryForAccess();
        }
        return false;
    }

    @Override
    public V getAndRemove(final K key) {
        assertNotClosed();
        assertNotNull(key, "key");
        final long getStart = Times.now(false);
        final V v = doGetControllingExpiry(getStart, key, false, false, true, false, loader);
        remove(key);
        return v;
    }

    private V doGetControllingExpiry(final long getStart, final K key, final boolean updateAcess, final boolean forceDoLoad,
            final boolean skipLoad, final boolean propagateLoadException, final CacheLoader<K, V> loader) {
        final boolean statisticsEnabled = config.isStatisticsEnabled();
        final SimpleKey<K> simpleKey = new SimpleKey<>(key);
        final SimpleElement<V> elt = delegate.get(simpleKey);
        V v = elt != null ? elt.getElement() : null;
        if (v == null && (config.isReadThrough() || forceDoLoad)) {
            if (!skipLoad) {
                v = doLoad(key, false, propagateLoadException, loader);
            }
        } else if (statisticsEnabled) {
            if (v != null) {
                statistics.increaseHits(1);
            } else {
                statistics.increaseMisses(1);
            }
        }

        if (updateAcess && elt != null) {
            final Duration expiryForAccess = expiryPolicy.getExpiryForAccess();
            if (!isNotZero(expiryForAccess)) {
                expires(simpleKey);
            }
        }
        if (statisticsEnabled && v != null) {
            statistics.addGetTime(Times.now(false) - getStart);
        }
        return v;
    }

    @Override
    public boolean replace(final K key, final V oldValue, final V newValue) {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(oldValue, "oldValue");
        assertNotNull(newValue, "newValue");
        final V value = doGetControllingExpiry(Times.now(config.isStatisticsEnabled()), key, false, config.isReadThrough(), false,
                true, loader);
        if (value != null && value.equals(oldValue)) {
            put(key, newValue);
            return true;
        } else if (value != null) {
            expiryPolicy.getExpiryForAccess();
        }
        return false;
    }

    @Override
    public boolean replace(final K key, final V value) {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(value, "value");
        boolean statisticsEnabled = config.isStatisticsEnabled();
        if (containsKey(key)) {
            if (statisticsEnabled) {
                statistics.increaseHits(1);
            }
            put(key, value);
            return true;
        } else if (statisticsEnabled) {
            statistics.increaseMisses(1);
        }
        return false;
    }

    @Override
    public V getAndReplace(final K key, final V value) {
        assertNotClosed();
        assertNotNull(key, "key");
        assertNotNull(value, "value");

        final boolean statisticsEnabled = config.isStatisticsEnabled();

        final SimpleElement<V> elt = delegate.get(new SimpleKey<>(key));
        if (elt != null) {
            V oldValue = elt.getElement();
            if (oldValue == null && config.isReadThrough()) {
                oldValue = doLoad(key, false, false, loader);
            } else if (statisticsEnabled) {
                statistics.increaseHits(1);
            }
            put(key, value);
            return oldValue;
        } else if (statisticsEnabled) {
            statistics.increaseMisses(1);
        }
        return null;
    }

    @Override
    public void removeAll(final Set<? extends K> keys) {
        assertNotClosed();
        assertNotNull(keys, "keys");
        for (final K k : keys) {
            remove(k);
        }
    }

    @Override
    public void removeAll() {
        assertNotClosed();
        for (final SimpleKey<K> k : delegate.keySet()) {
            remove(k.getKey());
        }
    }

    @Override
    public void clear() {
        assertNotClosed();
        delegate.clear();
    }

    @Override
    public <C2 extends Configuration<K, V>> C2 getConfiguration(final Class<C2> clazz) {
        assertNotClosed();
        return clazz.cast(config);
    }

    @Override
    public void loadAll(final Set<? extends K> keys, final boolean replaceExistingValues,
            final CompletionListener completionListener) {
        assertNotClosed();
        assertNotNull(keys, "keys");
        if (loader == null) { // quick exit path
            if (completionListener != null) {
                completionListener.onCompletion();
            }
            return;
        }
        for (final K k : keys) {
            assertNotNull(k, "a key");
        }
        addPoolTask(new Runnable() {

            @Override
            public void run() {
                doLoadAll(keys, replaceExistingValues, completionListener);
            }
        });
    }

    private void addPoolTask(final Runnable runnable) {
        final AtomicReference<Future<?>> ref = new AtomicReference<>();
        final CountDownLatch refIsSet = new CountDownLatch(1);
        ref.set(pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {
                    try {
                        refIsSet.await();
                    } catch (final InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    poolTasks.remove(ref.get());
                }
            }
        }));
        refIsSet.countDown();
        poolTasks.add(ref.get());
    }

    private void doLoadAll(final Set<? extends K> keys, final boolean replaceExistingValues,
            final CompletionListener completionListener) {
        try {
            final long now = Times.now(false);
            final Map<K, V> kvMap = loader.loadAll(keys);
            if (kvMap == null) {
                return;
            }
            final CacheLoader<K, V> preloaded = new MapLoader<>(kvMap);
            for (final K k : keys) {
                if (replaceExistingValues) {
                    doLoad(k, containsKey(k), completionListener != null, preloaded);
                } else if (!containsKey(k)) {
                    doGetControllingExpiry(now, k, true, true, false, completionListener != null, preloaded);
                }
            }
        } catch (final RuntimeException e) {
            if (completionListener != null) {
                completionListener.onException(e);
                return;
            }
        }
        if (completionListener != null) {
            completionListener.onCompletion();
        }
    }

    @Override
    public <T> T invoke(final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments)
            throws EntryProcessorException {
        final TempStateCacheView<K, V> view = new TempStateCacheView<K, V>(this);
        final T t = doInvoke(view, key, entryProcessor, arguments);
        view.merge();
        return t;
    }

    private <T> T doInvoke(final TempStateCacheView<K, V> view, final K key, final EntryProcessor<K, V, T> entryProcessor,
            final Object... arguments) {
        assertNotClosed();
        assertNotNull(entryProcessor, "entryProcessor");
        assertNotNull(key, "key");
        try {
            if (config.isStatisticsEnabled()) {
                if (containsKey(key)) {
                    statistics.increaseHits(1);
                } else {
                    statistics.increaseMisses(1);
                }
            }
            return entryProcessor.process(new SimpleMutableEntry<>(view, key), arguments);
        } catch (final Exception ex) {
            return throwEntryProcessorException(ex);
        }
    }

    @Override
    public <T> Map<K, EntryProcessorResult<T>> invokeAll(final Set<? extends K> keys,
            final EntryProcessor<K, V, T> entryProcessor, final Object... arguments) {
        assertNotClosed();
        assertNotNull(entryProcessor, "entryProcessor");
        final Map<K, EntryProcessorResult<T>> results = new HashMap<>();
        for (final K k : keys) {
            try {
                final T invoke = invoke(k, entryProcessor, arguments);
                if (invoke != null) {
                    results.put(k, new EntryProcessorResult<T>() {

                        @Override
                        public T get() throws EntryProcessorException {
                            return invoke;
                        }
                    });
                }
            } catch (final Exception e) {
                results.put(k, new EntryProcessorResult<T>() {

                    @Override
                    public T get() throws EntryProcessorException {
                        return throwEntryProcessorException(e);
                    }
                });
            }
        }
        return results;
    }

    @Override
    public void registerCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) {
        assertNotClosed();
        if (listeners.containsKey(cacheEntryListenerConfiguration)) {
            throw new IllegalArgumentException(cacheEntryListenerConfiguration + " already registered");
        }
        listeners.put(cacheEntryListenerConfiguration, new SimpleListener<>(cacheEntryListenerConfiguration));
        config.addListener(cacheEntryListenerConfiguration);
    }

    @Override
    public void deregisterCacheEntryListener(final CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) {
        assertNotClosed();
        listeners.remove(cacheEntryListenerConfiguration);
        config.removeListener(cacheEntryListenerConfiguration);
    }

    @Override
    public Iterator<Entry<K, V>> iterator() {
        assertNotClosed();
        final Iterator<SimpleKey<K>> keys = new HashSet<>(delegate.keySet()).iterator();
        return new Iterator<Entry<K, V>>() {

            private K lastKey = null;

            @Override
            public boolean hasNext() {
                return keys.hasNext();
            }

            @Override
            public Entry<K, V> next() {
                lastKey = keys.next().getKey();
                return new SimpleEntry<>(lastKey, get(lastKey));
            }

            @Override
            public void remove() {
                if (isClosed() || lastKey == null) {
                    throw new IllegalStateException(isClosed() ? "cache closed" : "call next() before remove()");
                }
                SimpleCache.this.remove(lastKey);
            }
        };
    }

    @Override
    public String getName() {
        assertNotClosed();
        return name;
    }

    @Override
    public CacheManager getCacheManager() {
        assertNotClosed();
        return manager;
    }

    @Override
    public synchronized void close() {
        if (isClosed()) {
            return;
        }

        for (final Future<?> task : poolTasks) {
            task.cancel(true);
        }

        final CacheException ce = new CacheException();
        manager.release(getName());
        closed = true;
        close(loader, ce);
        close(writer, ce);
        close(expiryPolicy, ce);
        for (final SimpleListener<K, V> listener : listeners.values()) {
            try {
                listener.close();
            } catch (final Exception e) {
                ce.addSuppressed(e);
            }
        }
        listeners.clear();
        JMXs.unregister(cacheConfigObjectName);
        JMXs.unregister(cacheStatsObjectName);
        delegate.clear();
        if (ce.getSuppressed().length > 0) {
            throw ce;
        }
    }

    @Override
    public boolean isClosed() {
        return closed;
    }

    @Override
    public <T> T unwrap(final Class<T> clazz) {
        assertNotClosed();
        if (clazz.isInstance(this)) {
            return clazz.cast(this);
        }
        if (clazz.isAssignableFrom(Map.class) || clazz.isAssignableFrom(ConcurrentMap.class)) {
            return clazz.cast(delegate);
        }
        throw new IllegalArgumentException(clazz.getName() + " not supported in unwrap");
    }

    public Statistics getStatistics() {
        return statistics;
    }

    public void enableManagement() {
        config.managementEnabled();
        JMXs.register(cacheConfigObjectName, new SimpleCacheMXBean<K, V>(this));
    }

    public void disableManagement() {
        config.managementDisabled();
        JMXs.unregister(cacheConfigObjectName);
    }

    public void enableStatistics() {
        config.statisticsEnabled();
        statistics.setActive(true);
        JMXs.register(cacheStatsObjectName, new SimpleCacheStatisticsMXBean(statistics));
    }

    public void disableStatistics() {
        config.statisticsDisabled();
        statistics.setActive(false);
        JMXs.unregister(cacheStatsObjectName);
    }

    private static String property(final Properties properties, final String cacheName, final String name,
            final String defaultValue) {
        return properties.getProperty(cacheName + "." + name, properties.getProperty(name, defaultValue));
    }

    private static boolean isNotZero(final Duration duration) {
        return duration == null || !duration.isZero();
    }

    private static <T> T throwEntryProcessorException(final Exception ex) {
        if (EntryProcessorException.class.isInstance(ex)) {
            throw EntryProcessorException.class.cast(ex);
        }
        throw new EntryProcessorException(ex);
    }

    private static void close(final Object potentiallyCloseable, final CacheException wrapper) {
        if (AutoCloseable.class.isInstance(potentiallyCloseable)) {
            try {
                AutoCloseable.class.cast(potentiallyCloseable).close();
            } catch (final Exception re) {
                wrapper.addSuppressed(re);
            }
        }
    }

    private class EvictionThread implements Runnable {

        private final long pause;

        private final long maxDelete;

        private EvictionThread(final long evictionPause, final long maxDelete) {
            this.pause = evictionPause;
            this.maxDelete = maxDelete;
        }

        @Override
        public void run() {
            while (!isClosed()) {
                try {
                    Thread.sleep(pause);
                } catch (final InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
                if (delegate.isEmpty()) {
                    continue;
                }

                try {
                    final List<SimpleKey<K>> keys = new ArrayList<>(delegate.keySet());
                    Collections.sort(keys, new Comparator<SimpleKey<K>>() {

                        @Override
                        public int compare(final SimpleKey<K> o1, final SimpleKey<K> o2) {
                            final long l = o1.lastAccess() - o2.lastAccess();
                            if (l == 0) {
                                return keys.indexOf(o1) - keys.indexOf(o2);
                            }
                            return (int) l;
                        }
                    });

                    int delete = 0;
                    for (final SimpleKey<K> key : keys) {
                        final SimpleElement<V> elt = delegate.get(key);
                        if (elt != null && elt.isExpired()) {
                            delegate.remove(key);
                            statistics.increaseEvictions(1);
                            onExpired(key, elt);
                            delete++;
                            if (delete >= maxDelete) {
                                break;
                            }
                        }
                    }
                } catch (final Exception e) {
                    // no-op
                }
            }
        }
    }

    private static class MapLoader<K, V> implements CacheLoader<K, V> {

        private final Map<K, V> loaded;

        private MapLoader(final Map<K, V> loaded) {
            this.loaded = loaded;
        }

        @Override
        public V load(final K key) throws CacheLoaderException {
            return loaded.get(key);
        }

        @Override
        public Map<K, V> loadAll(final Iterable<? extends K> keys) throws CacheLoaderException {
            throw new UnsupportedOperationException();
        }
    }
}
