001/*
002 * Copyright (C) 2012 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 com.google.common.annotations.GwtCompatible;
020import com.google.common.collect.BiMap;
021import com.google.common.collect.testing.DerivedGenerator;
022import com.google.common.collect.testing.Helpers;
023import com.google.common.collect.testing.OneSizeTestContainerGenerator;
024import com.google.common.collect.testing.SampleElements;
025import com.google.common.collect.testing.TestMapGenerator;
026import com.google.common.collect.testing.TestSetGenerator;
027import com.google.common.collect.testing.TestSubjectGenerator;
028import java.util.ArrayList;
029import java.util.Collection;
030import java.util.List;
031import java.util.Map;
032import java.util.Map.Entry;
033import java.util.Set;
034import org.checkerframework.checker.nullness.qual.Nullable;
035
036/**
037 * Derived suite generators for Guava collection interfaces, split out of the suite builders so that
038 * they are available to GWT.
039 *
040 * @author Louis Wasserman
041 */
042@GwtCompatible
043@ElementTypesAreNonnullByDefault
044public final class DerivedGoogleCollectionGenerators {
045  public static class MapGenerator<K extends @Nullable Object, V extends @Nullable Object>
046      implements TestMapGenerator<K, V>, DerivedGenerator {
047
048    private final OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>> generator;
049
050    public MapGenerator(
051        OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>> oneSizeTestContainerGenerator) {
052      this.generator = oneSizeTestContainerGenerator;
053    }
054
055    @Override
056    public SampleElements<Entry<K, V>> samples() {
057      return generator.samples();
058    }
059
060    @Override
061    public Map<K, V> create(Object... elements) {
062      return generator.create(elements);
063    }
064
065    @Override
066    public Entry<K, V>[] createArray(int length) {
067      return generator.createArray(length);
068    }
069
070    @Override
071    public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
072      return generator.order(insertionOrder);
073    }
074
075    @SuppressWarnings("unchecked")
076    @Override
077    public K[] createKeyArray(int length) {
078      return (K[]) new Object[length];
079    }
080
081    @SuppressWarnings("unchecked")
082    @Override
083    public V[] createValueArray(int length) {
084      return (V[]) new Object[length];
085    }
086
087    @Override
088    public TestSubjectGenerator<?> getInnerGenerator() {
089      return generator;
090    }
091  }
092
093  public static class InverseBiMapGenerator<K extends @Nullable Object, V extends @Nullable Object>
094      implements TestBiMapGenerator<V, K>, DerivedGenerator {
095
096    private final OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>> generator;
097
098    public InverseBiMapGenerator(
099        OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>> oneSizeTestContainerGenerator) {
100      this.generator = oneSizeTestContainerGenerator;
101    }
102
103    @Override
104    public SampleElements<Entry<V, K>> samples() {
105      SampleElements<Entry<K, V>> samples = generator.samples();
106      return new SampleElements<>(
107          reverse(samples.e0()),
108          reverse(samples.e1()),
109          reverse(samples.e2()),
110          reverse(samples.e3()),
111          reverse(samples.e4()));
112    }
113
114    private Entry<V, K> reverse(Entry<K, V> entry) {
115      return Helpers.mapEntry(entry.getValue(), entry.getKey());
116    }
117
118    @SuppressWarnings("unchecked")
119    @Override
120    public BiMap<V, K> create(Object... elements) {
121      Entry<?, ?>[] entries = new Entry<?, ?>[elements.length];
122      for (int i = 0; i < elements.length; i++) {
123        entries[i] = reverse((Entry<K, V>) elements[i]);
124      }
125      return generator.create((Object[]) entries).inverse();
126    }
127
128    @SuppressWarnings("unchecked")
129    @Override
130    public Entry<V, K>[] createArray(int length) {
131      return (Entry<V, K>[]) new Entry<?, ?>[length];
132    }
133
134    @Override
135    public Iterable<Entry<V, K>> order(List<Entry<V, K>> insertionOrder) {
136      return insertionOrder;
137    }
138
139    @SuppressWarnings("unchecked")
140    @Override
141    public V[] createKeyArray(int length) {
142      return (V[]) new Object[length];
143    }
144
145    @SuppressWarnings("unchecked")
146    @Override
147    public K[] createValueArray(int length) {
148      return (K[]) new Object[length];
149    }
150
151    @Override
152    public TestSubjectGenerator<?> getInnerGenerator() {
153      return generator;
154    }
155  }
156
157  public static class BiMapValueSetGenerator<K extends @Nullable Object, V extends @Nullable Object>
158      implements TestSetGenerator<V>, DerivedGenerator {
159    private final OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>> mapGenerator;
160    private final SampleElements<V> samples;
161
162    public BiMapValueSetGenerator(
163        OneSizeTestContainerGenerator<BiMap<K, V>, Entry<K, V>> mapGenerator) {
164      this.mapGenerator = mapGenerator;
165      SampleElements<Entry<K, V>> mapSamples = this.mapGenerator.samples();
166      this.samples =
167          new SampleElements<>(
168              mapSamples.e0().getValue(),
169              mapSamples.e1().getValue(),
170              mapSamples.e2().getValue(),
171              mapSamples.e3().getValue(),
172              mapSamples.e4().getValue());
173    }
174
175    @Override
176    public SampleElements<V> samples() {
177      return samples;
178    }
179
180    @Override
181    public Set<V> create(Object... elements) {
182      @SuppressWarnings("unchecked")
183      V[] valuesArray = (V[]) elements;
184
185      // Start with a suitably shaped collection of entries
186      Collection<Entry<K, V>> originalEntries = mapGenerator.getSampleElements(elements.length);
187
188      // Create a copy of that, with the desired value for each value
189      Collection<Entry<K, V>> entries = new ArrayList<>(elements.length);
190      int i = 0;
191      for (Entry<K, V> entry : originalEntries) {
192        entries.add(Helpers.mapEntry(entry.getKey(), valuesArray[i++]));
193      }
194
195      return mapGenerator.create(entries.toArray()).values();
196    }
197
198    @Override
199    public V[] createArray(int length) {
200      V[] vs =
201          ((TestBiMapGenerator<K, V>) mapGenerator.getInnerGenerator()).createValueArray(length);
202      return vs;
203    }
204
205    @Override
206    public Iterable<V> order(List<V> insertionOrder) {
207      return insertionOrder;
208    }
209
210    @Override
211    public TestSubjectGenerator<?> getInnerGenerator() {
212      return mapGenerator;
213    }
214  }
215
216  private DerivedGoogleCollectionGenerators() {}
217}