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