ArbitraryInstances.java revision 7dd252788645e940eada959bdde927426e2531c9
1/*
2 * Copyright (C) 2012 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.testing;
18
19import static com.google.common.base.Preconditions.checkArgument;
20
21import com.google.common.annotations.Beta;
22import com.google.common.base.CharMatcher;
23import com.google.common.base.Charsets;
24import com.google.common.base.Defaults;
25import com.google.common.base.Equivalence;
26import com.google.common.base.Joiner;
27import com.google.common.base.Optional;
28import com.google.common.base.Predicate;
29import com.google.common.base.Predicates;
30import com.google.common.base.Splitter;
31import com.google.common.base.Ticker;
32import com.google.common.collect.BiMap;
33import com.google.common.collect.ClassToInstanceMap;
34import com.google.common.collect.Constraint;
35import com.google.common.collect.Constraints;
36import com.google.common.collect.ImmutableBiMap;
37import com.google.common.collect.ImmutableClassToInstanceMap;
38import com.google.common.collect.ImmutableCollection;
39import com.google.common.collect.ImmutableList;
40import com.google.common.collect.ImmutableListMultimap;
41import com.google.common.collect.ImmutableMap;
42import com.google.common.collect.ImmutableMultimap;
43import com.google.common.collect.ImmutableMultiset;
44import com.google.common.collect.ImmutableSet;
45import com.google.common.collect.ImmutableSetMultimap;
46import com.google.common.collect.ImmutableSortedMap;
47import com.google.common.collect.ImmutableSortedMultiset;
48import com.google.common.collect.ImmutableSortedSet;
49import com.google.common.collect.ImmutableTable;
50import com.google.common.collect.Iterators;
51import com.google.common.collect.ListMultimap;
52import com.google.common.collect.MapConstraint;
53import com.google.common.collect.MapConstraints;
54import com.google.common.collect.MapDifference;
55import com.google.common.collect.Maps;
56import com.google.common.collect.Multimap;
57import com.google.common.collect.Multimaps;
58import com.google.common.collect.Multiset;
59import com.google.common.collect.Ordering;
60import com.google.common.collect.PeekingIterator;
61import com.google.common.collect.Range;
62import com.google.common.collect.RowSortedTable;
63import com.google.common.collect.SetMultimap;
64import com.google.common.collect.SortedMapDifference;
65import com.google.common.collect.SortedMultiset;
66import com.google.common.collect.SortedSetMultimap;
67import com.google.common.collect.Table;
68import com.google.common.collect.Tables;
69import com.google.common.collect.TreeBasedTable;
70import com.google.common.collect.TreeMultimap;
71import com.google.common.primitives.Primitives;
72import com.google.common.primitives.UnsignedInteger;
73import com.google.common.primitives.UnsignedLong;
74
75import java.io.ByteArrayInputStream;
76import java.io.ByteArrayOutputStream;
77import java.io.File;
78import java.io.InputStream;
79import java.io.OutputStream;
80import java.io.PrintStream;
81import java.io.PrintWriter;
82import java.io.Reader;
83import java.io.Serializable;
84import java.io.StringReader;
85import java.io.StringWriter;
86import java.io.Writer;
87import java.lang.reflect.AnnotatedElement;
88import java.lang.reflect.Array;
89import java.lang.reflect.Constructor;
90import java.lang.reflect.GenericDeclaration;
91import java.lang.reflect.InvocationTargetException;
92import java.lang.reflect.Modifier;
93import java.lang.reflect.Type;
94import java.math.BigDecimal;
95import java.math.BigInteger;
96import java.nio.Buffer;
97import java.nio.ByteBuffer;
98import java.nio.CharBuffer;
99import java.nio.DoubleBuffer;
100import java.nio.FloatBuffer;
101import java.nio.IntBuffer;
102import java.nio.LongBuffer;
103import java.nio.ShortBuffer;
104import java.nio.charset.Charset;
105import java.util.Collection;
106import java.util.Comparator;
107import java.util.Currency;
108import java.util.Iterator;
109import java.util.List;
110import java.util.ListIterator;
111import java.util.Locale;
112import java.util.Map;
113import java.util.Random;
114import java.util.Set;
115import java.util.SortedMap;
116import java.util.SortedSet;
117import java.util.concurrent.BlockingQueue;
118import java.util.concurrent.ConcurrentHashMap;
119import java.util.concurrent.ConcurrentMap;
120import java.util.concurrent.CountDownLatch;
121import java.util.concurrent.Executor;
122import java.util.concurrent.LinkedBlockingQueue;
123import java.util.concurrent.ScheduledThreadPoolExecutor;
124import java.util.concurrent.ThreadFactory;
125import java.util.concurrent.ThreadPoolExecutor;
126import java.util.concurrent.TimeUnit;
127import java.util.logging.Level;
128import java.util.logging.Logger;
129import java.util.regex.MatchResult;
130import java.util.regex.Matcher;
131import java.util.regex.Pattern;
132
133import javax.annotation.Nullable;
134
135/**
136 * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
137 * utilities.
138 *
139 * <p>Covers common types defined in {@code java.lang}, {@code java.lang.reflect}, {@code java.io},
140 * {@code java.nio}, {@code java.math}, {@code java.util}, {@code java.util.concurrent},
141 * {@code java.util.regex}, {@code com.google.common.base}, {@code com.google.common.collect}
142 * and {@code com.google.common.primitives}. In addition, any public class that exposes a public
143 * parameter-less constructor will be "new"d and returned.
144 *
145 * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
146 * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
147 * Immutable empty instances are returned for collection types; {@code ""} for string;
148 * {@code 0} for number types; reasonable default instance for other stateless types. For mutable
149 * types, a fresh instance is created each time {@code get()} is called.
150 *
151 * @author Kevin Bourrillion
152 * @author Ben Yu
153 * @since 12.0
154 */
155@Beta
156public final class ArbitraryInstances {
157
158  /**
159   * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
160   * in Android) requires a successful match in order to generate a {@code MatchResult}:
161   * http://goo.gl/5VQFmC
162   */
163  private static MatchResult newMatchResult() {
164    Matcher matcher = Pattern.compile(".").matcher("X");
165    matcher.find();
166    return matcher.toMatchResult();
167  }
168
169  private static final ClassToInstanceMap<Object> DEFAULTS = ImmutableClassToInstanceMap.builder()
170      // primitives
171      .put(Object.class, "")
172      .put(Number.class, 0)
173      .put(UnsignedInteger.class, UnsignedInteger.ZERO)
174      .put(UnsignedLong.class, UnsignedLong.ZERO)
175      .put(BigInteger.class, BigInteger.ZERO)
176      .put(BigDecimal.class, BigDecimal.ZERO)
177      .put(CharSequence.class, "")
178      .put(String.class, "")
179      .put(Pattern.class, Pattern.compile(""))
180      .put(MatchResult.class, newMatchResult())
181      .put(TimeUnit.class, TimeUnit.SECONDS)
182      .put(Charset.class, Charsets.UTF_8)
183      .put(Currency.class, Currency.getInstance(Locale.US))
184      .put(Locale.class, Locale.US)
185      // common.base
186      .put(CharMatcher.class, CharMatcher.NONE)
187      .put(Joiner.class, Joiner.on(','))
188      .put(Splitter.class, Splitter.on(','))
189      .put(Optional.class, Optional.absent())
190      .put(Predicate.class, Predicates.alwaysTrue())
191      .put(Equivalence.class, Equivalence.equals())
192      .put(Ticker.class, Ticker.systemTicker())
193      // io types
194      .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
195      .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
196      .put(Readable.class, new StringReader(""))
197      .put(Reader.class, new StringReader(""))
198      .put(StringReader.class, new StringReader(""))
199      .put(Buffer.class, ByteBuffer.allocate(0))
200      .put(CharBuffer.class, CharBuffer.allocate(0))
201      .put(ByteBuffer.class, ByteBuffer.allocate(0))
202      .put(ShortBuffer.class, ShortBuffer.allocate(0))
203      .put(IntBuffer.class, IntBuffer.allocate(0))
204      .put(LongBuffer.class, LongBuffer.allocate(0))
205      .put(FloatBuffer.class, FloatBuffer.allocate(0))
206      .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
207      .put(File.class, new File(""))
208      // All collections are immutable empty. So safe for any type parameter.
209      .put(Iterator.class, Iterators.emptyIterator())
210      .put(PeekingIterator.class, Iterators.peekingIterator(Iterators.emptyIterator()))
211      .put(ListIterator.class, ImmutableList.of().listIterator())
212      .put(Iterable.class, ImmutableSet.of())
213      .put(Collection.class, ImmutableList.of())
214      .put(ImmutableCollection.class, ImmutableList.of())
215      .put(List.class, ImmutableList.of())
216      .put(ImmutableList.class, ImmutableList.of())
217      .put(Set.class, ImmutableSet.of())
218      .put(ImmutableSet.class, ImmutableSet.of())
219      .put(SortedSet.class, ImmutableSortedSet.of())
220      .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
221      .put(Map.class, ImmutableMap.of())
222      .put(ImmutableMap.class, ImmutableMap.of())
223      .put(SortedMap.class, ImmutableSortedMap.of())
224      .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
225      .put(Multimap.class, ImmutableMultimap.of())
226      .put(ImmutableMultimap.class, ImmutableMultimap.of())
227      .put(ListMultimap.class, ImmutableListMultimap.of())
228      .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
229      .put(SetMultimap.class, ImmutableSetMultimap.of())
230      .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
231      .put(SortedSetMultimap.class, Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
232      .put(Multiset.class, ImmutableMultiset.of())
233      .put(ImmutableMultiset.class, ImmutableMultiset.of())
234      .put(SortedMultiset.class, ImmutableSortedMultiset.of())
235      .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
236      .put(BiMap.class, ImmutableBiMap.of())
237      .put(ImmutableBiMap.class, ImmutableBiMap.of())
238      .put(Table.class, ImmutableTable.of())
239      .put(ImmutableTable.class, ImmutableTable.of())
240      .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
241      .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
242      .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
243      .put(Comparable.class, ByToString.INSTANCE)
244      .put(Comparator.class, AlwaysEqual.INSTANCE)
245      .put(Ordering.class, AlwaysEqual.INSTANCE)
246      .put(Range.class, Range.all())
247      .put(Constraint.class, Constraints.notNull())
248      .put(MapConstraint.class, MapConstraints.notNull())
249      .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
250      .put(SortedMapDifference.class,
251          Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
252      // reflect
253      .put(AnnotatedElement.class, Object.class)
254      .put(GenericDeclaration.class, Object.class)
255      .put(Type.class, Object.class)
256      .build();
257
258  /**
259   * type -> implementation. Inherently mutable interfaces and abstract classes are mapped to their
260   * default implementations and are "new"d upon get().
261   */
262  private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
263
264  private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
265    checkArgument(type != implementation, "Don't register %s to itself!", type);
266    checkArgument(!DEFAULTS.containsKey(type),
267        "A default value was already registered for %s", type);
268    checkArgument(implementations.put(type, implementation) == null,
269        "Implementation for %s was already registered", type);
270  }
271
272  static {
273    setImplementation(Appendable.class, StringBuilder.class);
274    setImplementation(BlockingQueue.class, LinkedBlockingQueue.class);
275    setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
276    setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
277    setImplementation(OutputStream.class, ByteArrayOutputStream.class);
278    setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
279    setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
280    setImplementation(Random.class, Dummies.DeterministicRandom.class);
281    setImplementation(ScheduledThreadPoolExecutor.class,
282        Dummies.DummyScheduledThreadPoolExecutor.class);
283    setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
284    setImplementation(Writer.class, StringWriter.class);
285    setImplementation(Runnable.class, Dummies.DummyRunnable.class);
286    setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
287    setImplementation(Executor.class, Dummies.DummyExecutor.class);
288  }
289
290  @SuppressWarnings("unchecked") // it's a subtype map
291  @Nullable
292  private static <T> Class<? extends T> getImplementation(Class<T> type) {
293    return (Class<? extends T>) implementations.get(type);
294  }
295
296  private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
297
298  /**
299   * Returns an arbitrary value for {@code type} as the null value, or {@code null} if empty-ness is
300   * unknown for the type.
301   */
302  @Nullable public static <T> T get(Class<T> type) {
303    T defaultValue = DEFAULTS.getInstance(type);
304    if (defaultValue != null) {
305      return defaultValue;
306    }
307    Class<? extends T> implementation = getImplementation(type);
308    if (implementation != null) {
309      return get(implementation);
310    }
311    if (type.isEnum()) {
312      T[] enumConstants = type.getEnumConstants();
313      return (enumConstants.length == 0)
314          ? null
315          : enumConstants[0];
316    }
317    if (type.isArray()) {
318      return createEmptyArray(type);
319    }
320    T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
321    if (jvmDefault != null) {
322      return jvmDefault;
323    }
324    if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
325      return null;
326    }
327    final Constructor<T> constructor;
328    try {
329      constructor = type.getConstructor();
330    } catch (NoSuchMethodException e) {
331      return null;
332    }
333    constructor.setAccessible(true); // accessibility check is too slow
334    try {
335      return constructor.newInstance();
336    } catch (InstantiationException impossible) {
337      throw new AssertionError(impossible);
338    } catch (IllegalAccessException impossible) {
339      throw new AssertionError(impossible);
340    } catch (InvocationTargetException e) {
341      logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
342      return null;
343    }
344  }
345
346  @SuppressWarnings("unchecked") // same component type means same array type
347  private static <T> T createEmptyArray(Class<T> arrayType) {
348    return (T) Array.newInstance(arrayType.getComponentType(), 0);
349  }
350
351  // Internal implementations of some classes, with public default constructor that get() needs.
352  private static final class Dummies {
353
354    public static final class InMemoryPrintStream extends PrintStream {
355      public InMemoryPrintStream() {
356        super(new ByteArrayOutputStream());
357      }
358    }
359
360    public static final class InMemoryPrintWriter extends PrintWriter {
361      public InMemoryPrintWriter() {
362        super(new StringWriter());
363      }
364    }
365
366    public static final class DeterministicRandom extends Random {
367      @SuppressWarnings("unused") // invoked by reflection
368      public DeterministicRandom() {
369        super(0);
370      }
371    }
372
373    public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
374      public DummyScheduledThreadPoolExecutor() {
375        super(1);
376      }
377    }
378
379    public static final class DummyCountDownLatch extends CountDownLatch {
380      public DummyCountDownLatch() {
381        super(0);
382      }
383    }
384
385    public static final class DummyRunnable implements Runnable, Serializable {
386      @Override public void run() {}
387    }
388
389    public static final class DummyThreadFactory implements ThreadFactory, Serializable {
390      @Override public Thread newThread(Runnable r) {
391        return new Thread(r);
392      }
393    }
394
395    public static final class DummyExecutor implements Executor, Serializable {
396      @Override public void execute(Runnable command) {}
397    }
398  }
399
400  // Compare by toString() to satisfy 2 properties:
401  // 1. compareTo(null) should throw NullPointerException
402  // 2. the order is deterministic and easy to understand, for debugging purpose.
403  private static final class ByToString implements Comparable<Object>, Serializable {
404    private static final ByToString INSTANCE = new ByToString();
405
406    @Override public int compareTo(Object o) {
407      return toString().compareTo(o.toString());
408    }
409
410    @Override public String toString() {
411      return "BY_TO_STRING";
412    }
413
414    private Object readResolve() {
415      return INSTANCE;
416    }
417  }
418
419  // Always equal is a valid total ordering. And it works for any Object.
420  private static final class AlwaysEqual extends Ordering<Object> implements Serializable {
421    private static final AlwaysEqual INSTANCE = new AlwaysEqual();
422
423    @Override public int compare(Object o1, Object o2) {
424      return 0;
425    }
426
427    @Override public String toString() {
428      return "ALWAYS_EQUAL";
429    }
430
431    private Object readResolve() {
432      return INSTANCE;
433    }
434  }
435
436  private ArbitraryInstances() {}
437}
438