PageRenderTime 27ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/guava25/collect/MultimapBuilder.java

http://github.com/WindowsAzure/azure-sdk-for-java
Java | 474 lines | 254 code | 59 blank | 161 comment | 0 complexity | b9fe2c5ab541e68fd97a1d86ec27f557 MD5 | raw file
Possible License(s): MIT
  1. /*
  2. * Copyright (C) 2013 The Guava Authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * Portions Copyright (c) Microsoft Corporation
  18. */
  19. package com.azure.cosmos.implementation.guava25.collect;
  20. import static com.azure.cosmos.implementation.guava25.base.Preconditions.checkNotNull;
  21. import static com.azure.cosmos.implementation.guava25.collect.CollectPreconditions.checkNonnegative;
  22. import com.azure.cosmos.implementation.guava25.base.Supplier;
  23. import java.io.Serializable;
  24. import java.util.ArrayList;
  25. import java.util.Collection;
  26. import java.util.Comparator;
  27. import java.util.EnumMap;
  28. import java.util.EnumSet;
  29. import java.util.LinkedList;
  30. import java.util.List;
  31. import java.util.Map;
  32. import java.util.Set;
  33. import java.util.SortedSet;
  34. import java.util.TreeMap;
  35. import java.util.TreeSet;
  36. /**
  37. * A builder for a multimap implementation that allows customization of the backing map and value
  38. * collection implementations used in a particular multimap.
  39. *
  40. * <p>This can be used to easily configure multimap data structure implementations not provided
  41. * explicitly in {@code com.google.common.collect}, for example:
  42. *
  43. * <pre>{@code
  44. * ListMultimap<String, Integer> treeListMultimap =
  45. * MultimapBuilder.treeKeys().arrayListValues().build();
  46. * SetMultimap<Integer, MyEnum> hashEnumMultimap =
  47. * MultimapBuilder.hashKeys().enumSetValues(MyEnum.class).build();
  48. * }</pre>
  49. *
  50. * <p>{@code MultimapBuilder} instances are immutable. Invoking a configuration method has no effect
  51. * on the receiving instance; you must store and use the new builder instance it returns instead.
  52. *
  53. * <p>The generated multimaps are serializable if the key and value types are serializable, unless
  54. * stated otherwise in one of the configuration methods.
  55. *
  56. * @author Louis Wasserman
  57. * @param <K0> An upper bound on the key type of the generated multimap.
  58. * @param <V0> An upper bound on the value type of the generated multimap.
  59. * @since 16.0
  60. */
  61. public abstract class MultimapBuilder<K0, V0> {
  62. /*
  63. * Leaving K and V as upper bounds rather than the actual key and value types allows type
  64. * parameters to be left implicit more often. CacheBuilder uses the same technique.
  65. */
  66. private MultimapBuilder() {}
  67. private static final int DEFAULT_EXPECTED_KEYS = 8;
  68. /** Uses a hash table to map keys to value collections. */
  69. public static MultimapBuilderWithKeys<Object> hashKeys() {
  70. return hashKeys(DEFAULT_EXPECTED_KEYS);
  71. }
  72. /**
  73. * Uses a hash table to map keys to value collections, initialized to expect the specified
  74. * number of keys.
  75. *
  76. * @throws IllegalArgumentException if {@code expectedKeys < 0}
  77. */
  78. public static MultimapBuilderWithKeys<Object> hashKeys(final int expectedKeys) {
  79. checkNonnegative(expectedKeys, "expectedKeys");
  80. return new MultimapBuilderWithKeys<Object>() {
  81. @Override
  82. <K, V> Map<K, Collection<V>> createMap() {
  83. return Platform.newHashMapWithExpectedSize(expectedKeys);
  84. }
  85. };
  86. }
  87. /**
  88. * Uses a hash table to map keys to value collections.
  89. *
  90. * <p>The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
  91. * Multimap#asMap()} will iterate through the keys in the order that they were first added to the
  92. * multimap, save that if all values associated with a key are removed and then the key is added
  93. * back into the multimap, that key will come last in the key iteration order.
  94. */
  95. public static MultimapBuilderWithKeys<Object> linkedHashKeys() {
  96. return linkedHashKeys(DEFAULT_EXPECTED_KEYS);
  97. }
  98. /**
  99. * Uses an hash table to map keys to value collections, initialized to expect the
  100. * specified number of keys.
  101. *
  102. * <p>The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
  103. * Multimap#asMap()} will iterate through the keys in the order that they were first added to the
  104. * multimap, save that if all values associated with a key are removed and then the key is added
  105. * back into the multimap, that key will come last in the key iteration order.
  106. */
  107. public static MultimapBuilderWithKeys<Object> linkedHashKeys(final int expectedKeys) {
  108. checkNonnegative(expectedKeys, "expectedKeys");
  109. return new MultimapBuilderWithKeys<Object>() {
  110. @Override
  111. <K, V> Map<K, Collection<V>> createMap() {
  112. return Platform.newLinkedHashMapWithExpectedSize(expectedKeys);
  113. }
  114. };
  115. }
  116. /**
  117. * Uses a naturally-ordered {@link TreeMap} to map keys to value collections.
  118. *
  119. * <p>The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
  120. * Multimap#asMap()} will iterate through the keys in sorted order.
  121. *
  122. * <p>For all multimaps generated by the resulting builder, the {@link Multimap#keySet()} can be
  123. * safely cast to a {@link java.util.SortedSet}, and the {@link Multimap#asMap()} can safely be
  124. * cast to a {@link java.util.SortedMap}.
  125. */
  126. @SuppressWarnings("rawtypes")
  127. public static MultimapBuilderWithKeys<Comparable> treeKeys() {
  128. return treeKeys(Ordering.natural());
  129. }
  130. /**
  131. * Uses a {@link TreeMap} sorted by the specified comparator to map keys to value collections.
  132. *
  133. * <p>The collections returned by {@link Multimap#keySet()}, {@link Multimap#keys()}, and {@link
  134. * Multimap#asMap()} will iterate through the keys in sorted order.
  135. *
  136. * <p>For all multimaps generated by the resulting builder, the {@link Multimap#keySet()} can be
  137. * safely cast to a {@link java.util.SortedSet}, and the {@link Multimap#asMap()} can safely be
  138. * cast to a {@link java.util.SortedMap}.
  139. *
  140. * <p>Multimaps generated by the resulting builder will not be serializable if {@code comparator}
  141. * is not serializable.
  142. */
  143. public static <K0> MultimapBuilderWithKeys<K0> treeKeys(final Comparator<K0> comparator) {
  144. checkNotNull(comparator);
  145. return new MultimapBuilderWithKeys<K0>() {
  146. @Override
  147. <K extends K0, V> Map<K, Collection<V>> createMap() {
  148. return new TreeMap<>(comparator);
  149. }
  150. };
  151. }
  152. /**
  153. * Uses an {@link EnumMap} to map keys to value collections.
  154. *
  155. * @since 16.0
  156. */
  157. public static <K0 extends Enum<K0>> MultimapBuilderWithKeys<K0> enumKeys(
  158. final Class<K0> keyClass) {
  159. checkNotNull(keyClass);
  160. return new MultimapBuilderWithKeys<K0>() {
  161. @SuppressWarnings({"unchecked", "rawtypes"})
  162. @Override
  163. <K extends K0, V> Map<K, Collection<V>> createMap() {
  164. // K must actually be K0, since enums are effectively final
  165. // (their subclasses are inaccessible)
  166. return (Map<K, Collection<V>>) new EnumMap<K0, Collection<V>>(keyClass);
  167. }
  168. };
  169. }
  170. private static final class ArrayListSupplier<V> implements Supplier<List<V>>, Serializable {
  171. private final int expectedValuesPerKey;
  172. ArrayListSupplier(int expectedValuesPerKey) {
  173. this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
  174. }
  175. @Override
  176. public List<V> get() {
  177. return new ArrayList<V>(expectedValuesPerKey);
  178. }
  179. }
  180. private enum LinkedListSupplier implements Supplier<List<Object>> {
  181. INSTANCE;
  182. public static <V> Supplier<List<V>> instance() {
  183. // Each call generates a fresh LinkedList, which can serve as a List<V> for any V.
  184. @SuppressWarnings({"rawtypes", "unchecked"})
  185. Supplier<List<V>> result = (Supplier) INSTANCE;
  186. return result;
  187. }
  188. @Override
  189. public List<Object> get() {
  190. return new LinkedList<>();
  191. }
  192. }
  193. private static final class HashSetSupplier<V> implements Supplier<Set<V>>, Serializable {
  194. private final int expectedValuesPerKey;
  195. HashSetSupplier(int expectedValuesPerKey) {
  196. this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
  197. }
  198. @Override
  199. public Set<V> get() {
  200. return Platform.newHashSetWithExpectedSize(expectedValuesPerKey);
  201. }
  202. }
  203. private static final class LinkedHashSetSupplier<V> implements Supplier<Set<V>>, Serializable {
  204. private final int expectedValuesPerKey;
  205. LinkedHashSetSupplier(int expectedValuesPerKey) {
  206. this.expectedValuesPerKey = checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
  207. }
  208. @Override
  209. public Set<V> get() {
  210. return Platform.newLinkedHashSetWithExpectedSize(expectedValuesPerKey);
  211. }
  212. }
  213. private static final class TreeSetSupplier<V> implements Supplier<SortedSet<V>>, Serializable {
  214. private final Comparator<? super V> comparator;
  215. TreeSetSupplier(Comparator<? super V> comparator) {
  216. this.comparator = checkNotNull(comparator);
  217. }
  218. @Override
  219. public SortedSet<V> get() {
  220. return new TreeSet<V>(comparator);
  221. }
  222. }
  223. private static final class EnumSetSupplier<V extends Enum<V>>
  224. implements Supplier<Set<V>>, Serializable {
  225. private final Class<V> clazz;
  226. EnumSetSupplier(Class<V> clazz) {
  227. this.clazz = checkNotNull(clazz);
  228. }
  229. @Override
  230. public Set<V> get() {
  231. return EnumSet.noneOf(clazz);
  232. }
  233. }
  234. /**
  235. * An intermediate stage in a {@link MultimapBuilder} in which the key-value collection map
  236. * implementation has been specified, but the value collection implementation has not.
  237. *
  238. * @param <K0> The upper bound on the key type of the generated multimap.
  239. * @since 16.0
  240. */
  241. public abstract static class MultimapBuilderWithKeys<K0> {
  242. private static final int DEFAULT_EXPECTED_VALUES_PER_KEY = 2;
  243. MultimapBuilderWithKeys() {}
  244. abstract <K extends K0, V> Map<K, Collection<V>> createMap();
  245. /** Uses an {@link ArrayList} to store value collections. */
  246. public ListMultimapBuilder<K0, Object> arrayListValues() {
  247. return arrayListValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
  248. }
  249. /**
  250. * Uses an {@link ArrayList} to store value collections, initialized to expect the specified
  251. * number of values per key.
  252. *
  253. * @throws IllegalArgumentException if {@code expectedValuesPerKey < 0}
  254. */
  255. public ListMultimapBuilder<K0, Object> arrayListValues(final int expectedValuesPerKey) {
  256. checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
  257. return new ListMultimapBuilder<K0, Object>() {
  258. @Override
  259. public <K extends K0, V> ListMultimap<K, V> build() {
  260. return Multimaps.newListMultimap(
  261. MultimapBuilderWithKeys.this.<K, V>createMap(),
  262. new ArrayListSupplier<V>(expectedValuesPerKey));
  263. }
  264. };
  265. }
  266. /** Uses a {@link LinkedList} to store value collections. */
  267. public ListMultimapBuilder<K0, Object> linkedListValues() {
  268. return new ListMultimapBuilder<K0, Object>() {
  269. @Override
  270. public <K extends K0, V> ListMultimap<K, V> build() {
  271. return Multimaps.newListMultimap(
  272. MultimapBuilderWithKeys.this.<K, V>createMap(), LinkedListSupplier.<V>instance());
  273. }
  274. };
  275. }
  276. /** Uses a hash-based {@code Set} to store value collections. */
  277. public SetMultimapBuilder<K0, Object> hashSetValues() {
  278. return hashSetValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
  279. }
  280. /**
  281. * Uses a hash-based {@code Set} to store value collections, initialized to expect the specified number
  282. * of values per key.
  283. *
  284. * @throws IllegalArgumentException if {@code expectedValuesPerKey < 0}
  285. */
  286. public SetMultimapBuilder<K0, Object> hashSetValues(final int expectedValuesPerKey) {
  287. checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
  288. return new SetMultimapBuilder<K0, Object>() {
  289. @Override
  290. public <K extends K0, V> SetMultimap<K, V> build() {
  291. return Multimaps.newSetMultimap(
  292. MultimapBuilderWithKeys.this.<K, V>createMap(),
  293. new HashSetSupplier<V>(expectedValuesPerKey));
  294. }
  295. };
  296. }
  297. /** Uses an insertion-ordered hash-based {@code Set} to store value collections. */
  298. public SetMultimapBuilder<K0, Object> linkedHashSetValues() {
  299. return linkedHashSetValues(DEFAULT_EXPECTED_VALUES_PER_KEY);
  300. }
  301. /**
  302. * Uses an insertion-ordered hash-based {@code Set} to store value collections, initialized to expect the specified
  303. * number of values per key.
  304. *
  305. * @throws IllegalArgumentException if {@code expectedValuesPerKey < 0}
  306. */
  307. public SetMultimapBuilder<K0, Object> linkedHashSetValues(final int expectedValuesPerKey) {
  308. checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
  309. return new SetMultimapBuilder<K0, Object>() {
  310. @Override
  311. public <K extends K0, V> SetMultimap<K, V> build() {
  312. return Multimaps.newSetMultimap(
  313. MultimapBuilderWithKeys.this.<K, V>createMap(),
  314. new LinkedHashSetSupplier<V>(expectedValuesPerKey));
  315. }
  316. };
  317. }
  318. /** Uses a naturally-ordered {@link TreeSet} to store value collections. */
  319. @SuppressWarnings("rawtypes")
  320. public SortedSetMultimapBuilder<K0, Comparable> treeSetValues() {
  321. return treeSetValues(Ordering.natural());
  322. }
  323. /**
  324. * Uses a {@link TreeSet} ordered by the specified comparator to store value collections.
  325. *
  326. * <p>Multimaps generated by the resulting builder will not be serializable if {@code
  327. * comparator} is not serializable.
  328. */
  329. public <V0> SortedSetMultimapBuilder<K0, V0> treeSetValues(final Comparator<V0> comparator) {
  330. checkNotNull(comparator, "comparator");
  331. return new SortedSetMultimapBuilder<K0, V0>() {
  332. @Override
  333. public <K extends K0, V extends V0> SortedSetMultimap<K, V> build() {
  334. return Multimaps.newSortedSetMultimap(
  335. MultimapBuilderWithKeys.this.<K, V>createMap(), new TreeSetSupplier<V>(comparator));
  336. }
  337. };
  338. }
  339. /** Uses an {@link EnumSet} to store value collections. */
  340. public <V0 extends Enum<V0>> SetMultimapBuilder<K0, V0> enumSetValues(
  341. final Class<V0> valueClass) {
  342. checkNotNull(valueClass, "valueClass");
  343. return new SetMultimapBuilder<K0, V0>() {
  344. @Override
  345. public <K extends K0, V extends V0> SetMultimap<K, V> build() {
  346. // V must actually be V0, since enums are effectively final
  347. // (their subclasses are inaccessible)
  348. @SuppressWarnings({"unchecked", "rawtypes"})
  349. Supplier<Set<V>> factory = (Supplier) new EnumSetSupplier<V0>(valueClass);
  350. return Multimaps.newSetMultimap(MultimapBuilderWithKeys.this.<K, V>createMap(), factory);
  351. }
  352. };
  353. }
  354. }
  355. /** Returns a new, empty {@code Multimap} with the specified implementation. */
  356. public abstract <K extends K0, V extends V0> Multimap<K, V> build();
  357. /**
  358. * Returns a {@code Multimap} with the specified implementation, initialized with the entries of
  359. * {@code multimap}.
  360. */
  361. public <K extends K0, V extends V0> Multimap<K, V> build(
  362. Multimap<? extends K, ? extends V> multimap) {
  363. Multimap<K, V> result = build();
  364. result.putAll(multimap);
  365. return result;
  366. }
  367. /**
  368. * A specialization of {@link MultimapBuilder} that generates {@link ListMultimap} instances.
  369. *
  370. * @since 16.0
  371. */
  372. public abstract static class ListMultimapBuilder<K0, V0> extends MultimapBuilder<K0, V0> {
  373. ListMultimapBuilder() {}
  374. @Override
  375. public abstract <K extends K0, V extends V0> ListMultimap<K, V> build();
  376. @SuppressWarnings({"unchecked", "rawtypes"})
  377. @Override
  378. public <K extends K0, V extends V0> ListMultimap<K, V> build(
  379. Multimap<? extends K, ? extends V> multimap) {
  380. return (ListMultimap<K, V>) super.build(multimap);
  381. }
  382. }
  383. /**
  384. * A specialization of {@link MultimapBuilder} that generates {@link SetMultimap} instances.
  385. *
  386. * @since 16.0
  387. */
  388. public abstract static class SetMultimapBuilder<K0, V0> extends MultimapBuilder<K0, V0> {
  389. SetMultimapBuilder() {}
  390. @Override
  391. public abstract <K extends K0, V extends V0> SetMultimap<K, V> build();
  392. @SuppressWarnings({"unchecked", "rawtypes"})
  393. @Override
  394. public <K extends K0, V extends V0> SetMultimap<K, V> build(
  395. Multimap<? extends K, ? extends V> multimap) {
  396. return (SetMultimap<K, V>) super.build(multimap);
  397. }
  398. }
  399. /**
  400. * A specialization of {@link MultimapBuilder} that generates {@link SortedSetMultimap} instances.
  401. *
  402. * @since 16.0
  403. */
  404. public abstract static class SortedSetMultimapBuilder<K0, V0> extends SetMultimapBuilder<K0, V0> {
  405. SortedSetMultimapBuilder() {}
  406. @Override
  407. public abstract <K extends K0, V extends V0> SortedSetMultimap<K, V> build();
  408. @SuppressWarnings({"unchecked", "rawtypes"})
  409. @Override
  410. public <K extends K0, V extends V0> SortedSetMultimap<K, V> build(
  411. Multimap<? extends K, ? extends V> multimap) {
  412. return (SortedSetMultimap<K, V>) super.build(multimap);
  413. }
  414. }
  415. }