/*
 * Copyright (c) 2015, 2021 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:
//     Oracle - initial API and implementation
package org.eclipse.persistence.indirection;

import java.util.Collection;
import java.util.Map;

/**
 * Provides factory methods to create JDK specific implementation
 * of particular type of {@link IndirectCollection}.
 *
 * @author Lukas Jungmann
 * @see IndirectCollection
 * @see IndirectList
 * @see IndirectMap
 * @see IndirectSet
 * @since EclipseLink 2.6.0
 */
public final class IndirectCollectionsFactory {

    private static final IndirectCollectionsProvider provider = getProvider();

    /**
     * Class implementing {@link IndirectList}.
     */
    public static final Class IndirectList_Class = provider.getListClass();

    /**
     * Class implementing {@link IndirectSet}.
     */
    public static final Class IndirectSet_Class = provider.getSetClass();

    /**
     * Class implementing {@link IndirectMap}.
     */
    public static final Class IndirectMap_Class = provider.getMapClass();

    private IndirectCollectionsFactory() {
        // no instance please
    }

    /**
     * Construct an empty {@link IndirectList} with the default initial capacity (10)
     * and default capacity increment (0).
     *
     * @param <E> the class of the objects in the list
     * @return an empty {@link IndirectList} with the default initial capacity
     *      and default capacity increment
     */
    public static <E> IndirectList<E> createIndirectList() {
        return provider.createIndirectList(10, 0);
    }

    /**
     * Construct an empty {@link IndirectList} with the specified initial capacity
     * and default capacity increment (0).
     *
     * @param <E> the class of the objects in the list
     * @param initialCapacity the initial capacity of the vector
     *
     * @return an empty {@link IndirectList} with the specified initial capacity
     *      and default capacity increment
     * @throws IllegalArgumentException if the specified initial capacity
     *      is negative
     */
    public static <E> IndirectList<E> createIndirectList(int initialCapacity) {
        return provider.createIndirectList(initialCapacity, 0);
    }

    /**
     * Construct an {@link IndirectList} containing the elements of the specified
     * collection, in the order they are returned by the collection's iterator.
     *
     * @param <E> the class of the objects in the list
     * @param collection a collection containing the elements to construct
     *      the {@link IndirectList} with.
     * @return an {@link IndirectList} containing the elements of the specified
     *      collection
     */
    public static <E> IndirectList<E> createIndirectList(Collection<? extends E> collection) {
        return  provider.createIndirectList(collection);
    }

    /**
     * Construct an empty {@link IndirectSet} with the default initial capacity (10)
     * and the default load factor (0.75).
     *
     * @return an empty {@link IndirectSet} with the default initial capacity
     *      and the default load factor
     */
    public static <E> IndirectSet<E> createIndirectSet() {
        return provider.createIndirectSet(10, 0.75f);
    }

    /**
     * Construct an empty {@link IndirectSet} with the specified initial capacity
     * and the default load factor (0.75).
     *
     * @param initialCapacity the initial capacity of the set
     *
     * @return an empty {@link IndirectSet} with the specified initial capacity
     *      and the default load factor
     * @throws IllegalArgumentException if the specified initial capacity is negative
     */
    public static <E> IndirectSet<E> createIndirectSet(int initialCapacity) {
        return provider.createIndirectSet(initialCapacity, 0.75f);
    }

    /**
     * Constructs an {@link IndirectSet} containing the elements of the specified
     * collection.
     *
     * @param collection a collection containing the elements to construct
     *      the {@link IndirectSet} with
     *
     * @return an {@link IndirectSet} containing the elements of the specified collection
     * @throws NullPointerException if the specified collection is null
     */
    public static <E> IndirectSet<E> createIndirectSet(Collection<? extends E> collection) {
        return provider.createIndirectSet(collection);
    }

    /**
     * Construct a new, empty {@link IndirectMap} with the default initial
     * capacity (11) and the default load factor (0.75).
     *
     * @return a new, empty {@link IndirectMap} with the default initial
     *      capacity and the default load factor
     */
    public static <K, V> IndirectMap<K, V> createIndirectMap() {
        return provider.createIndirectMap(11, 0.75f);
    }

    /**
     * Construct a new, empty {@link IndirectMap} with the specified initial
     * capacity and the default load factor (0.75).
     *
     * @param initialCapacity the initial capacity of the {@link IndirectMap}
     *
     * @return a new, empty {@link IndirectMap} with the specified initial
     *      capacity and the default load factor
     * @throws  IllegalArgumentException  if the initial capacity is less than
     *      or equal to zero
     */
    public static <K, V> IndirectMap<K, V> createIndirectMap(int initialCapacity) {
        return provider.createIndirectMap(initialCapacity, 0.75f);
    }

    /**
     * Construct a new {@link IndirectMap} with the same mappings as the given Map.
     * The {@link IndirectMap} is created with a capacity of twice the number of entries
     * in the given Map or 11 (whichever is greater), and a default load factor, which is 0.75.
     *
     * @param map the map whose mappings are to be placed into created {@link IndirectMap}
     *
     * @return a new {@link IndirectMap} with the same mappings as the given Map
     * @throws NullPointerException if the specified map is null
     */
    public static <K, V> IndirectMap<K, V> createIndirectMap(Map<? extends K, ? extends V> map) {
        return provider.createIndirectMap(map);
    }

    /**
     * As of EclipseLink 2.6.0 this returns Java SE 7- compatible provider by default
     * on Java SE 7 and Java SE 8+ compatible provider if Java SE 8+ is detected.
     *
     * @return default provider responsible for creating Java SE specific implementations
     * of {@link IndirectCollection}s
     */
    private static IndirectCollectionsProvider getProvider() {
        return new DefaultProvider();
    }

    /**
     * Define API providers of {@link IndirectCollection} implementations must conform to.
     */
    public interface IndirectCollectionsProvider {

        /**
         * Class implementing {@link IndirectList}.
         *
         * @return class implementing {@link IndirectList}
         */
        Class getListClass();

        /**
         * Construct an empty {@link IndirectList} with the specified initial capacity
         * and capacity increment.
         *
         * @param <E> the class of the objects in the list
         * @param initialCapacity the initial capacity of the list
         * @param capacityIncrement the amount by which the capacity is increased
         *      when the list overflows
         *
         * @return an empty {@link IndirectList} with the specified initial capacity
         *      and capacity increment
         * @throws IllegalArgumentException if the specified initial capacity is negative
         */
        <E> IndirectList<E> createIndirectList(int initialCapacity, int capacityIncrement);

        /**
         * Constructs an {@link IndirectList} containing the elements of the specified
         * collection, in the order they are returned by the collection's iterator.
         *
         * @param <E> the class of the objects in the list
         * @param collection a collection containing the elements to construct
         *      the {@link IndirectList} with
         *
         * @return an {@link IndirectList} containing the elements of the specified collection
         * @throws NullPointerException if the specified collection is null
         */
        <E> IndirectList<E> createIndirectList(Collection<? extends E> collection);

        /**
         * Class implementing {@link IndirectSet}.
         *
         * @return class implementing {@link IndirectSet}
         */
        Class getSetClass();

        /**
         * Construct an empty {@link IndirectSet} with the specified initial capacity
         * and the specified load factor.
         *
         * @param initialCapacity the initial capacity of the set
         * @param loadFactor the load factor of the set
         *
         * @return an empty {@link IndirectSet} with the specified initial capacity
         *      and the specified load factor
         * @throws IllegalArgumentException if the specified initial capacity is negative
         */
        <E> IndirectSet<E> createIndirectSet(int initialCapacity, float loadFactor);

        /**
         * Constructs an {@link IndirectSet} containing the elements of the specified
         * collection.
         *
         * @param collection a collection containing the elements to construct
         *      the {@link IndirectSet} with
         *
         * @return an {@link IndirectSet} containing the elements of the specified collection
         * @throws NullPointerException if the specified collection is null
         */
        <E> IndirectSet<E> createIndirectSet(Collection<? extends E> collection);

        /**
         * Class implementing {@link IndirectMap}.
         *
         * @return class implementing {@link IndirectMap}
         */
        Class getMapClass();

        /**
         * Construct a new, empty {@link IndirectMap} with the specified initial
         * capacity and the specified load factor.
         *
         * @param initialCapacity the initial capacity of the {@link IndirectMap}
         * @param loadFactor a number between 0.0 and 1.0
         *
         * @return a new, empty {@link IndirectMap} with the specified initial
         *      capacity and the specified load factor
         * @throws  IllegalArgumentException  if the initial capacity is less than
         *      or equal to zero, or if the load factor is less than or equal to zero
         */
        <K, V> IndirectMap<K, V> createIndirectMap(int initialCapacity, float loadFactor);

        /**
         * Construct a new {@link IndirectMap} with the same mappings as the given Map.
         * The {@link IndirectMap} is created with a capacity of twice the number of entries
         * in the given Map or 11 (whichever is greater), and a default load factor, which is 0.75.
         *
         * @param map the map whose mappings are to be placed into created {@link IndirectMap}
         *
         * @return a new {@link IndirectMap} with the same mappings as the given Map
         * @throws NullPointerException if the specified map is null
         */
        <K, V> IndirectMap<K, V> createIndirectMap(Map<? extends K, ? extends V> map);
    }

    /**
     * Provider for creating Java SE 7 (and older) compatible
     * {@link IndirectCollection} implementations.
     */
    private static final class DefaultProvider implements IndirectCollectionsProvider {

        @Override
        public Class getListClass() {
            return IndirectList.class;
        }

        @Override
        public <E> IndirectList<E> createIndirectList(int initialCapacity, int capacityIncrement) {
            return new IndirectList<>(initialCapacity, capacityIncrement);
        }

        @Override
        public <E> IndirectList<E> createIndirectList(Collection<? extends E> collection) {
            return new IndirectList<>(collection);
        }

        @Override
        public Class getSetClass() {
            return IndirectSet.class;
        }

        @Override
        public <E> IndirectSet<E> createIndirectSet(int initialCapacity, float loadFactor) {
            return new IndirectSet<>(initialCapacity, loadFactor);
        }

        @Override
        public <E> IndirectSet<E> createIndirectSet(Collection<? extends E> collection) {
            return new IndirectSet<>(collection);
        }

        @Override
        public Class getMapClass() {
            return IndirectMap.class;
        }

        @Override
        public <K, V> IndirectMap<K, V> createIndirectMap(int initialCapacity, float loadFactor) {
            return new IndirectMap<>(initialCapacity, loadFactor);
        }

        @Override
        public <K, V> IndirectMap<K, V> createIndirectMap(Map<? extends K, ? extends V> map) {
            return new IndirectMap<>(map);
        }
    }
}
