/*
 * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2015, 2018 IBM Corporation. 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:
//     05/06/2015-2.7 Tomas Kraus
//       - Initial API and implementation.
package org.eclipse.persistence.internal.jpa;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.platform.server.ServerPlatformUtils;

/**
 * Partition isolated {@link HashMap}. Provides HashMap with partition isolation for {@link ServerPlatform}s
 * that support partitioning. Partition isolation is transparent and keeps {@link Map} API unchanged.
 */
public final class IsolatedHashMap<K, V> implements Map<K, V> {

    /** Default short enough partition ID when server does not support partitions.*/
    private static final String DEFAULT_PARTITION_ID = "0";

    /** Default initial capacity used to create {@link HashMap}s for individual partitions. */
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    /** Default load factor used to create {@link HashMap}s for individual partitions. */
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /** Detected server platform. */
    private static final ServerPlatform serverPlatform;

    /** Does platform support partitions? */
    private static final boolean supportPartitions;

    /** Class initialization code. */
    static {
        String serverPlatformName = ServerPlatformUtils.detectServerPlatform(null);
        serverPlatform = serverPlatformName != null
                ? ServerPlatformUtils.createServerPlatform(
                        null, serverPlatformName, IsolatedHashMap.class.getClassLoader())
                : null;
        // False value also handles cases when serverPlatform is null to avoid NPE.
        supportPartitions = serverPlatform != null ? serverPlatform.usesPartitions() : false;
    }

    /**
     * INTERNAL:
     * Partition isolated {@link Map} factory. Provides {@link Map} separated for individual partitions.
     * Factory method will return {@link HashMap} on platforms without partitions support. Slower
     * {@link IsolatedHashMap} instance will be used only on platforms with partitions support.
     */
    public static final <K, V>Map<K, V> newMap() {
        return supportPartitions ? new IsolatedHashMap<>() : new HashMap<>();
    }

    /** Initial capacity used to create {@link HashMap}s for individual partitions. */
    private final int initialCapacity;

    /** Initial load factor used to create {@link HashMap}s for individual partitions. */
    private final float loadFactor;

    /** Partition ID to {@link Map} mapping. Used when platform does support partitions. */
    private final Map<String, Map<K, V>> maps;

    /**
     * Constructs an empty {@code IsolatedHashMap} with the default initial capacity {@code 16} and the default
     * load factor {@code 0.75} for every partition.
     */
    private IsolatedHashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    /**
     * Constructs an empty {@code IsolatedHashMap} with the initial capacity and the default
     * load factor specified as arguments.
     * @param initialCapacity Initial capacity used to create {@link HashMap}s for individual partitions.
     * @param loadFactor      Initial load factor used used to create {@link HashMap}s for individual partitions.
     */
    private IsolatedHashMap(final int initialCapacity, final float loadFactor) {
        this.initialCapacity = initialCapacity;
        this.loadFactor = loadFactor;
        maps = new ConcurrentHashMap<>(8);
    }

    /**
     * Get {@link Map} for current partition.
     * @return {@link Map} for current partition. Will never return {@code null}.
     */
    private Map<K, V> getMap() {
        String partitionId = supportPartitions ? serverPlatform.getPartitionID() : DEFAULT_PARTITION_ID;
        Map<K, V> partitionMap = maps.get(partitionId);
        // First null check to skip locking when map is already initialized.
        if (partitionMap == null) {
            // FindBugs would be complaining about locking on maps so this is used to shut it up.
            synchronized(this) {
                // Second null check while having lock.
                partitionMap = maps.get(partitionId);
                if (partitionMap == null) {
                    partitionMap = new HashMap<>(initialCapacity, loadFactor);
                    maps.put(partitionId, partitionMap);
                }
            }
        }
        return partitionMap;
    }

    // All Map interface methods are delegated to Map mapped to current partition.

    @Override
    public int size() {
        return getMap().size();
    }


    @Override
    public boolean isEmpty() {
        return getMap().isEmpty();
    }


    @Override
    public boolean containsKey(Object key) {
        return getMap().containsKey(key);
    }


    @Override
    public boolean containsValue(Object value) {
        return getMap().containsValue(value);
    }


    @Override
    public V get(Object key) {
        return getMap().get(key);
    }


    @Override
    public V put(K key, V value) {
        return getMap().put(key, value);
    }


    @Override
    public V remove(Object key) {
        return getMap().remove(key);
    }


    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        getMap().putAll(m);
    }


    @Override
    public void clear() {
        getMap().clear();
    }


    @Override
    public Set<K> keySet() {
        return getMap().keySet();
    }


    @Override
    public Collection<V> values() {
        return getMap().values();
    }


    @Override
    public Set<java.util.Map.Entry<K, V>> entrySet() {
        return getMap().entrySet();
    }

}
