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.collect.testing.Helpers.mapEntry;
020
021import com.google.common.annotations.GwtCompatible;
022import com.google.common.collect.ImmutableMap;
023import com.google.common.collect.ImmutableSet;
024import com.google.common.collect.Iterables;
025import com.google.common.collect.Maps;
026import com.google.common.collect.Ordering;
027import com.google.common.collect.testing.AnEnum;
028import com.google.common.collect.testing.SampleElements;
029import com.google.common.collect.testing.TestEnumMapGenerator;
030import com.google.common.collect.testing.TestListGenerator;
031import com.google.common.collect.testing.TestMapGenerator;
032import com.google.common.collect.testing.TestStringListGenerator;
033import com.google.common.collect.testing.TestStringMapGenerator;
034import com.google.common.collect.testing.TestUnhashableCollectionGenerator;
035import com.google.common.collect.testing.UnhashableObject;
036import java.util.Arrays;
037import java.util.Collection;
038import java.util.EnumMap;
039import java.util.List;
040import java.util.Map;
041import java.util.Map.Entry;
042
043/**
044 * Generators of different types of map and related collections, such as keys, entries and values.
045 *
046 * @author Hayward Chan
047 */
048@GwtCompatible
049@ElementTypesAreNonnullByDefault
050public class MapGenerators {
051  public static class ImmutableMapGenerator extends TestStringMapGenerator {
052    @Override
053    protected Map<String, String> create(Entry<String, String>[] entries) {
054      ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
055      for (Entry<String, String> entry : entries) {
056        builder.put(entry.getKey(), entry.getValue());
057      }
058      return builder.buildOrThrow();
059    }
060  }
061
062  public static class ImmutableMapCopyOfGenerator extends TestStringMapGenerator {
063    @Override
064    protected Map<String, String> create(Entry<String, String>[] entries) {
065      Map<String, String> builder = Maps.newLinkedHashMap();
066      for (Entry<String, String> entry : entries) {
067        builder.put(entry.getKey(), entry.getValue());
068      }
069      return ImmutableMap.copyOf(builder);
070    }
071  }
072
073  public static class ImmutableMapCopyOfEntriesGenerator extends TestStringMapGenerator {
074    @Override
075    protected Map<String, String> create(Entry<String, String>[] entries) {
076      return ImmutableMap.copyOf(Arrays.asList(entries));
077    }
078  }
079
080  public static class ImmutableMapUnhashableValuesGenerator
081      extends TestUnhashableCollectionGenerator<Collection<UnhashableObject>> {
082
083    @Override
084    public Collection<UnhashableObject> create(UnhashableObject[] elements) {
085      ImmutableMap.Builder<Integer, UnhashableObject> builder = ImmutableMap.builder();
086      int key = 1;
087      for (UnhashableObject value : elements) {
088        builder.put(key++, value);
089      }
090      return builder.buildOrThrow().values();
091    }
092  }
093
094  public static class ImmutableMapKeyListGenerator extends TestStringListGenerator {
095    @Override
096    public List<String> create(String[] elements) {
097      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
098      for (int i = 0; i < elements.length; i++) {
099        builder.put(elements[i], i);
100      }
101      return builder.buildOrThrow().keySet().asList();
102    }
103  }
104
105  public static class ImmutableMapValueListGenerator extends TestStringListGenerator {
106    @Override
107    public List<String> create(String[] elements) {
108      ImmutableMap.Builder<Integer, String> builder = ImmutableMap.builder();
109      for (int i = 0; i < elements.length; i++) {
110        builder.put(i, elements[i]);
111      }
112      return builder.buildOrThrow().values().asList();
113    }
114  }
115
116  public static class ImmutableMapEntryListGenerator
117      implements TestListGenerator<Entry<String, Integer>> {
118
119    @Override
120    public SampleElements<Entry<String, Integer>> samples() {
121      return new SampleElements<>(
122          mapEntry("foo", 5),
123          mapEntry("bar", 3),
124          mapEntry("baz", 17),
125          mapEntry("quux", 1),
126          mapEntry("toaster", -2));
127    }
128
129    @SuppressWarnings("unchecked")
130    @Override
131    public Entry<String, Integer>[] createArray(int length) {
132      return (Entry<String, Integer>[]) new Entry<?, ?>[length];
133    }
134
135    @Override
136    public Iterable<Entry<String, Integer>> order(List<Entry<String, Integer>> insertionOrder) {
137      return insertionOrder;
138    }
139
140    @Override
141    public List<Entry<String, Integer>> create(Object... elements) {
142      ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
143      for (Object o : elements) {
144        @SuppressWarnings("unchecked")
145        Entry<String, Integer> entry = (Entry<String, Integer>) o;
146        builder.put(entry);
147      }
148      return builder.buildOrThrow().entrySet().asList();
149    }
150  }
151
152  public static class ImmutableEnumMapGenerator extends TestEnumMapGenerator {
153    @Override
154    protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
155      Map<AnEnum, String> map = Maps.newHashMap();
156      for (Entry<AnEnum, String> entry : entries) {
157        // checkArgument(!map.containsKey(entry.getKey()));
158        map.put(entry.getKey(), entry.getValue());
159      }
160      return Maps.immutableEnumMap(map);
161    }
162  }
163
164  public static class ImmutableMapCopyOfEnumMapGenerator extends TestEnumMapGenerator {
165    @Override
166    protected Map<AnEnum, String> create(Entry<AnEnum, String>[] entries) {
167      EnumMap<AnEnum, String> map = new EnumMap<>(AnEnum.class);
168      for (Entry<AnEnum, String> entry : entries) {
169        map.put(entry.getKey(), entry.getValue());
170      }
171      return ImmutableMap.copyOf(map);
172    }
173
174    @Override
175    public Iterable<Entry<AnEnum, String>> order(List<Entry<AnEnum, String>> insertionOrder) {
176      return new Ordering<Entry<AnEnum, String>>() {
177
178        @Override
179        public int compare(Entry<AnEnum, String> left, Entry<AnEnum, String> right) {
180          return left.getKey().compareTo(right.getKey());
181        }
182      }.sortedCopy(insertionOrder);
183    }
184  }
185
186  public static class ImmutableMapValuesAsSingletonSetGenerator
187      implements TestMapGenerator<String, Collection<Integer>> {
188
189    @Override
190    public SampleElements<Entry<String, Collection<Integer>>> samples() {
191      return new SampleElements<>(
192          mapEntry("one", collectionOf(10000)),
193          mapEntry("two", collectionOf(-2000)),
194          mapEntry("three", collectionOf(300)),
195          mapEntry("four", collectionOf(-40)),
196          mapEntry("five", collectionOf(5)));
197    }
198
199    // javac7 can't infer the type parameters correctly in samples()
200    private static Collection<Integer> collectionOf(int item) {
201      return ImmutableSet.of(item);
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 = Iterables.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}