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.testing.Helpers.mapEntry;
022import static java.util.Arrays.asList;
023
024import com.google.common.annotations.GwtCompatible;
025import com.google.common.collect.ImmutableMap;
026import com.google.common.collect.ImmutableSet;
027import com.google.common.collect.Maps;
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.List;
041import java.util.Map;
042import java.util.Map.Entry;
043import org.jspecify.annotations.NullMarked;
044
045/**
046 * Generators of different types of map and related collections, such as keys, entries and values.
047 *
048 * @author Hayward Chan
049 */
050@GwtCompatible
051@NullMarked
052public class MapGenerators {
053  public static class ImmutableMapGenerator extends TestStringMapGenerator {
054    @Override
055    protected Map<String, String> create(Entry<String, String>[] entries) {
056      ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
057      for (Entry<String, String> entry : entries) {
058        checkNotNull(entry);
059        builder.put(entry.getKey(), entry.getValue());
060      }
061      return builder.buildOrThrow();
062    }
063  }
064
065  public static class ImmutableMapCopyOfGenerator extends TestStringMapGenerator {
066    @Override
067    protected Map<String, String> create(Entry<String, String>[] entries) {
068      Map<String, String> builder = Maps.newLinkedHashMap();
069      for (Entry<String, String> entry : entries) {
070        builder.put(entry.getKey(), entry.getValue());
071      }
072      return ImmutableMap.copyOf(builder);
073    }
074  }
075
076  public static class ImmutableMapCopyOfEntriesGenerator extends TestStringMapGenerator {
077    @Override
078    protected Map<String, String> create(Entry<String, String>[] entries) {
079      return ImmutableMap.copyOf(asList(entries));
080    }
081  }
082
083  public static class ImmutableMapUnhashableValuesGenerator
084      extends TestUnhashableCollectionGenerator<Collection<UnhashableObject>> {
085
086    @Override
087    public Collection<UnhashableObject> create(UnhashableObject[] elements) {
088      ImmutableMap.Builder<Integer, UnhashableObject> builder = ImmutableMap.builder();
089      int key = 1;
090      for (UnhashableObject value : elements) {
091        builder.put(key++, value);
092      }
093      return builder.buildOrThrow().values();
094    }
095  }
096
097  public static class ImmutableMapKeyListGenerator extends TestStringListGenerator {
098    @Override
099    public List<String> create(String[] elements) {
100      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
101      for (int i = 0; i < elements.length; i++) {
102        builder.put(elements[i], i);
103      }
104      return builder.buildOrThrow().keySet().asList();
105    }
106  }
107
108  public static class ImmutableMapValueListGenerator extends TestStringListGenerator {
109    @Override
110    public List<String> create(String[] elements) {
111      ImmutableMap.Builder<Integer, String> builder = ImmutableMap.builder();
112      for (int i = 0; i < elements.length; i++) {
113        builder.put(i, elements[i]);
114      }
115      return builder.buildOrThrow().values().asList();
116    }
117  }
118
119  public static class ImmutableMapEntryListGenerator
120      implements TestListGenerator<Entry<String, Integer>> {
121
122    @Override
123    public SampleElements<Entry<String, Integer>> samples() {
124      return new SampleElements<>(
125          mapEntry("foo", 5),
126          mapEntry("bar", 3),
127          mapEntry("baz", 17),
128          mapEntry("quux", 1),
129          mapEntry("toaster", -2));
130    }
131
132    @SuppressWarnings("unchecked")
133    @Override
134    public Entry<String, Integer>[] createArray(int length) {
135      return (Entry<String, Integer>[]) new Entry<?, ?>[length];
136    }
137
138    @Override
139    public Iterable<Entry<String, Integer>> order(List<Entry<String, Integer>> insertionOrder) {
140      return insertionOrder;
141    }
142
143    @Override
144    public List<Entry<String, Integer>> create(Object... elements) {
145      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
146      for (Object o : elements) {
147        @SuppressWarnings("unchecked")
148        Entry<String, Integer> entry = (Entry<String, Integer>) checkNotNull(o);
149        builder.put(entry);
150      }
151      return builder.buildOrThrow().entrySet().asList();
152    }
153  }
154
155  public static class ImmutableEnumMapGenerator extends TestEnumMapGenerator {
156    @Override
157    protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
158      Map<AnEnum, String> map = Maps.newHashMap();
159      for (Entry<AnEnum, String> entry : entries) {
160        checkNotNull(entry);
161        map.put(entry.getKey(), entry.getValue());
162      }
163      return Maps.immutableEnumMap(map);
164    }
165  }
166
167  public static class ImmutableMapCopyOfEnumMapGenerator extends TestEnumMapGenerator {
168    @Override
169    protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
170      EnumMap<AnEnum, String> map = new EnumMap<>(AnEnum.class);
171      for (Entry<AnEnum, String> entry : entries) {
172        map.put(entry.getKey(), entry.getValue());
173      }
174      return ImmutableMap.copyOf(map);
175    }
176
177    @Override
178    public Iterable<Entry<AnEnum, String>> order(List<Entry<AnEnum, String>> insertionOrder) {
179      return new Ordering<Entry<AnEnum, String>>() {
180
181        @Override
182        public int compare(Entry<AnEnum, String> left, Entry<AnEnum, String> right) {
183          return left.getKey().compareTo(right.getKey());
184        }
185      }.sortedCopy(insertionOrder);
186    }
187  }
188
189  public static class ImmutableMapValuesAsSingletonSetGenerator
190      implements TestMapGenerator<String, Collection<Integer>> {
191
192    @Override
193    public SampleElements<Entry<String, Collection<Integer>>> samples() {
194      return new SampleElements<>(
195          mapEntry("one", ImmutableSet.of(10000)),
196          mapEntry("two", ImmutableSet.of(-2000)),
197          mapEntry("three", ImmutableSet.of(300)),
198          mapEntry("four", ImmutableSet.of(-40)),
199          mapEntry("five", ImmutableSet.of(5)));
200    }
201
202    @Override
203    public Map<String, Collection<Integer>> create(Object... elements) {
204      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
205      // assumes that each set is a singleton or less (as is done for the samples)
206      for (Object elem : elements) {
207        @SuppressWarnings("unchecked") // safe by generator contract
208        Entry<String, Collection<Integer>> entry = (Entry<String, Collection<Integer>>) elem;
209        Integer value = getOnlyElement(entry.getValue());
210        builder.put(entry.getKey(), value);
211      }
212      return builder.buildOrThrow().asMultimap().asMap();
213    }
214
215    @Override
216    @SuppressWarnings({"unchecked", "rawtypes"}) // needed for arrays
217    public Entry<String, Collection<Integer>>[] createArray(int length) {
218      return new Entry[length];
219    }
220
221    @Override
222    public Iterable<Entry<String, Collection<Integer>>> order(
223        List<Entry<String, Collection<Integer>>> insertionOrder) {
224      return insertionOrder;
225    }
226
227    @Override
228    public String[] createKeyArray(int length) {
229      return new String[length];
230    }
231
232    @Override
233    @SuppressWarnings({"unchecked", "rawtypes"}) // needed for arrays
234    public Collection<Integer>[] createValueArray(int length) {
235      return new ImmutableSet[length];
236    }
237  }
238}