001/*
002 * Copyright (C) 2009 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect.testing.google;
018
019import static com.google.common.base.Preconditions.checkNotNull;
020import static com.google.common.collect.Iterables.getOnlyElement;
021import static com.google.common.collect.Maps.immutableEnumMap;
022import static com.google.common.collect.testing.Helpers.mapEntry;
023import static java.util.Arrays.asList;
024
025import com.google.common.annotations.GwtCompatible;
026import com.google.common.collect.ImmutableMap;
027import com.google.common.collect.ImmutableSet;
028import com.google.common.collect.Ordering;
029import com.google.common.collect.testing.AnEnum;
030import com.google.common.collect.testing.SampleElements;
031import com.google.common.collect.testing.TestEnumMapGenerator;
032import com.google.common.collect.testing.TestListGenerator;
033import com.google.common.collect.testing.TestMapGenerator;
034import com.google.common.collect.testing.TestStringListGenerator;
035import com.google.common.collect.testing.TestStringMapGenerator;
036import com.google.common.collect.testing.TestUnhashableCollectionGenerator;
037import com.google.common.collect.testing.UnhashableObject;
038import java.util.Collection;
039import java.util.EnumMap;
040import java.util.HashMap;
041import java.util.LinkedHashMap;
042import java.util.List;
043import java.util.Map;
044import java.util.Map.Entry;
045import org.jspecify.annotations.NullMarked;
046
047/**
048 * Generators of different types of map and related collections, such as keys, entries and values.
049 *
050 * @author Hayward Chan
051 */
052@GwtCompatible
053@NullMarked
054public class MapGenerators {
055  public static class ImmutableMapGenerator extends TestStringMapGenerator {
056    @Override
057    protected Map<String, String> create(Entry<String, String>[] entries) {
058      ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
059      for (Entry<String, String> entry : entries) {
060        checkNotNull(entry);
061        builder.put(entry.getKey(), entry.getValue());
062      }
063      return builder.buildOrThrow();
064    }
065  }
066
067  public static class ImmutableMapCopyOfGenerator extends TestStringMapGenerator {
068    @Override
069    protected Map<String, String> create(Entry<String, String>[] entries) {
070      Map<String, String> builder = new LinkedHashMap<>();
071      for (Entry<String, String> entry : entries) {
072        builder.put(entry.getKey(), entry.getValue());
073      }
074      return ImmutableMap.copyOf(builder);
075    }
076  }
077
078  public static class ImmutableMapCopyOfEntriesGenerator extends TestStringMapGenerator {
079    @Override
080    protected Map<String, String> create(Entry<String, String>[] entries) {
081      return ImmutableMap.copyOf(asList(entries));
082    }
083  }
084
085  public static class ImmutableMapUnhashableValuesGenerator
086      extends TestUnhashableCollectionGenerator<Collection<UnhashableObject>> {
087
088    @Override
089    public Collection<UnhashableObject> create(UnhashableObject[] elements) {
090      ImmutableMap.Builder<Integer, UnhashableObject> builder = ImmutableMap.builder();
091      int key = 1;
092      for (UnhashableObject value : elements) {
093        builder.put(key++, value);
094      }
095      return builder.buildOrThrow().values();
096    }
097  }
098
099  public static class ImmutableMapKeyListGenerator extends TestStringListGenerator {
100    @Override
101    public List<String> create(String[] elements) {
102      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
103      for (int i = 0; i < elements.length; i++) {
104        builder.put(elements[i], i);
105      }
106      return builder.buildOrThrow().keySet().asList();
107    }
108  }
109
110  public static class ImmutableMapValueListGenerator extends TestStringListGenerator {
111    @Override
112    public List<String> create(String[] elements) {
113      ImmutableMap.Builder<Integer, String> builder = ImmutableMap.builder();
114      for (int i = 0; i < elements.length; i++) {
115        builder.put(i, elements[i]);
116      }
117      return builder.buildOrThrow().values().asList();
118    }
119  }
120
121  public static class ImmutableMapEntryListGenerator
122      implements TestListGenerator<Entry<String, Integer>> {
123
124    @Override
125    public SampleElements<Entry<String, Integer>> samples() {
126      return new SampleElements<>(
127          mapEntry("foo", 5),
128          mapEntry("bar", 3),
129          mapEntry("baz", 17),
130          mapEntry("quux", 1),
131          mapEntry("toaster", -2));
132    }
133
134    @SuppressWarnings("unchecked")
135    @Override
136    public Entry<String, Integer>[] createArray(int length) {
137      return (Entry<String, Integer>[]) new Entry<?, ?>[length];
138    }
139
140    @Override
141    public Iterable<Entry<String, Integer>> order(List<Entry<String, Integer>> insertionOrder) {
142      return insertionOrder;
143    }
144
145    @Override
146    public List<Entry<String, Integer>> create(Object... elements) {
147      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
148      for (Object o : elements) {
149        @SuppressWarnings("unchecked")
150        Entry<String, Integer> entry = (Entry<String, Integer>) checkNotNull(o);
151        builder.put(entry);
152      }
153      return builder.buildOrThrow().entrySet().asList();
154    }
155  }
156
157  public static class ImmutableEnumMapGenerator extends TestEnumMapGenerator {
158    @Override
159    protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
160      Map<AnEnum, String> map = new HashMap<>();
161      for (Entry<AnEnum, String> entry : entries) {
162        checkNotNull(entry);
163        map.put(entry.getKey(), entry.getValue());
164      }
165      return immutableEnumMap(map);
166    }
167  }
168
169  public static class ImmutableMapCopyOfEnumMapGenerator extends TestEnumMapGenerator {
170    @Override
171    protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
172      EnumMap<AnEnum, String> map = new EnumMap<>(AnEnum.class);
173      for (Entry<AnEnum, String> entry : entries) {
174        map.put(entry.getKey(), entry.getValue());
175      }
176      return ImmutableMap.copyOf(map);
177    }
178
179    @Override
180    public Iterable<Entry<AnEnum, String>> order(List<Entry<AnEnum, String>> insertionOrder) {
181      return new Ordering<Entry<AnEnum, String>>() {
182
183        @Override
184        public int compare(Entry<AnEnum, String> left, Entry<AnEnum, String> right) {
185          return left.getKey().compareTo(right.getKey());
186        }
187      }.sortedCopy(insertionOrder);
188    }
189  }
190
191  public static class ImmutableMapValuesAsSingletonSetGenerator
192      implements TestMapGenerator<String, Collection<Integer>> {
193
194    @Override
195    public SampleElements<Entry<String, Collection<Integer>>> samples() {
196      return new SampleElements<>(
197          mapEntry("one", ImmutableSet.of(10000)),
198          mapEntry("two", ImmutableSet.of(-2000)),
199          mapEntry("three", ImmutableSet.of(300)),
200          mapEntry("four", ImmutableSet.of(-40)),
201          mapEntry("five", ImmutableSet.of(5)));
202    }
203
204    @Override
205    public Map<String, Collection<Integer>> create(Object... elements) {
206      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
207      // assumes that each set is a singleton or less (as is done for the samples)
208      for (Object elem : elements) {
209        @SuppressWarnings("unchecked") // safe by generator contract
210        Entry<String, Collection<Integer>> entry = (Entry<String, Collection<Integer>>) elem;
211        Integer value = getOnlyElement(entry.getValue());
212        builder.put(entry.getKey(), value);
213      }
214      return builder.buildOrThrow().asMultimap().asMap();
215    }
216
217    @Override
218    @SuppressWarnings({"unchecked", "rawtypes"}) // needed for arrays
219    public Entry<String, Collection<Integer>>[] createArray(int length) {
220      return new Entry[length];
221    }
222
223    @Override
224    public Iterable<Entry<String, Collection<Integer>>> order(
225        List<Entry<String, Collection<Integer>>> insertionOrder) {
226      return insertionOrder;
227    }
228
229    @Override
230    public String[] createKeyArray(int length) {
231      return new String[length];
232    }
233
234    @Override
235    @SuppressWarnings({"unchecked", "rawtypes"}) // needed for arrays
236    public Collection<Integer>[] createValueArray(int length) {
237      return new ImmutableSet[length];
238    }
239  }
240
241  /**
242   * Useless constructor for a class of static utility methods.
243   *
244   * @deprecated Do not instantiate this utility class.
245   */
246  @Deprecated
247  public MapGenerators() {}
248}