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