001/*
002 * Configurate
003 * Copyright (C) zml and Configurate contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.spongepowered.configurate.util;
018
019import static java.util.Objects.requireNonNull;
020
021import java.util.Comparator;
022import java.util.LinkedHashMap;
023import java.util.Map;
024import java.util.concurrent.ConcurrentHashMap;
025import java.util.concurrent.ConcurrentMap;
026import java.util.concurrent.ConcurrentSkipListMap;
027
028/**
029 * Default implementations of {@link MapFactory}.
030 *
031 * @since 4.0.0
032 */
033public final class MapFactories {
034
035    private MapFactories() {}
036
037    /**
038     * Returns a {@link MapFactory} which creates maps without an order.
039     *
040     * @return a map factory which produces unordered maps
041     * @since 4.0.0
042     */
043    public static MapFactory unordered() {
044        return DefaultFactory.UNORDERED;
045    }
046
047    /**
048     * Returns a {@link MapFactory} which creates maps which are sorted using the given comparator.
049     *
050     * @param comparator the comparator used to sort the map keys
051     * @return a map factory which produces sorted maps
052     * @since 4.0.0
053     */
054    public static MapFactory sorted(final Comparator<Object> comparator) {
055        return new SortedMapFactory(requireNonNull(comparator, "comparator"));
056    }
057
058    /**
059     * Returns a {@link MapFactory} which creates maps which are naturally sorted.
060     *
061     * @return a map factory which produces naturally sorted maps
062     * @see Comparator#naturalOrder()
063     * @since 4.0.0
064     */
065    public static MapFactory sortedNatural() {
066        return DefaultFactory.SORTED_NATURAL;
067    }
068
069    /**
070     * Returns a {@link MapFactory} which creates maps which are sorted by insertion order.
071     *
072     * @return a map factory which produces maps sorted by insertion order
073     * @since 4.0.0
074     */
075    public static MapFactory insertionOrdered() {
076        return DefaultFactory.INSERTION_ORDERED;
077    }
078
079    private enum DefaultFactory implements MapFactory {
080        /**
081         * A factory creating maps with no order contract.
082         *
083         * @since 4.0.0
084         */
085        UNORDERED {
086            @Override
087            public <K, V> ConcurrentMap<K, V> create() {
088                return new ConcurrentHashMap<>();
089            }
090        },
091        /**
092         * A factory creating maps which sort comparable elements by
093         * natural order.
094         *
095         * @since 4.0.0
096         */
097        SORTED_NATURAL {
098            @Override
099            public <K, V> ConcurrentMap<K, V> create() {
100                return new ConcurrentSkipListMap<>();
101            }
102        },
103        /**
104         * A factory creating maps that preserve insertion order.
105         *
106         * @since 4.0.0
107         */
108        INSERTION_ORDERED {
109            @Override
110            public <K, V> Map<K, V> create() {
111                return new LinkedHashMap<>();
112            }
113        }
114    }
115
116    private static final class SortedMapFactory implements MapFactory {
117        private final Comparator<Object> comparator;
118
119        private SortedMapFactory(final Comparator<Object> comparator) {
120            this.comparator = comparator;
121        }
122
123        @Override
124        public <K, V> ConcurrentMap<K, V> create() {
125            return new ConcurrentSkipListMap<>(this.comparator);
126        }
127
128        @Override
129        public boolean equals(final Object obj) {
130            return obj instanceof SortedMapFactory && this.comparator.equals(((SortedMapFactory) obj).comparator);
131        }
132
133        @Override
134        public int hashCode() {
135            return this.comparator.hashCode();
136        }
137
138        @Override
139        public String toString() {
140            return "SortedMapFactory{comparator=" + this.comparator + '}';
141        }
142    }
143
144}