/*
 * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//      Marcel Valovy - initial API and implementation
package org.eclipse.persistence.internal.cache;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * Memoizer for computing resource expensive tasks asynchronously &amp; concurrently.
 *
 * Inspired by D. Lea. <i>JCiP</i>, 2nd edition. Addison-Wesley, 2006. pp.109
 *
 * @author Marcel Valovy - marcelv3612@gmail.com
 * @since 2.6
 */
public class Memoizer<A, V> implements LowLevelProcessor<A, V> {

    private final ConcurrentMap<MemoizerKey, Future<V>> cache = new ConcurrentHashMap<>();
    private final KeyStorage keyStorage = new KeyStorage();

    @Override
    public V compute(final ComputableTask<A, V> c, final A taskArg) throws InterruptedException {
        final MemoizerKey key = keyStorage.get(c, taskArg);
        while (true) {
            Future<V> f = cache.get(key);
            if (f == null) {
                Callable<V> evaluation = new Callable<V>() {
                    @Override
                    public V call() throws InterruptedException {
                        return c.compute(taskArg);
                    }
                };
                FutureTask<V> ft = new FutureTask<>(evaluation);
                f = cache.putIfAbsent(key, ft);
                if (f == null) {
                    f = ft;
                    ft.run();
                }
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                /*
                 *  "Caching a Future instead of a value creates the possibility of cache pollution: if a computation
                 *  is cancelled or fails, future attempts to compute the results will also indicate cancellation or
                 *  failure. To avoid this, Memoizer removes the Future from the cache if it detects that the
                 *  computation was cancelled."
                 */
                cache.remove(key, f);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Forgets result of the specified task.
     * This allows to manually control size of internal cache.
     *
     * @param task computable task, forming part of result key
     * @param key argument of computation
     */
    public void forget(ComputableTask<A, V> task, A key) {
        cache.remove(this.new MemoizerKey(task, key));
    }

    /**
     * Forgets all cached results.
     */
    public void forgetAll() {
        cache.clear();
    }

    /**
     * Composite-key map.
     */
    private class KeyStorage {

        Map<MemoizerKey, MemoizerKey> map = new ConcurrentHashMap<>();

        public MemoizerKey get(final ComputableTask<A, V> c, final A taskArg) {
            MemoizerKey certificate = new MemoizerKey(c, taskArg);
            MemoizerKey key = map.putIfAbsent(certificate, certificate);
            return (key == null) ? certificate : key;
        }
    }

    /**
     * Key for composite-key map.
     */
    private class MemoizerKey {

        private final ComputableTask<A, V> task;
        private final A key;

        private MemoizerKey(ComputableTask<A, V> task, A key) {
            this.task = task;
            this.key = key;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            //noinspection unchecked
            MemoizerKey cacheKey = (MemoizerKey) o;

            //noinspection SimplifiableIfStatement
            if (key != null ? !key.equals(cacheKey.key) : cacheKey.key != null) return false;
            return !(task != null ? !task.equals(cacheKey.task) : cacheKey.task != null);

        }

        @Override
        public int hashCode() {
            int result = task != null ? task.hashCode() : 0;
            result = 31 * result + (key != null ? key.hashCode() : 0);
            return result;
        }
    }
}
